blackfoundry-pcap 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +145 -0
- data/README +48 -0
- data/README.ja +50 -0
- data/Rakefile +23 -0
- data/ext/Pcap.c +798 -0
- data/ext/extconf.rb +16 -0
- data/ext/icmp_packet.c +444 -0
- data/ext/ip_packet.c +342 -0
- data/ext/packet.c +310 -0
- data/ext/ruby_pcap.h +133 -0
- data/ext/tcp_packet.c +121 -0
- data/ext/udp_packet.c +96 -0
- data/lib/pcap_misc.rb +116 -0
- data/lib/pcaplet.rb +113 -0
- metadata +79 -0
data/ChangeLog
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
2000-08-13 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
2
|
+
|
3
|
+
* version 0.6 released.
|
4
|
+
|
5
|
+
* packet.c (packet_match): Packet#=~ added.
|
6
|
+
|
7
|
+
* Pcap.c (capture_setfilter): Filter object can be used in
|
8
|
+
Capture#setfilter.
|
9
|
+
|
10
|
+
* lib/pcaplet.rb: invoke gzip when reading /\.gz$/ file.
|
11
|
+
Pcaplet.new accept options.
|
12
|
+
|
13
|
+
* Pcap.c: implement Filter logical operation.
|
14
|
+
(filter_source): Filter#source added.
|
15
|
+
|
16
|
+
2000-08-09 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
17
|
+
|
18
|
+
* Pcap.c (filter_new): use pcap_compile_nopcap() if available.
|
19
|
+
|
20
|
+
1999-11-08 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
21
|
+
|
22
|
+
* version 0.5 released.
|
23
|
+
|
24
|
+
* Pcap.c: Call Check_SafeStr() before I/O operation.
|
25
|
+
|
26
|
+
* lib/pcaplet.rb: Use getopts instead of parseparg.
|
27
|
+
|
28
|
+
1999-11-05 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
29
|
+
|
30
|
+
* Filter document added.
|
31
|
+
|
32
|
+
1999-11-04 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
33
|
+
|
34
|
+
* Pcap.c (filter_match): datalink and caplen check.
|
35
|
+
|
36
|
+
1999-10-30 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
37
|
+
|
38
|
+
* Pcap.c (Init_pcap): added Pcap.{lookupdev,lookupnet}.
|
39
|
+
|
40
|
+
1999-10-29 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
41
|
+
|
42
|
+
* Pcap.c: use RTEST instead of Qtrue/Qfalse test.
|
43
|
+
|
44
|
+
1999-08-27 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
45
|
+
|
46
|
+
* ip_packet.c (ipaddr_s_new): changed to use gethostbyname().
|
47
|
+
|
48
|
+
* icmp_packet.c: icmp_type_info lacks type 31-36 hole.
|
49
|
+
|
50
|
+
1999-08-26 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
51
|
+
|
52
|
+
* version 0.4 released.
|
53
|
+
|
54
|
+
* ICMPPacket document added.
|
55
|
+
|
56
|
+
1999-08-25 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
57
|
+
|
58
|
+
* udp_packet.c: UdpPacket renamed to UDPPacket.
|
59
|
+
|
60
|
+
* tcp_packet.c: TcpPacket renamed to TCPPacket.
|
61
|
+
|
62
|
+
* ip_packet.c: IpPacket renamed to IPPacket.
|
63
|
+
|
64
|
+
1999-08-24 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
65
|
+
|
66
|
+
* icmp_packet.c: ICMP support.
|
67
|
+
|
68
|
+
1999-08-18 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
69
|
+
|
70
|
+
* Pcap.c (Init_pcap): PcapStat is now defined as Pcap::Stat.
|
71
|
+
|
72
|
+
1999-08-17 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
73
|
+
|
74
|
+
* ip_packet.c (setup_ip_packet): check ip_v == 4
|
75
|
+
|
76
|
+
1999-08-14 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
77
|
+
|
78
|
+
* ip_packet.c (setup_ip_packet): ntohs must be used for ip_len.
|
79
|
+
|
80
|
+
* packet.c (Init_packet): Packet#udp? added.
|
81
|
+
|
82
|
+
1999-07-23 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
83
|
+
|
84
|
+
* extconf.rb: --with-pcap-prefix is changed to --with-pcap-dir
|
85
|
+
|
86
|
+
1999-07-14 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
87
|
+
|
88
|
+
* ip_packet.c (Init_ip_packet): IP address is now represented by
|
89
|
+
new class IPAddress implemented in C. IpAddress is obsolete but
|
90
|
+
remains for backward compatibility.
|
91
|
+
|
92
|
+
1999-07-11 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
93
|
+
|
94
|
+
* Pcap.c (Init_pcap): Capture includes Enumerable.
|
95
|
+
|
96
|
+
1999-07-02 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
97
|
+
|
98
|
+
* version 0.3.1 released.
|
99
|
+
|
100
|
+
* Pcap.c: Filter class is added.
|
101
|
+
|
102
|
+
* tcp_packet.c (tcpp_data): data length bug is fixed.
|
103
|
+
|
104
|
+
1999-06-27 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
105
|
+
|
106
|
+
* Pcap.c (capture_loop): improved to be thread-friendly.
|
107
|
+
|
108
|
+
1999-05-24 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
109
|
+
|
110
|
+
* version 0.3 released.
|
111
|
+
|
112
|
+
* extconf.rb: --with-pcap-prefix option added.
|
113
|
+
|
114
|
+
* changed to based on ruby-1.3.x.
|
115
|
+
|
116
|
+
1999-04-20 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
117
|
+
|
118
|
+
* version 0.2 released.
|
119
|
+
|
120
|
+
1999-04-18 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
121
|
+
|
122
|
+
* UdpPacket documentation added.
|
123
|
+
|
124
|
+
1999-02-08 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
125
|
+
|
126
|
+
* udp_packet.c: UDP supprot added.
|
127
|
+
|
128
|
+
1998-12-07 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
129
|
+
|
130
|
+
* version 0.1.1 released.
|
131
|
+
|
132
|
+
* Document about exception classes added.
|
133
|
+
|
134
|
+
* Pcap.c (CheckClass): CheckClass added.
|
135
|
+
(dumper_dump): check data-link type and caplen.
|
136
|
+
|
137
|
+
1998-12-06 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
138
|
+
|
139
|
+
* packet.c: Packet#datalink added.
|
140
|
+
|
141
|
+
* English document added.
|
142
|
+
|
143
|
+
1998-12-01 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
144
|
+
|
145
|
+
* version 0.1 released.
|
data/README
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
* Introduction
|
2
|
+
|
3
|
+
ruby-pcap is a ruby extension to LBL libpcap (Packet Capture library).
|
4
|
+
This library also includes classes to access TCP/IP header.
|
5
|
+
|
6
|
+
* Installation
|
7
|
+
|
8
|
+
Requirements:
|
9
|
+
|
10
|
+
- ruby-1.4.x
|
11
|
+
- libpcap (http://www.tcpdump.org/)
|
12
|
+
|
13
|
+
Compile:
|
14
|
+
|
15
|
+
If ruby supports dynamic link of extension module on your OS,
|
16
|
+
following commands will install ruby-pcap.
|
17
|
+
|
18
|
+
ruby extconf.rb [options]
|
19
|
+
make
|
20
|
+
make install
|
21
|
+
|
22
|
+
You can specify options when you run 'ruby extconf.rb':
|
23
|
+
|
24
|
+
`--with-pcap-dir=PREFIX'
|
25
|
+
Directory where libpcap is installed. Default is '/usr/local'.
|
26
|
+
|
27
|
+
If dynamic link isn't available, you can link ruby-pcap statically
|
28
|
+
with ruby. Extract ruby-pcap under the directory 'ext' in ruby source
|
29
|
+
tree, then build ruby.
|
30
|
+
|
31
|
+
* Usage
|
32
|
+
|
33
|
+
See the documentation under the directory 'doc'.
|
34
|
+
Directory 'examples' contains some simple scripts.
|
35
|
+
|
36
|
+
* Author
|
37
|
+
|
38
|
+
Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
39
|
+
|
40
|
+
ruby-pcap is copyrighted free software by Masaki Fukushima.
|
41
|
+
|
42
|
+
You can redistribute it and/or modify it under the terms of
|
43
|
+
the GPL (GNU GENERAL PUBLIC LICENSE). See COPYING file about GPL.
|
44
|
+
|
45
|
+
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
46
|
+
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
47
|
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. See the GPL for
|
48
|
+
more details.
|
data/README.ja
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
* $B35MW(B
|
2
|
+
|
3
|
+
ruby-pcap $B$O(B Ruby $B$+$i(B LBL $B$N(B libpcap (Packet Capture library) $B$X%"%/(B
|
4
|
+
$B%;%9$9$k$?$a$N3HD%%i%$%V%i%j$G$9!#(BTCP/IP$B$N%X%C%@$N>pJs$K%"%/%;%9$9$k$?(B
|
5
|
+
$B$a$N%/%i%9$b4^$s$G$$$^$9!#(B
|
6
|
+
|
7
|
+
* $B%$%s%9%H!<%k(B
|
8
|
+
|
9
|
+
$BI,MW$J$b$N(B:
|
10
|
+
|
11
|
+
- ruby-1.4.x
|
12
|
+
- libpcap (http://www.tcpdump.org/)
|
13
|
+
|
14
|
+
$B%3%s%Q%$%k(B:
|
15
|
+
|
16
|
+
ruby $B$,3HD%%i%$%V%i%j$N%@%$%J%_%C%/%j%s%/$r%5%]!<%H$7$F$$$k>l9g$O!"(B
|
17
|
+
$B0J2<$N<j=g$G%$%s%9%H!<%k$G$-$^$9!#(B
|
18
|
+
|
19
|
+
ruby extconf.rb [options]
|
20
|
+
make
|
21
|
+
make install
|
22
|
+
|
23
|
+
'ruby extconf.rb'$B$r<B9T$9$k;~$K$O0J2<$N%*%W%7%g%s$r;XDj$G$-$^$9!#(B
|
24
|
+
|
25
|
+
`--with-pcap-dir=PREFIX'
|
26
|
+
libpcap$B$,%$%s%9%H!<%k$5$l$F$$$k%G%#%l%/%H%j$r;XDj$7$^$9!#(B
|
27
|
+
$B%G%U%)%k%H$O(B'/usr/local'$B$G$9!#(B
|
28
|
+
|
29
|
+
$B%@%$%J%_%C%/%j%s%/$,;H$($J$$>l9g$O(B ruby $B$K@EE*$K%j%s%/$7$F2<$5$$!#(B
|
30
|
+
$B$=$N>l9g$O(B ruby $B%=!<%9Cf$N(B 'ext' $B%G%#%l%/%H%j$N2<$G(B ruby-pcap $B$rE83+$7(B
|
31
|
+
$B$F$+$i(B ruby $B$r%S%k%I$7$F2<$5$$!#(B
|
32
|
+
|
33
|
+
* $B;H$$J}(B
|
34
|
+
|
35
|
+
doc $B$*$h$S(B doc-ja $B%G%#%l%/%H%j0J2<$K$"$k%U%!%$%k$r8+$F2<$5$$!#(B
|
36
|
+
examples $B%G%#%l%/%H%j$K4JC1$J%5%s%W%k%9%/%j%W%H$,$"$j$^$9!#(B
|
37
|
+
|
38
|
+
* $B:n<T(B
|
39
|
+
|
40
|
+
$BJ!Eh@55!(B <fukusima@goto.info.waseda.ac.jp>
|
41
|
+
|
42
|
+
ruby-pcap$B$OJ!Eh@55!$,Cx:n8"$rJ];}$9$k(B free software $B$G$9!#(B
|
43
|
+
|
44
|
+
ruby-pcap$B$O(BGPL(GNU GENERAL PUBLIC LICENSE)$B$K=>$C$F:FG[I[$^$?$O(B
|
45
|
+
$BJQ99$9$k$3$H$,$G$-$^$9!#(BGPL$B$K$D$$$F$O(BCOPYING$B%U%!%$%k$r;2>H$7$F(B
|
46
|
+
$B$/$@$5$$!#(B
|
47
|
+
|
48
|
+
ruby-pcap$B$OL5J]>Z$G$9!#:n<T$O(Bruby-pcap$B$N%P%0$J$I$+$iH/@8$9$k(B
|
49
|
+
$B$$$+$J$kB;32$KBP$7$F$b@UG$$r;}$A$^$;$s!#>\:Y$K$D$$$F$O(B GPL $B$r(B
|
50
|
+
$B;2>H$7$F$/$@$5$$!#(B
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
task :default => [:make]
|
4
|
+
|
5
|
+
task :make do
|
6
|
+
puts `ruby extconf.rb`
|
7
|
+
puts `make`
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'jeweler'
|
11
|
+
Jeweler::Tasks.new do |s|
|
12
|
+
s.version = '0.1'
|
13
|
+
s.name = 'blackfoundry-pcap'
|
14
|
+
s.summary = 'extensions to ruby-pcap'
|
15
|
+
s.email = 'david@blackfoundry.com'
|
16
|
+
s.description =<<-eod
|
17
|
+
Some extensions to the pcap library.
|
18
|
+
eod
|
19
|
+
s.executables = []
|
20
|
+
s.authors = ['David Turnbull']
|
21
|
+
s.files = ['Rakefile', 'lib'] + Dir['ext/**'] + Dir['lib/**']
|
22
|
+
end
|
23
|
+
|
data/ext/Pcap.c
ADDED
@@ -0,0 +1,798 @@
|
|
1
|
+
/*
|
2
|
+
* Pcap.c
|
3
|
+
*
|
4
|
+
* $Id: Pcap.c,v 1.10 2000/08/13 05:56:31 fukusima Exp $
|
5
|
+
*
|
6
|
+
* Copyright (C) 1998-2000 Masaki Fukushima
|
7
|
+
*/
|
8
|
+
|
9
|
+
#include "ruby_pcap.h"
|
10
|
+
#include "rubysig.h"
|
11
|
+
#include <sys/time.h>
|
12
|
+
#include <sys/types.h>
|
13
|
+
#include <unistd.h>
|
14
|
+
|
15
|
+
#define DEFAULT_DATALINK DLT_EN10MB
|
16
|
+
#define DEFAULT_SNAPLEN 68
|
17
|
+
#define DEFAULT_PROMISC 1
|
18
|
+
#define DEFAULT_TO_MS 1000
|
19
|
+
static char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
20
|
+
|
21
|
+
VALUE mPcap, rbpcap_convert = Qnil;
|
22
|
+
VALUE ePcapError;
|
23
|
+
VALUE eTruncatedPacket;
|
24
|
+
VALUE cFilter;
|
25
|
+
static VALUE cCapture;
|
26
|
+
static VALUE cPcapStat;
|
27
|
+
static VALUE cDumper;
|
28
|
+
|
29
|
+
struct filter_object {
|
30
|
+
char *expr;
|
31
|
+
struct bpf_program program;
|
32
|
+
int datalink;
|
33
|
+
int snaplen;
|
34
|
+
VALUE param;
|
35
|
+
VALUE optimize;
|
36
|
+
VALUE netmask;
|
37
|
+
};
|
38
|
+
|
39
|
+
#define GetFilter(obj, filter) \
|
40
|
+
Data_Get_Struct(obj, struct filter_object, filter)
|
41
|
+
|
42
|
+
|
43
|
+
static VALUE
|
44
|
+
pcap_s_lookupdev(self)
|
45
|
+
VALUE self;
|
46
|
+
{
|
47
|
+
char *dev;
|
48
|
+
|
49
|
+
dev = pcap_lookupdev(pcap_errbuf);
|
50
|
+
if (dev == NULL) {
|
51
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
52
|
+
}
|
53
|
+
return rb_str_new2(dev);
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE
|
57
|
+
pcap_s_lookupnet(self, dev)
|
58
|
+
VALUE self;
|
59
|
+
VALUE dev;
|
60
|
+
{
|
61
|
+
bpf_u_int32 net, mask, m;
|
62
|
+
struct in_addr addr;
|
63
|
+
|
64
|
+
Check_Type(dev, T_STRING);
|
65
|
+
if (pcap_lookupnet(STR2CSTR(dev), &net, &mask, pcap_errbuf) == -1) {
|
66
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
67
|
+
}
|
68
|
+
|
69
|
+
addr.s_addr = net;
|
70
|
+
m = ntohl(mask);
|
71
|
+
return rb_ary_new3(2, new_ipaddr(&addr), UINT32_2_NUM(m));
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE
|
75
|
+
pcap_s_convert(self)
|
76
|
+
VALUE self;
|
77
|
+
{
|
78
|
+
return rbpcap_convert;
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE
|
82
|
+
pcap_s_convert_set(self, val)
|
83
|
+
VALUE self;
|
84
|
+
{
|
85
|
+
rbpcap_convert = val;
|
86
|
+
return Qnil;
|
87
|
+
}
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Capture object
|
91
|
+
*/
|
92
|
+
|
93
|
+
struct capture_object {
|
94
|
+
pcap_t *pcap;
|
95
|
+
bpf_u_int32 netmask;
|
96
|
+
int dl_type; /* data-link type (DLT_*) */
|
97
|
+
};
|
98
|
+
|
99
|
+
static void
|
100
|
+
closed_capture()
|
101
|
+
{
|
102
|
+
rb_raise(rb_eRuntimeError, "device is already closed");
|
103
|
+
}
|
104
|
+
|
105
|
+
#define GetCapture(obj, cap) {\
|
106
|
+
Data_Get_Struct(obj, struct capture_object, cap);\
|
107
|
+
if (cap->pcap == NULL) closed_capture();\
|
108
|
+
}
|
109
|
+
|
110
|
+
/* called from GC */
|
111
|
+
static void
|
112
|
+
free_capture(cap)
|
113
|
+
struct capture_object *cap;
|
114
|
+
{
|
115
|
+
DEBUG_PRINT("free_capture");
|
116
|
+
if (cap->pcap != NULL) {
|
117
|
+
DEBUG_PRINT("closing capture");
|
118
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
119
|
+
pcap_close(cap->pcap);
|
120
|
+
cap->pcap = NULL;
|
121
|
+
}
|
122
|
+
free(cap);
|
123
|
+
}
|
124
|
+
|
125
|
+
static VALUE
|
126
|
+
capture_open_live(argc, argv, class)
|
127
|
+
int argc;
|
128
|
+
VALUE *argv;
|
129
|
+
VALUE class;
|
130
|
+
{
|
131
|
+
VALUE v_device, v_snaplen, v_promisc, v_to_ms;
|
132
|
+
char *device;
|
133
|
+
int snaplen, promisc, to_ms;
|
134
|
+
int rs;
|
135
|
+
VALUE self;
|
136
|
+
struct capture_object *cap;
|
137
|
+
pcap_t *pcap;
|
138
|
+
bpf_u_int32 net, netmask;
|
139
|
+
|
140
|
+
DEBUG_PRINT("capture_open_live");
|
141
|
+
|
142
|
+
/* scan arg */
|
143
|
+
rs = rb_scan_args(argc, argv, "13", &v_device, &v_snaplen,
|
144
|
+
&v_promisc, &v_to_ms);
|
145
|
+
|
146
|
+
/* device */
|
147
|
+
Check_SafeStr(v_device);
|
148
|
+
device = RSTRING(v_device)->ptr;
|
149
|
+
/* snaplen */
|
150
|
+
if (rs >= 2) {
|
151
|
+
Check_Type(v_snaplen, T_FIXNUM);
|
152
|
+
snaplen = FIX2INT(v_snaplen);
|
153
|
+
} else {
|
154
|
+
snaplen = DEFAULT_SNAPLEN;
|
155
|
+
}
|
156
|
+
if (snaplen < 0)
|
157
|
+
rb_raise(rb_eArgError, "invalid snaplen");
|
158
|
+
/* promisc */
|
159
|
+
if (rs >= 3) {
|
160
|
+
promisc = RTEST(v_promisc);
|
161
|
+
} else {
|
162
|
+
promisc = DEFAULT_PROMISC;
|
163
|
+
}
|
164
|
+
/* to_ms */
|
165
|
+
if (rs >= 4) {
|
166
|
+
Check_Type(v_to_ms, T_FIXNUM);
|
167
|
+
to_ms = FIX2INT(v_to_ms);
|
168
|
+
} else
|
169
|
+
to_ms = DEFAULT_TO_MS;
|
170
|
+
|
171
|
+
/* open */
|
172
|
+
pcap = pcap_open_live(device, snaplen, promisc, to_ms, pcap_errbuf);
|
173
|
+
if (pcap == NULL) {
|
174
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
175
|
+
}
|
176
|
+
if (pcap_lookupnet(device, &net, &netmask, pcap_errbuf) == -1) {
|
177
|
+
netmask = 0;
|
178
|
+
rb_warning("cannot lookup net: %s\n", pcap_errbuf);
|
179
|
+
}
|
180
|
+
|
181
|
+
/* setup instance */
|
182
|
+
self = Data_Make_Struct(class, struct capture_object,
|
183
|
+
0, free_capture, cap);
|
184
|
+
cap->pcap = pcap;
|
185
|
+
cap->netmask = netmask;
|
186
|
+
cap->dl_type = pcap_datalink(pcap);
|
187
|
+
|
188
|
+
return self;
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE
|
192
|
+
capture_open_offline(class, fname)
|
193
|
+
VALUE class;
|
194
|
+
VALUE fname;
|
195
|
+
{
|
196
|
+
VALUE self;
|
197
|
+
struct capture_object *cap;
|
198
|
+
pcap_t *pcap;
|
199
|
+
|
200
|
+
DEBUG_PRINT("capture_open_offline");
|
201
|
+
|
202
|
+
/* open offline */
|
203
|
+
Check_SafeStr(fname);
|
204
|
+
pcap = pcap_open_offline(RSTRING(fname)->ptr, pcap_errbuf);
|
205
|
+
if (pcap == NULL) {
|
206
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
207
|
+
}
|
208
|
+
|
209
|
+
/* setup instance */
|
210
|
+
self = Data_Make_Struct(class, struct capture_object,
|
211
|
+
0, free_capture, cap);
|
212
|
+
cap->pcap = pcap;
|
213
|
+
cap->netmask = 0;
|
214
|
+
cap->dl_type = pcap_datalink(pcap);
|
215
|
+
|
216
|
+
return self;
|
217
|
+
}
|
218
|
+
|
219
|
+
static VALUE
|
220
|
+
capture_close(self)
|
221
|
+
VALUE self;
|
222
|
+
{
|
223
|
+
struct capture_object *cap;
|
224
|
+
|
225
|
+
DEBUG_PRINT("capture_close");
|
226
|
+
GetCapture(self, cap);
|
227
|
+
|
228
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
229
|
+
pcap_close(cap->pcap);
|
230
|
+
cap->pcap = NULL;
|
231
|
+
return Qnil;
|
232
|
+
}
|
233
|
+
|
234
|
+
static void
|
235
|
+
handler(cap, pkthdr, data)
|
236
|
+
struct capture_object *cap;
|
237
|
+
const struct pcap_pkthdr *pkthdr;
|
238
|
+
const u_char *data;
|
239
|
+
{
|
240
|
+
size_t offset = ftell(pcap_file(cap->pcap)) - pkthdr->caplen;
|
241
|
+
VALUE pkt = new_packet(data, pkthdr, cap->dl_type);
|
242
|
+
rb_yield_values(2, LONG2NUM(offset), pkt);
|
243
|
+
}
|
244
|
+
|
245
|
+
static VALUE
|
246
|
+
capture_dispatch(argc, argv, self)
|
247
|
+
int argc;
|
248
|
+
VALUE *argv;
|
249
|
+
VALUE self;
|
250
|
+
{
|
251
|
+
VALUE v_cnt;
|
252
|
+
int cnt;
|
253
|
+
struct capture_object *cap;
|
254
|
+
int ret;
|
255
|
+
|
256
|
+
DEBUG_PRINT("capture_dispatch");
|
257
|
+
GetCapture(self, cap);
|
258
|
+
|
259
|
+
|
260
|
+
/* scan arg */
|
261
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
262
|
+
FIXNUM_P(v_cnt);
|
263
|
+
cnt = FIX2INT(v_cnt);
|
264
|
+
} else
|
265
|
+
cnt = -1;
|
266
|
+
|
267
|
+
TRAP_BEG;
|
268
|
+
ret = pcap_dispatch(cap->pcap, cnt, handler, (u_char *)cap);
|
269
|
+
TRAP_END;
|
270
|
+
if (ret == -1)
|
271
|
+
rb_raise(ePcapError, "dispatch: %s", pcap_geterr(cap->pcap));
|
272
|
+
|
273
|
+
return INT2FIX(ret);
|
274
|
+
}
|
275
|
+
|
276
|
+
int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); /* pcap-int.h */
|
277
|
+
|
278
|
+
static VALUE
|
279
|
+
capture_loop(argc, argv, self)
|
280
|
+
int argc;
|
281
|
+
VALUE *argv;
|
282
|
+
VALUE self;
|
283
|
+
{
|
284
|
+
VALUE v_cnt;
|
285
|
+
int cnt;
|
286
|
+
struct capture_object *cap;
|
287
|
+
int ret;
|
288
|
+
|
289
|
+
DEBUG_PRINT("capture_loop");
|
290
|
+
GetCapture(self, cap);
|
291
|
+
|
292
|
+
|
293
|
+
/* scan arg */
|
294
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
295
|
+
FIXNUM_P(v_cnt);
|
296
|
+
cnt = FIX2INT(v_cnt);
|
297
|
+
} else
|
298
|
+
cnt = -1;
|
299
|
+
|
300
|
+
#if 0
|
301
|
+
TRAP_BEG;
|
302
|
+
ret = pcap_loop(cap->pcap, cnt, handler, (u_char *)cap);
|
303
|
+
TRAP_END;
|
304
|
+
#else
|
305
|
+
if (pcap_file(cap->pcap) != NULL) {
|
306
|
+
TRAP_BEG;
|
307
|
+
ret = pcap_loop(cap->pcap, cnt, handler, (u_char *)cap);
|
308
|
+
TRAP_END;
|
309
|
+
} else {
|
310
|
+
int fd = pcap_fileno(cap->pcap);
|
311
|
+
fd_set rset;
|
312
|
+
struct timeval tm;
|
313
|
+
|
314
|
+
FD_ZERO(&rset);
|
315
|
+
tm.tv_sec = 0;
|
316
|
+
tm.tv_usec = 0;
|
317
|
+
for (;;) {
|
318
|
+
do {
|
319
|
+
FD_SET(fd, &rset);
|
320
|
+
if (select(fd+1, &rset, NULL, NULL, &tm) == 0) {
|
321
|
+
rb_thread_wait_fd(fd);
|
322
|
+
}
|
323
|
+
TRAP_BEG;
|
324
|
+
ret = pcap_read(cap->pcap, 1, handler, (u_char *)cap);
|
325
|
+
TRAP_END;
|
326
|
+
} while (ret == 0);
|
327
|
+
if (ret <= 0)
|
328
|
+
break;
|
329
|
+
if (cnt > 0) {
|
330
|
+
cnt -= ret;
|
331
|
+
if (cnt <= 0)
|
332
|
+
break;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
}
|
336
|
+
#endif
|
337
|
+
return INT2FIX(ret);
|
338
|
+
}
|
339
|
+
|
340
|
+
static VALUE
|
341
|
+
capture_setfilter(argc, argv, self)
|
342
|
+
int argc;
|
343
|
+
VALUE *argv;
|
344
|
+
VALUE self;
|
345
|
+
{
|
346
|
+
struct capture_object *cap;
|
347
|
+
VALUE vfilter, optimize;
|
348
|
+
char *filter;
|
349
|
+
int opt;
|
350
|
+
struct bpf_program program;
|
351
|
+
|
352
|
+
DEBUG_PRINT("capture_setfilter");
|
353
|
+
GetCapture(self, cap);
|
354
|
+
|
355
|
+
/* scan arg */
|
356
|
+
if (rb_scan_args(argc, argv, "11", &vfilter, &optimize) == 1) {
|
357
|
+
optimize = Qtrue;
|
358
|
+
}
|
359
|
+
|
360
|
+
/* check arg */
|
361
|
+
if (IsKindOf(vfilter, cFilter)) {
|
362
|
+
struct filter_object *f;
|
363
|
+
GetFilter(vfilter, f);
|
364
|
+
filter = f->expr;
|
365
|
+
} else {
|
366
|
+
Check_Type(vfilter, T_STRING);
|
367
|
+
filter = RSTRING(vfilter)->ptr;
|
368
|
+
}
|
369
|
+
opt = RTEST(optimize);
|
370
|
+
|
371
|
+
/* operation */
|
372
|
+
if (pcap_compile(cap->pcap, &program, filter,
|
373
|
+
opt, cap->netmask) < 0)
|
374
|
+
rb_raise(ePcapError, "setfilter: %s", pcap_geterr(cap->pcap));
|
375
|
+
if (pcap_setfilter(cap->pcap, &program) < 0)
|
376
|
+
rb_raise(ePcapError, "setfilter: %s", pcap_geterr(cap->pcap));
|
377
|
+
|
378
|
+
return Qnil;
|
379
|
+
}
|
380
|
+
|
381
|
+
static VALUE
|
382
|
+
capture_datalink(self)
|
383
|
+
VALUE self;
|
384
|
+
{
|
385
|
+
struct capture_object *cap;
|
386
|
+
|
387
|
+
DEBUG_PRINT("capture_datalink");
|
388
|
+
GetCapture(self, cap);
|
389
|
+
|
390
|
+
return INT2NUM(pcap_datalink(cap->pcap));
|
391
|
+
}
|
392
|
+
|
393
|
+
static VALUE
|
394
|
+
capture_snapshot(self)
|
395
|
+
VALUE self;
|
396
|
+
{
|
397
|
+
struct capture_object *cap;
|
398
|
+
|
399
|
+
DEBUG_PRINT("capture_snapshot");
|
400
|
+
GetCapture(self, cap);
|
401
|
+
|
402
|
+
return INT2NUM(pcap_snapshot(cap->pcap));
|
403
|
+
}
|
404
|
+
|
405
|
+
static VALUE
|
406
|
+
capture_stats(self)
|
407
|
+
VALUE self;
|
408
|
+
{
|
409
|
+
struct capture_object *cap;
|
410
|
+
struct pcap_stat stat;
|
411
|
+
VALUE v_stat;
|
412
|
+
|
413
|
+
DEBUG_PRINT("capture_stats");
|
414
|
+
GetCapture(self, cap);
|
415
|
+
|
416
|
+
if (pcap_stats(cap->pcap, &stat) == -1)
|
417
|
+
return Qnil;
|
418
|
+
|
419
|
+
v_stat = rb_funcall(cPcapStat, rb_intern("new"), 3,
|
420
|
+
UINT2NUM(stat.ps_recv),
|
421
|
+
UINT2NUM(stat.ps_drop),
|
422
|
+
UINT2NUM(stat.ps_ifdrop));
|
423
|
+
|
424
|
+
return v_stat;
|
425
|
+
}
|
426
|
+
|
427
|
+
/*
|
428
|
+
* Dumper object
|
429
|
+
*/
|
430
|
+
|
431
|
+
struct dumper_object {
|
432
|
+
pcap_dumper_t *pcap_dumper;
|
433
|
+
int dl_type;
|
434
|
+
bpf_u_int32 snaplen;
|
435
|
+
};
|
436
|
+
|
437
|
+
static void
|
438
|
+
closed_dumper()
|
439
|
+
{
|
440
|
+
rb_raise(rb_eRuntimeError, "dumper is already closed");
|
441
|
+
}
|
442
|
+
|
443
|
+
#define GetDumper(obj, dumper) {\
|
444
|
+
Data_Get_Struct(obj, struct dumper_object, dumper);\
|
445
|
+
if (dumper->pcap_dumper == NULL) closed_dumper();\
|
446
|
+
}
|
447
|
+
|
448
|
+
/* called from GC */
|
449
|
+
static void
|
450
|
+
free_dumper(dumper)
|
451
|
+
struct dumper_object *dumper;
|
452
|
+
{
|
453
|
+
DEBUG_PRINT("free_dumper");
|
454
|
+
if (dumper->pcap_dumper != NULL) {
|
455
|
+
DEBUG_PRINT("closing dumper");
|
456
|
+
pcap_dump_close(dumper->pcap_dumper);
|
457
|
+
dumper->pcap_dumper = NULL;
|
458
|
+
}
|
459
|
+
free(dumper);
|
460
|
+
}
|
461
|
+
|
462
|
+
static VALUE
|
463
|
+
dumper_open(class, v_cap, v_fname)
|
464
|
+
VALUE class;
|
465
|
+
VALUE v_cap;
|
466
|
+
VALUE v_fname;
|
467
|
+
{
|
468
|
+
struct dumper_object *dumper;
|
469
|
+
struct capture_object *cap;
|
470
|
+
pcap_dumper_t *pcap_dumper;
|
471
|
+
VALUE self;
|
472
|
+
|
473
|
+
DEBUG_PRINT("dumper_open");
|
474
|
+
|
475
|
+
CheckClass(v_cap, cCapture);
|
476
|
+
GetCapture(v_cap, cap);
|
477
|
+
Check_SafeStr(v_fname);
|
478
|
+
|
479
|
+
pcap_dumper = pcap_dump_open(cap->pcap, RSTRING(v_fname)->ptr);
|
480
|
+
if (pcap_dumper == NULL) {
|
481
|
+
rb_raise(ePcapError, "dumper_open: %s", pcap_geterr(cap->pcap));
|
482
|
+
}
|
483
|
+
|
484
|
+
self = Data_Make_Struct(class, struct dumper_object, 0,
|
485
|
+
free_dumper, dumper);
|
486
|
+
dumper->pcap_dumper = pcap_dumper;
|
487
|
+
dumper->dl_type = cap->dl_type;
|
488
|
+
dumper->snaplen = pcap_snapshot(cap->pcap);
|
489
|
+
|
490
|
+
return self;
|
491
|
+
}
|
492
|
+
|
493
|
+
static VALUE
|
494
|
+
dumper_close(self)
|
495
|
+
VALUE self;
|
496
|
+
{
|
497
|
+
struct dumper_object *dumper;
|
498
|
+
|
499
|
+
DEBUG_PRINT("dumper_close");
|
500
|
+
GetDumper(self, dumper);
|
501
|
+
|
502
|
+
pcap_dump_close(dumper->pcap_dumper);
|
503
|
+
dumper->pcap_dumper = NULL;
|
504
|
+
return Qnil;
|
505
|
+
}
|
506
|
+
|
507
|
+
static VALUE
|
508
|
+
dumper_dump(self, v_pkt)
|
509
|
+
VALUE self;
|
510
|
+
VALUE v_pkt;
|
511
|
+
{
|
512
|
+
struct dumper_object *dumper;
|
513
|
+
struct packet_object *pkt;
|
514
|
+
|
515
|
+
DEBUG_PRINT("dumper_dump");
|
516
|
+
GetDumper(self, dumper);
|
517
|
+
|
518
|
+
CheckClass(v_pkt, cPacket);
|
519
|
+
GetPacket(v_pkt, pkt);
|
520
|
+
if (pkt->hdr.dl_type != dumper->dl_type)
|
521
|
+
rb_raise(rb_eArgError, "Cannot dump this packet: data-link type mismatch");
|
522
|
+
if (pkt->hdr.pkthdr.caplen > dumper->snaplen)
|
523
|
+
rb_raise(rb_eArgError, "Cannot dump this packet: too large caplen");
|
524
|
+
|
525
|
+
pcap_dump((u_char *)dumper->pcap_dumper, &pkt->hdr.pkthdr, pkt->data);
|
526
|
+
return Qnil;
|
527
|
+
}
|
528
|
+
|
529
|
+
/*
|
530
|
+
* Filter object
|
531
|
+
*/
|
532
|
+
|
533
|
+
/* called from GC */
|
534
|
+
static void
|
535
|
+
mark_filter(filter)
|
536
|
+
struct filter_object *filter;
|
537
|
+
{
|
538
|
+
rb_gc_mark(filter->param);
|
539
|
+
rb_gc_mark(filter->optimize);
|
540
|
+
rb_gc_mark(filter->netmask);
|
541
|
+
}
|
542
|
+
|
543
|
+
static void
|
544
|
+
free_filter(filter)
|
545
|
+
struct filter_object *filter;
|
546
|
+
{
|
547
|
+
free(filter->expr);
|
548
|
+
free(filter);
|
549
|
+
/*
|
550
|
+
* This cause memory leak because filter->program hold some memory.
|
551
|
+
* We overlook it because libpcap does not implement pcap_freecode().
|
552
|
+
*/
|
553
|
+
}
|
554
|
+
|
555
|
+
static VALUE
|
556
|
+
filter_new(argc, argv, class)
|
557
|
+
int argc;
|
558
|
+
VALUE *argv;
|
559
|
+
VALUE class;
|
560
|
+
{
|
561
|
+
VALUE self, v_expr, v_optimize, v_capture, v_netmask;
|
562
|
+
struct filter_object *filter;
|
563
|
+
struct capture_object *capture;
|
564
|
+
pcap_t *pcap;
|
565
|
+
char *expr;
|
566
|
+
int n, optimize, snaplen, linktype;
|
567
|
+
bpf_u_int32 netmask;
|
568
|
+
|
569
|
+
n = rb_scan_args(argc, argv, "13", &v_expr, &v_capture,
|
570
|
+
&v_optimize, &v_netmask);
|
571
|
+
/* filter expression */
|
572
|
+
Check_Type(v_expr, T_STRING);
|
573
|
+
expr = STR2CSTR(v_expr);
|
574
|
+
/* capture object */
|
575
|
+
if (IsKindOf(v_capture, cCapture)) {
|
576
|
+
CheckClass(v_capture, cCapture);
|
577
|
+
GetCapture(v_capture, capture);
|
578
|
+
pcap = capture->pcap;
|
579
|
+
} else if (NIL_P(v_capture)) {
|
580
|
+
/* assume most common case */
|
581
|
+
snaplen = DEFAULT_SNAPLEN;
|
582
|
+
linktype = DEFAULT_DATALINK;
|
583
|
+
pcap = 0;
|
584
|
+
} else {
|
585
|
+
snaplen = NUM2INT(rb_funcall(v_capture, rb_intern("[]"), 1, INT2FIX(0)));
|
586
|
+
linktype = NUM2INT(rb_funcall(v_capture, rb_intern("[]"), 1, INT2FIX(1)));
|
587
|
+
pcap = 0;
|
588
|
+
}
|
589
|
+
/* optimize flag */
|
590
|
+
optimize = 1;
|
591
|
+
if (n >= 3) {
|
592
|
+
optimize = RTEST(v_optimize);
|
593
|
+
}
|
594
|
+
/* netmask */
|
595
|
+
netmask = 0;
|
596
|
+
if (n >= 4) {
|
597
|
+
bpf_u_int32 mask = NUM2UINT(v_netmask);
|
598
|
+
netmask = htonl(mask);
|
599
|
+
}
|
600
|
+
|
601
|
+
filter = (struct filter_object *)xmalloc(sizeof(struct filter_object));
|
602
|
+
if (pcap) {
|
603
|
+
if (pcap_compile(pcap, &filter->program, expr, optimize, netmask) < 0)
|
604
|
+
rb_raise(ePcapError, "%s", pcap_geterr(pcap));
|
605
|
+
filter->datalink = pcap_datalink(pcap);
|
606
|
+
filter->snaplen = pcap_snapshot(pcap);
|
607
|
+
} else {
|
608
|
+
#ifdef HAVE_PCAP_COMPILE_NOPCAP
|
609
|
+
if (pcap_compile_nopcap(snaplen, linktype, &filter->program, expr, optimize, netmask) < 0)
|
610
|
+
/* libpcap-0.5 provides no error report for pcap_compile_nopcap */
|
611
|
+
rb_raise(ePcapError, "pcap_compile_nopcap error");
|
612
|
+
filter->datalink = linktype;
|
613
|
+
filter->snaplen = snaplen;
|
614
|
+
#else
|
615
|
+
rb_raise(rb_eArgError, "pcap_compile_nopcap needs libpcap-0.5 or later");
|
616
|
+
#endif
|
617
|
+
}
|
618
|
+
self = Data_Wrap_Struct(class, mark_filter, free_filter, filter);
|
619
|
+
filter->expr = strdup(expr);
|
620
|
+
filter->param = v_capture;
|
621
|
+
filter->optimize = optimize ? Qtrue : Qfalse;
|
622
|
+
filter->netmask = INT2NUM(ntohl(netmask));
|
623
|
+
|
624
|
+
return self;
|
625
|
+
}
|
626
|
+
|
627
|
+
VALUE
|
628
|
+
filter_match(self, v_pkt)
|
629
|
+
VALUE self, v_pkt;
|
630
|
+
{
|
631
|
+
struct filter_object *filter;
|
632
|
+
struct packet_object *pkt;
|
633
|
+
struct pcap_pkthdr *h;
|
634
|
+
|
635
|
+
GetFilter(self, filter);
|
636
|
+
CheckClass(v_pkt, cPacket);
|
637
|
+
GetPacket(v_pkt, pkt);
|
638
|
+
h = &pkt->hdr.pkthdr;
|
639
|
+
|
640
|
+
if (filter->datalink != pkt->hdr.dl_type)
|
641
|
+
rb_raise(rb_eRuntimeError, "Incompatible datalink type");
|
642
|
+
if (filter->snaplen < h->caplen)
|
643
|
+
rb_raise(rb_eRuntimeError, "Incompatible snaplen");
|
644
|
+
|
645
|
+
if (bpf_filter(filter->program.bf_insns, pkt->data, h->len, h->caplen))
|
646
|
+
return Qtrue;
|
647
|
+
else
|
648
|
+
return Qfalse;
|
649
|
+
}
|
650
|
+
|
651
|
+
static VALUE
|
652
|
+
filter_source(self)
|
653
|
+
VALUE self;
|
654
|
+
{
|
655
|
+
struct filter_object *filter;
|
656
|
+
|
657
|
+
GetFilter(self, filter);
|
658
|
+
return rb_str_new2(filter->expr);
|
659
|
+
}
|
660
|
+
|
661
|
+
static VALUE
|
662
|
+
new_filter(expr, param, optimize, netmask)
|
663
|
+
char *expr;
|
664
|
+
VALUE param, optimize, netmask;
|
665
|
+
{
|
666
|
+
return rb_funcall(cFilter,
|
667
|
+
rb_intern("new"), 4,
|
668
|
+
rb_str_new2(expr), param, optimize, netmask);
|
669
|
+
}
|
670
|
+
|
671
|
+
static VALUE
|
672
|
+
filter_or(self, other)
|
673
|
+
VALUE self, other;
|
674
|
+
{
|
675
|
+
struct filter_object *filter, *filter2;
|
676
|
+
char *expr;
|
677
|
+
|
678
|
+
CheckClass(other, cFilter);
|
679
|
+
GetFilter(self, filter);
|
680
|
+
GetFilter(other, filter2);
|
681
|
+
|
682
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + strlen(filter2->expr) + 16);
|
683
|
+
sprintf(expr, "( %s ) or ( %s )", filter->expr, filter2->expr);
|
684
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
685
|
+
}
|
686
|
+
|
687
|
+
static VALUE
|
688
|
+
filter_and(self, other)
|
689
|
+
VALUE self, other;
|
690
|
+
{
|
691
|
+
struct filter_object *filter, *filter2;
|
692
|
+
char *expr;
|
693
|
+
|
694
|
+
CheckClass(other, cFilter);
|
695
|
+
GetFilter(self, filter);
|
696
|
+
GetFilter(other, filter2);
|
697
|
+
|
698
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + strlen(filter2->expr) + 16);
|
699
|
+
sprintf(expr, "( %s ) and ( %s )", filter->expr, filter2->expr);
|
700
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
701
|
+
}
|
702
|
+
|
703
|
+
static VALUE
|
704
|
+
filter_not(self)
|
705
|
+
VALUE self;
|
706
|
+
{
|
707
|
+
struct filter_object *filter;
|
708
|
+
char *expr;
|
709
|
+
|
710
|
+
GetFilter(self, filter);
|
711
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + 16);
|
712
|
+
sprintf(expr, "not ( %s )", filter->expr);
|
713
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
714
|
+
}
|
715
|
+
|
716
|
+
/*
|
717
|
+
* Class definition
|
718
|
+
*/
|
719
|
+
|
720
|
+
void
|
721
|
+
Init_pcap(void)
|
722
|
+
{
|
723
|
+
DEBUG_PRINT("Init_pcap");
|
724
|
+
|
725
|
+
/* define module Pcap */
|
726
|
+
mPcap = rb_define_module("Pcap");
|
727
|
+
rb_define_module_function(mPcap, "lookupdev", pcap_s_lookupdev, 0);
|
728
|
+
rb_define_module_function(mPcap, "lookupnet", pcap_s_lookupnet, 1);
|
729
|
+
rb_global_variable(&rbpcap_convert);
|
730
|
+
rb_define_singleton_method(mPcap, "convert?", pcap_s_convert, 0);
|
731
|
+
rb_define_singleton_method(mPcap, "convert=", pcap_s_convert_set, 1);
|
732
|
+
rb_define_const(mPcap, "DLT_NULL", INT2NUM(DLT_NULL));
|
733
|
+
rb_define_const(mPcap, "DLT_EN10MB", INT2NUM(DLT_EN10MB));
|
734
|
+
rb_define_const(mPcap, "DLT_EN3MB", INT2NUM(DLT_EN3MB));
|
735
|
+
rb_define_const(mPcap, "DLT_AX25", INT2NUM(DLT_AX25));
|
736
|
+
rb_define_const(mPcap, "DLT_PRONET", INT2NUM(DLT_PRONET));
|
737
|
+
rb_define_const(mPcap, "DLT_CHAOS", INT2NUM(DLT_CHAOS));
|
738
|
+
rb_define_const(mPcap, "DLT_IEEE802", INT2NUM(DLT_IEEE802));
|
739
|
+
rb_define_const(mPcap, "DLT_ARCNET", INT2NUM(DLT_ARCNET));
|
740
|
+
rb_define_const(mPcap, "DLT_SLIP", INT2NUM(DLT_SLIP));
|
741
|
+
rb_define_const(mPcap, "DLT_PPP", INT2NUM(DLT_PPP));
|
742
|
+
rb_define_const(mPcap, "DLT_FDDI", INT2NUM(DLT_FDDI));
|
743
|
+
rb_define_const(mPcap, "DLT_ATM_RFC1483", INT2NUM(DLT_ATM_RFC1483));
|
744
|
+
#ifdef DLT_RAW
|
745
|
+
rb_define_const(mPcap, "DLT_RAW", INT2NUM(DLT_RAW));
|
746
|
+
rb_define_const(mPcap, "DLT_SLIP_BSDOS", INT2NUM(DLT_SLIP_BSDOS));
|
747
|
+
rb_define_const(mPcap, "DLT_PPP_BSDOS", INT2NUM(DLT_PPP_BSDOS));
|
748
|
+
#endif
|
749
|
+
|
750
|
+
/* define class Capture */
|
751
|
+
cCapture = rb_define_class_under(mPcap, "Capture", rb_cObject);
|
752
|
+
rb_include_module(cCapture, rb_mEnumerable);
|
753
|
+
rb_define_singleton_method(cCapture, "open_live", capture_open_live, -1);
|
754
|
+
rb_define_singleton_method(cCapture, "open_offline", capture_open_offline, 1);
|
755
|
+
rb_define_method(cCapture, "close", capture_close, 0);
|
756
|
+
rb_define_method(cCapture, "dispatch", capture_dispatch, -1);
|
757
|
+
rb_define_method(cCapture, "loop", capture_loop, -1);
|
758
|
+
rb_define_method(cCapture, "each_packet", capture_loop, -1);
|
759
|
+
rb_define_method(cCapture, "each", capture_loop, -1);
|
760
|
+
rb_define_method(cCapture, "setfilter", capture_setfilter, -1);
|
761
|
+
rb_define_method(cCapture, "datalink", capture_datalink, 0);
|
762
|
+
rb_define_method(cCapture, "snapshot", capture_snapshot, 0);
|
763
|
+
rb_define_method(cCapture, "snaplen", capture_snapshot, 0);
|
764
|
+
rb_define_method(cCapture, "stats", capture_stats, 0);
|
765
|
+
|
766
|
+
/* define class Dumper */
|
767
|
+
cDumper = rb_define_class_under(mPcap, "Dumper", rb_cObject);
|
768
|
+
rb_define_singleton_method(cDumper, "open", dumper_open, 2);
|
769
|
+
rb_define_method(cDumper, "close", dumper_close, 0);
|
770
|
+
rb_define_method(cDumper, "dump", dumper_dump, 1);
|
771
|
+
|
772
|
+
/* define class Filter */
|
773
|
+
cFilter = rb_define_class_under(mPcap, "Filter", rb_cObject);
|
774
|
+
rb_define_singleton_method(cFilter, "new", filter_new, -1);
|
775
|
+
rb_define_singleton_method(cFilter, "compile", filter_new, -1);
|
776
|
+
rb_define_method(cFilter, "=~", filter_match, 1);
|
777
|
+
rb_define_method(cFilter, "===", filter_match, 1);
|
778
|
+
rb_define_method(cFilter, "source", filter_source, 0);
|
779
|
+
rb_define_method(cFilter, "|", filter_or, 1);
|
780
|
+
rb_define_method(cFilter, "&", filter_and, 1);
|
781
|
+
rb_define_method(cFilter, "~@", filter_not, 0);
|
782
|
+
/*rb_define_method(cFilter, "&", filter_and, 1);*/
|
783
|
+
|
784
|
+
/* define class PcapStat */
|
785
|
+
cPcapStat = rb_funcall(rb_cStruct, rb_intern("new"), 4,
|
786
|
+
Qnil,
|
787
|
+
INT2NUM(rb_intern("recv")),
|
788
|
+
INT2NUM(rb_intern("drop")),
|
789
|
+
INT2NUM(rb_intern("ifdrop")));
|
790
|
+
rb_define_const(mPcap, "Stat", cPcapStat);
|
791
|
+
|
792
|
+
/* define exception classes */
|
793
|
+
ePcapError = rb_define_class_under(mPcap, "PcapError", rb_eStandardError);
|
794
|
+
eTruncatedPacket = rb_define_class_under(mPcap, "TruncatedPacket", ePcapError);
|
795
|
+
|
796
|
+
Init_packet();
|
797
|
+
rb_f_require(Qnil, rb_str_new2("pcap_misc"));
|
798
|
+
}
|