ruby-pcap 0.7.8
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/.gitignore +19 -0
- data/COPYING +340 -0
- data/ChangeLog +145 -0
- data/Gemfile +4 -0
- data/MANIFEST +47 -0
- data/README +47 -0
- data/README.ja +50 -0
- data/Rakefile +1 -0
- data/VERSION +1 -0
- data/doc-ja/Capture.html +147 -0
- data/doc-ja/Dumper.html +54 -0
- data/doc-ja/Filter.html +112 -0
- data/doc-ja/ICMPPacket.html +189 -0
- data/doc-ja/IPAddress.html +60 -0
- data/doc-ja/IPPacket.html +142 -0
- data/doc-ja/Packet.html +101 -0
- data/doc-ja/Pcap.html +111 -0
- data/doc-ja/PcapError.html +21 -0
- data/doc-ja/Pcaplet.html +113 -0
- data/doc-ja/TCPPacket.html +148 -0
- data/doc-ja/TruncatedPacket.html +22 -0
- data/doc-ja/UDPPacket.html +73 -0
- data/doc-ja/index.html +54 -0
- data/examples/httpdump.rb +27 -0
- data/examples/rewrite_time.rb +28 -0
- data/examples/tcpdump.rb +26 -0
- data/examples/test.rb +11 -0
- data/ext/Pcap.c +938 -0
- data/ext/extconf.rb +22 -0
- data/ext/icmp_packet.c +444 -0
- data/ext/ip_packet.c +424 -0
- data/ext/packet.c +328 -0
- data/ext/ruby_pcap.h +134 -0
- data/ext/tcp_packet.c +121 -0
- data/ext/udp_packet.c +96 -0
- data/lib/pcap_misc.rb +80 -0
- data/lib/pcaplet.rb +127 -0
- data/ruby-pcap.gemspec +20 -0
- metadata +101 -0
data/doc-ja/index.html
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
2
|
+
<html> <head>
|
3
|
+
<title>Ruby/Pcap Library</title>
|
4
|
+
</head>
|
5
|
+
|
6
|
+
<body bgcolor="ffffff">
|
7
|
+
<h1>Ruby/Pcap��ĥ�饤�֥��</h1>
|
8
|
+
|
9
|
+
LBL �� libpcap (Packet Capture library) �ؤ� ruby ���ե������Ǥ���
|
10
|
+
|
11
|
+
<h2>�⥸�塼��</h2>
|
12
|
+
<ul>
|
13
|
+
<li><a href="Pcap.html"><code>Pcap</code></a>
|
14
|
+
</ul>
|
15
|
+
|
16
|
+
<h2>���饹</h2>
|
17
|
+
|
18
|
+
�ʲ��Υ��饹������ <code>Pcap</code> �⥸�塼��β����������Ƥ��ޤ���
|
19
|
+
�������äƻ��Ѥ���Ȥ��� <code>Pcap</code> �⥸�塼���
|
20
|
+
<code>include</code> ���뤫���⤷���� <code>Pcap::Capture</code> �Τ�
|
21
|
+
���˻��Ȥ��Ƥ���������
|
22
|
+
|
23
|
+
<ul>
|
24
|
+
<li><a href="Capture.html"><code>Capture</code></a>
|
25
|
+
<li><a href="Pcaplet.html"><code>Pcaplet</code></a>
|
26
|
+
<li><a href="Packet.html"><code>Packet</code></a>
|
27
|
+
<ul>
|
28
|
+
<li><a href="IPPacket.html"><code>IPPacket</code></a>
|
29
|
+
<ul>
|
30
|
+
<li><a href="TCPPacket.html"><code>TCPPacket</code></a>
|
31
|
+
<li><a href="UDPPacket.html"><code>UDPPacket</code></a>
|
32
|
+
<li><a href="ICMPPacket.html"><code>ICMPPacket</code></a>
|
33
|
+
</ul>
|
34
|
+
</ul>
|
35
|
+
<li><a href="IPAddress.html"><code>IPAddress</code></a>
|
36
|
+
<li><a href="Dumper.html"><code>Dumper</code></a>
|
37
|
+
<li><a href="Filter.html"><code>Filter</code></a>
|
38
|
+
</ul>
|
39
|
+
|
40
|
+
<h2>�㳰</h2>
|
41
|
+
|
42
|
+
<ul>
|
43
|
+
<li><a href="PcapError.html"><code>PcapError</code></a>
|
44
|
+
<ul>
|
45
|
+
<li><a href="TruncatedPacket.html"><code>TruncatedPacket</code></a>
|
46
|
+
</ul>
|
47
|
+
</ul>
|
48
|
+
|
49
|
+
<hr>
|
50
|
+
<P ALIGN="RIGHT">
|
51
|
+
<A HREF="mailto:fukusima@goto.info.waseda.ac.jp">
|
52
|
+
fukusima@goto.info.waseda.ac.jp</A><BR>
|
53
|
+
</P>
|
54
|
+
</body> </html>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pcaplet'
|
4
|
+
httpdump = Pcaplet.new('-s 1500')
|
5
|
+
|
6
|
+
HTTP_REQUEST = Pcap::Filter.new('tcp and dst port 80', httpdump.capture)
|
7
|
+
HTTP_RESPONSE = Pcap::Filter.new('tcp and src port 80', httpdump.capture)
|
8
|
+
|
9
|
+
httpdump.add_filter(HTTP_REQUEST | HTTP_RESPONSE)
|
10
|
+
httpdump.each_packet {|pkt|
|
11
|
+
data = pkt.tcp_data
|
12
|
+
case pkt
|
13
|
+
when HTTP_REQUEST
|
14
|
+
if data and data =~ /^GET\s+(\S+)/
|
15
|
+
path = $1
|
16
|
+
host = pkt.dst.to_s
|
17
|
+
host << ":#{pkt.dst_port}" if pkt.dport != 80
|
18
|
+
s = "#{pkt.src}:#{pkt.sport} > GET http://#{host}#{path}"
|
19
|
+
end
|
20
|
+
when HTTP_RESPONSE
|
21
|
+
if data and data =~ /^(HTTP\/.*)$/
|
22
|
+
status = $1
|
23
|
+
s = "#{pkt.dst}:#{pkt.dport} < #{status}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
puts s if s
|
27
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pcap'
|
4
|
+
|
5
|
+
if 3 != ARGV.size
|
6
|
+
STDERR.puts "Usage: #{$0} in.pcap out.pcap delta"
|
7
|
+
exit(2)
|
8
|
+
end
|
9
|
+
|
10
|
+
in_filename, out_filename, delta = ARGV
|
11
|
+
|
12
|
+
inp = outc = outp = nil
|
13
|
+
begin
|
14
|
+
inp = Pcap::Capture.open_offline(in_filename)
|
15
|
+
outc = Pcap::Capture.open_dead(inp.datalink, inp.snaplen)
|
16
|
+
outp = Pcap::Dumper.open(outc, out_filename)
|
17
|
+
inp.loop(-1) do |pkt|
|
18
|
+
pkt.time_i += delta.to_i
|
19
|
+
outp.dump(pkt)
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
STDERR.puts e.message,e.backtrace
|
23
|
+
ensure
|
24
|
+
inp.close if inp
|
25
|
+
outp.close if outp
|
26
|
+
outc.close if outc
|
27
|
+
end
|
28
|
+
|
data/examples/tcpdump.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pcaplet'
|
4
|
+
include Pcap
|
5
|
+
|
6
|
+
class Time
|
7
|
+
# tcpdump style format
|
8
|
+
def to_s
|
9
|
+
sprintf "%0.2d:%0.2d:%0.2d.%0.6d", hour, min, sec, tv_usec
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
pcaplet = Pcaplet.new
|
14
|
+
pcaplet.each_packet { |pkt|
|
15
|
+
print "#{pkt.time} #{pkt}"
|
16
|
+
if pkt.tcp?
|
17
|
+
print " (#{pkt.tcp_data_len})"
|
18
|
+
print " ack #{pkt.tcp_ack}" if pkt.tcp_ack?
|
19
|
+
print " win #{pkt.tcp_win}"
|
20
|
+
end
|
21
|
+
if pkt.ip?
|
22
|
+
print " (DF)" if pkt.ip_df?
|
23
|
+
end
|
24
|
+
print "\n"
|
25
|
+
}
|
26
|
+
pcaplet.close
|
data/examples/test.rb
ADDED
data/ext/Pcap.c
ADDED
@@ -0,0 +1,938 @@
|
|
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
|
+
|
20
|
+
#ifdef PCAP_DONT_TRAP
|
21
|
+
#define MAYBE_TRAP_BEG do {} while (0)
|
22
|
+
#define MAYBE_TRAP_END do {} while (0)
|
23
|
+
#else
|
24
|
+
#define MAYBE_TRAP_BEG TRAP_BEG
|
25
|
+
#define MAYBE_TRAP_END TRAP_END
|
26
|
+
#endif
|
27
|
+
|
28
|
+
static char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
29
|
+
|
30
|
+
VALUE mPcap, rbpcap_convert = Qnil;
|
31
|
+
VALUE ePcapError;
|
32
|
+
VALUE eTruncatedPacket;
|
33
|
+
VALUE cFilter;
|
34
|
+
static VALUE cCapture;
|
35
|
+
static VALUE cPcapStat;
|
36
|
+
static VALUE cDumper;
|
37
|
+
|
38
|
+
struct filter_object {
|
39
|
+
char *expr;
|
40
|
+
struct bpf_program program;
|
41
|
+
int datalink;
|
42
|
+
int snaplen;
|
43
|
+
VALUE param;
|
44
|
+
VALUE optimize;
|
45
|
+
VALUE netmask;
|
46
|
+
};
|
47
|
+
|
48
|
+
#define GetFilter(obj, filter) \
|
49
|
+
Data_Get_Struct(obj, struct filter_object, filter)
|
50
|
+
|
51
|
+
|
52
|
+
static VALUE
|
53
|
+
pcap_s_lookupdev(self)
|
54
|
+
VALUE self;
|
55
|
+
{
|
56
|
+
char *dev;
|
57
|
+
|
58
|
+
dev = pcap_lookupdev(pcap_errbuf);
|
59
|
+
if (dev == NULL) {
|
60
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
61
|
+
}
|
62
|
+
return rb_str_new2(dev);
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE
|
66
|
+
pcap_s_findalldevs(self)
|
67
|
+
VALUE self;
|
68
|
+
{
|
69
|
+
pcap_if_t *alldevsp;
|
70
|
+
VALUE return_ary;
|
71
|
+
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
72
|
+
|
73
|
+
return_ary = rb_ary_new();
|
74
|
+
|
75
|
+
pcap_findalldevs(&alldevsp, pcap_errbuf);
|
76
|
+
|
77
|
+
if (alldevsp == NULL) // List is empty, probably an error
|
78
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
79
|
+
|
80
|
+
for (; alldevsp->next != NULL; alldevsp = alldevsp->next)
|
81
|
+
rb_ary_push(return_ary, rb_str_new2(alldevsp->name));
|
82
|
+
|
83
|
+
pcap_freealldevs(alldevsp);
|
84
|
+
|
85
|
+
return return_ary;
|
86
|
+
}
|
87
|
+
|
88
|
+
static VALUE
|
89
|
+
pcap_s_lookupnet(self, dev)
|
90
|
+
VALUE self;
|
91
|
+
VALUE dev;
|
92
|
+
{
|
93
|
+
bpf_u_int32 net, mask, m;
|
94
|
+
struct in_addr addr;
|
95
|
+
|
96
|
+
Check_Type(dev, T_STRING);
|
97
|
+
if (pcap_lookupnet(StringValuePtr(dev), &net, &mask, pcap_errbuf) == -1) {
|
98
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
99
|
+
}
|
100
|
+
|
101
|
+
addr.s_addr = net;
|
102
|
+
m = ntohl(mask);
|
103
|
+
return rb_ary_new3(2, new_ipaddr(&addr), UINT32_2_NUM(m));
|
104
|
+
}
|
105
|
+
|
106
|
+
static VALUE
|
107
|
+
pcap_s_convert(self)
|
108
|
+
VALUE self;
|
109
|
+
{
|
110
|
+
return rbpcap_convert;
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE
|
114
|
+
pcap_s_convert_set(self, val)
|
115
|
+
VALUE self;
|
116
|
+
{
|
117
|
+
rbpcap_convert = val;
|
118
|
+
return Qnil;
|
119
|
+
}
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Capture object
|
123
|
+
*/
|
124
|
+
|
125
|
+
struct capture_object {
|
126
|
+
pcap_t *pcap;
|
127
|
+
bpf_u_int32 netmask;
|
128
|
+
int dl_type; /* data-link type (DLT_*) */
|
129
|
+
};
|
130
|
+
|
131
|
+
static void
|
132
|
+
closed_capture()
|
133
|
+
{
|
134
|
+
rb_raise(rb_eRuntimeError, "device is already closed");
|
135
|
+
}
|
136
|
+
|
137
|
+
#define GetCapture(obj, cap) {\
|
138
|
+
Data_Get_Struct(obj, struct capture_object, cap);\
|
139
|
+
if (cap->pcap == NULL) closed_capture();\
|
140
|
+
}
|
141
|
+
|
142
|
+
/* called from GC */
|
143
|
+
static void
|
144
|
+
free_capture(cap)
|
145
|
+
struct capture_object *cap;
|
146
|
+
{
|
147
|
+
DEBUG_PRINT("free_capture");
|
148
|
+
if (cap->pcap != NULL) {
|
149
|
+
DEBUG_PRINT("closing capture");
|
150
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
151
|
+
pcap_close(cap->pcap);
|
152
|
+
cap->pcap = NULL;
|
153
|
+
}
|
154
|
+
free(cap);
|
155
|
+
}
|
156
|
+
|
157
|
+
static VALUE
|
158
|
+
capture_open_live(argc, argv, class)
|
159
|
+
int argc;
|
160
|
+
VALUE *argv;
|
161
|
+
VALUE class;
|
162
|
+
{
|
163
|
+
VALUE v_device, v_snaplen, v_promisc, v_to_ms;
|
164
|
+
char *device;
|
165
|
+
int snaplen, promisc, to_ms;
|
166
|
+
int rs;
|
167
|
+
VALUE self;
|
168
|
+
struct capture_object *cap;
|
169
|
+
pcap_t *pcap;
|
170
|
+
bpf_u_int32 net, netmask;
|
171
|
+
|
172
|
+
DEBUG_PRINT("capture_open_live");
|
173
|
+
|
174
|
+
/* scan arg */
|
175
|
+
rs = rb_scan_args(argc, argv, "13", &v_device, &v_snaplen,
|
176
|
+
&v_promisc, &v_to_ms);
|
177
|
+
|
178
|
+
/* device */
|
179
|
+
Check_SafeStr(v_device);
|
180
|
+
device = RSTRING_PTR(v_device);
|
181
|
+
/* snaplen */
|
182
|
+
if (rs >= 2) {
|
183
|
+
Check_Type(v_snaplen, T_FIXNUM);
|
184
|
+
snaplen = FIX2INT(v_snaplen);
|
185
|
+
} else {
|
186
|
+
snaplen = DEFAULT_SNAPLEN;
|
187
|
+
}
|
188
|
+
if (snaplen < 0)
|
189
|
+
rb_raise(rb_eArgError, "invalid snaplen");
|
190
|
+
/* promisc */
|
191
|
+
if (rs >= 3) {
|
192
|
+
promisc = RTEST(v_promisc);
|
193
|
+
} else {
|
194
|
+
promisc = DEFAULT_PROMISC;
|
195
|
+
}
|
196
|
+
/* to_ms */
|
197
|
+
if (rs >= 4) {
|
198
|
+
Check_Type(v_to_ms, T_FIXNUM);
|
199
|
+
to_ms = FIX2INT(v_to_ms);
|
200
|
+
} else
|
201
|
+
to_ms = DEFAULT_TO_MS;
|
202
|
+
|
203
|
+
/* open */
|
204
|
+
pcap = pcap_open_live(device, snaplen, promisc, to_ms, pcap_errbuf);
|
205
|
+
if (pcap == NULL) {
|
206
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
207
|
+
}
|
208
|
+
if (pcap_lookupnet(device, &net, &netmask, pcap_errbuf) == -1) {
|
209
|
+
netmask = 0;
|
210
|
+
rb_warning("cannot lookup net: %s\n", pcap_errbuf);
|
211
|
+
}
|
212
|
+
|
213
|
+
/* setup instance */
|
214
|
+
self = Data_Make_Struct(class, struct capture_object,
|
215
|
+
0, free_capture, cap);
|
216
|
+
cap->pcap = pcap;
|
217
|
+
cap->netmask = netmask;
|
218
|
+
cap->dl_type = pcap_datalink(pcap);
|
219
|
+
|
220
|
+
return self;
|
221
|
+
}
|
222
|
+
|
223
|
+
static VALUE
|
224
|
+
capture_open_offline(class, fname)
|
225
|
+
VALUE class;
|
226
|
+
VALUE fname;
|
227
|
+
{
|
228
|
+
VALUE self;
|
229
|
+
struct capture_object *cap;
|
230
|
+
pcap_t *pcap;
|
231
|
+
|
232
|
+
DEBUG_PRINT("capture_open_offline");
|
233
|
+
|
234
|
+
/* open offline */
|
235
|
+
Check_SafeStr(fname);
|
236
|
+
pcap = pcap_open_offline(RSTRING_PTR(fname), pcap_errbuf);
|
237
|
+
if (pcap == NULL) {
|
238
|
+
rb_raise(ePcapError, "%s", pcap_errbuf);
|
239
|
+
}
|
240
|
+
|
241
|
+
/* setup instance */
|
242
|
+
self = Data_Make_Struct(class, struct capture_object,
|
243
|
+
0, free_capture, cap);
|
244
|
+
cap->pcap = pcap;
|
245
|
+
cap->netmask = 0;
|
246
|
+
cap->dl_type = pcap_datalink(pcap);
|
247
|
+
|
248
|
+
return self;
|
249
|
+
}
|
250
|
+
|
251
|
+
static VALUE
|
252
|
+
capture_open_dead(argc, argv, class)
|
253
|
+
int argc;
|
254
|
+
VALUE *argv;
|
255
|
+
VALUE class;
|
256
|
+
{
|
257
|
+
VALUE self;
|
258
|
+
struct capture_object *cap;
|
259
|
+
pcap_t *pcap;
|
260
|
+
VALUE v_linktype, v_snaplen;
|
261
|
+
int linktype, snaplen;
|
262
|
+
int rs;
|
263
|
+
|
264
|
+
DEBUG_PRINT("capture_open_dead");
|
265
|
+
|
266
|
+
/* scan arg */
|
267
|
+
rs = rb_scan_args(argc, argv, "02", &v_linktype, &v_snaplen);
|
268
|
+
if (rs >= 1) {
|
269
|
+
Check_Type(v_linktype, T_FIXNUM);
|
270
|
+
linktype = FIX2INT(v_linktype);
|
271
|
+
} else {
|
272
|
+
linktype = DEFAULT_DATALINK;
|
273
|
+
}
|
274
|
+
if (rs == 2) {
|
275
|
+
Check_Type(v_snaplen, T_FIXNUM);
|
276
|
+
snaplen = FIX2INT(v_snaplen);
|
277
|
+
} else {
|
278
|
+
snaplen = DEFAULT_SNAPLEN;
|
279
|
+
}
|
280
|
+
|
281
|
+
pcap = pcap_open_dead(linktype, snaplen);
|
282
|
+
|
283
|
+
if (pcap == NULL) {
|
284
|
+
rb_raise(ePcapError, "Error calling pcap_open_dead");
|
285
|
+
}
|
286
|
+
|
287
|
+
/* setup instance */
|
288
|
+
self = Data_Make_Struct(class, struct capture_object,
|
289
|
+
0, free_capture, cap);
|
290
|
+
cap->pcap = pcap;
|
291
|
+
cap->netmask = 0;
|
292
|
+
cap->dl_type = pcap_datalink(pcap);
|
293
|
+
|
294
|
+
return self;
|
295
|
+
}
|
296
|
+
|
297
|
+
static VALUE
|
298
|
+
capture_close(self)
|
299
|
+
VALUE self;
|
300
|
+
{
|
301
|
+
struct capture_object *cap;
|
302
|
+
|
303
|
+
DEBUG_PRINT("capture_close");
|
304
|
+
GetCapture(self, cap);
|
305
|
+
|
306
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
307
|
+
pcap_close(cap->pcap);
|
308
|
+
cap->pcap = NULL;
|
309
|
+
return Qnil;
|
310
|
+
}
|
311
|
+
|
312
|
+
static void
|
313
|
+
handler(cap, pkthdr, data)
|
314
|
+
struct capture_object *cap;
|
315
|
+
const struct pcap_pkthdr *pkthdr;
|
316
|
+
const u_char *data;
|
317
|
+
{
|
318
|
+
rb_yield(new_packet(data, pkthdr, cap->dl_type));
|
319
|
+
}
|
320
|
+
|
321
|
+
static VALUE
|
322
|
+
capture_dispatch(argc, argv, self)
|
323
|
+
int argc;
|
324
|
+
VALUE *argv;
|
325
|
+
VALUE self;
|
326
|
+
{
|
327
|
+
VALUE v_cnt;
|
328
|
+
int cnt;
|
329
|
+
struct capture_object *cap;
|
330
|
+
int ret;
|
331
|
+
|
332
|
+
DEBUG_PRINT("capture_dispatch");
|
333
|
+
GetCapture(self, cap);
|
334
|
+
|
335
|
+
/* scan arg */
|
336
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
337
|
+
FIXNUM_P(v_cnt);
|
338
|
+
cnt = FIX2INT(v_cnt);
|
339
|
+
} else {
|
340
|
+
cnt = -1;
|
341
|
+
}
|
342
|
+
|
343
|
+
MAYBE_TRAP_BEG;
|
344
|
+
ret = pcap_dispatch(cap->pcap, cnt, handler, (u_char *)cap);
|
345
|
+
MAYBE_TRAP_END;
|
346
|
+
if (ret == -1) {
|
347
|
+
rb_raise(ePcapError, "dispatch: %s", pcap_geterr(cap->pcap));
|
348
|
+
}
|
349
|
+
|
350
|
+
return INT2FIX(ret);
|
351
|
+
}
|
352
|
+
|
353
|
+
static VALUE
|
354
|
+
capture_fh(argc, argv, self)
|
355
|
+
int argc;
|
356
|
+
VALUE *argv;
|
357
|
+
VALUE self;
|
358
|
+
{
|
359
|
+
VALUE v_cnt;
|
360
|
+
int cnt;
|
361
|
+
struct capture_object *cap;
|
362
|
+
int ret;
|
363
|
+
|
364
|
+
DEBUG_PRINT("capture_fh");
|
365
|
+
GetCapture(self, cap);
|
366
|
+
|
367
|
+
return rb_funcall(rb_path2class("IO"), rb_intern("new"), 1, INT2FIX(pcap_fileno(cap->pcap)));
|
368
|
+
}
|
369
|
+
|
370
|
+
static VALUE
|
371
|
+
capture_loop(argc, argv, self)
|
372
|
+
int argc;
|
373
|
+
VALUE *argv;
|
374
|
+
VALUE self;
|
375
|
+
{
|
376
|
+
VALUE v_cnt;
|
377
|
+
int cnt;
|
378
|
+
struct capture_object *cap;
|
379
|
+
int ret;
|
380
|
+
|
381
|
+
DEBUG_PRINT("capture_loop");
|
382
|
+
GetCapture(self, cap);
|
383
|
+
|
384
|
+
/* scan arg */
|
385
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
386
|
+
FIXNUM_P(v_cnt);
|
387
|
+
cnt = FIX2INT(v_cnt);
|
388
|
+
} else {
|
389
|
+
cnt = -1;
|
390
|
+
}
|
391
|
+
|
392
|
+
if (pcap_file(cap->pcap) != NULL) {
|
393
|
+
MAYBE_TRAP_BEG;
|
394
|
+
ret = pcap_loop(cap->pcap, cnt, handler, (u_char *)cap);
|
395
|
+
MAYBE_TRAP_END;
|
396
|
+
}
|
397
|
+
else {
|
398
|
+
int fd = pcap_fileno(cap->pcap);
|
399
|
+
fd_set rset;
|
400
|
+
struct timeval tm;
|
401
|
+
|
402
|
+
FD_ZERO(&rset);
|
403
|
+
tm.tv_sec = 0;
|
404
|
+
tm.tv_usec = 0;
|
405
|
+
for (;;) {
|
406
|
+
do {
|
407
|
+
FD_SET(fd, &rset);
|
408
|
+
if (select(fd+1, &rset, NULL, NULL, &tm) == 0) {
|
409
|
+
rb_thread_wait_fd(fd);
|
410
|
+
}
|
411
|
+
MAYBE_TRAP_BEG;
|
412
|
+
ret = pcap_dispatch(cap->pcap, 1, handler, (u_char *)cap);
|
413
|
+
MAYBE_TRAP_END;
|
414
|
+
} while (ret == 0);
|
415
|
+
|
416
|
+
if (ret <= 0)
|
417
|
+
break;
|
418
|
+
if (cnt > 0) {
|
419
|
+
cnt -= ret;
|
420
|
+
if (cnt <= 0)
|
421
|
+
break;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
return INT2FIX(ret);
|
427
|
+
}
|
428
|
+
|
429
|
+
static VALUE
|
430
|
+
capture_setfilter(argc, argv, self)
|
431
|
+
int argc;
|
432
|
+
VALUE *argv;
|
433
|
+
VALUE self;
|
434
|
+
{
|
435
|
+
struct capture_object *cap;
|
436
|
+
VALUE vfilter, optimize;
|
437
|
+
char *filter;
|
438
|
+
int opt;
|
439
|
+
struct bpf_program program;
|
440
|
+
|
441
|
+
DEBUG_PRINT("capture_setfilter");
|
442
|
+
GetCapture(self, cap);
|
443
|
+
|
444
|
+
/* scan arg */
|
445
|
+
if (rb_scan_args(argc, argv, "11", &vfilter, &optimize) == 1) {
|
446
|
+
optimize = Qtrue;
|
447
|
+
}
|
448
|
+
|
449
|
+
/* check arg */
|
450
|
+
if (IsKindOf(vfilter, cFilter)) {
|
451
|
+
struct filter_object *f;
|
452
|
+
GetFilter(vfilter, f);
|
453
|
+
filter = f->expr;
|
454
|
+
} else {
|
455
|
+
Check_Type(vfilter, T_STRING);
|
456
|
+
filter = RSTRING_PTR(vfilter);
|
457
|
+
}
|
458
|
+
opt = RTEST(optimize);
|
459
|
+
|
460
|
+
/* operation */
|
461
|
+
if (pcap_compile(cap->pcap, &program, filter,
|
462
|
+
opt, cap->netmask) < 0)
|
463
|
+
rb_raise(ePcapError, "setfilter: %s", pcap_geterr(cap->pcap));
|
464
|
+
if (pcap_setfilter(cap->pcap, &program) < 0)
|
465
|
+
rb_raise(ePcapError, "setfilter: %s", pcap_geterr(cap->pcap));
|
466
|
+
|
467
|
+
return Qnil;
|
468
|
+
}
|
469
|
+
|
470
|
+
static VALUE
|
471
|
+
capture_datalink(self)
|
472
|
+
VALUE self;
|
473
|
+
{
|
474
|
+
struct capture_object *cap;
|
475
|
+
|
476
|
+
DEBUG_PRINT("capture_datalink");
|
477
|
+
GetCapture(self, cap);
|
478
|
+
|
479
|
+
return INT2NUM(pcap_datalink(cap->pcap));
|
480
|
+
}
|
481
|
+
|
482
|
+
static VALUE
|
483
|
+
capture_snapshot(self)
|
484
|
+
VALUE self;
|
485
|
+
{
|
486
|
+
struct capture_object *cap;
|
487
|
+
|
488
|
+
DEBUG_PRINT("capture_snapshot");
|
489
|
+
GetCapture(self, cap);
|
490
|
+
|
491
|
+
return INT2NUM(pcap_snapshot(cap->pcap));
|
492
|
+
}
|
493
|
+
|
494
|
+
static VALUE
|
495
|
+
capture_stats(self)
|
496
|
+
VALUE self;
|
497
|
+
{
|
498
|
+
struct capture_object *cap;
|
499
|
+
struct pcap_stat stat;
|
500
|
+
VALUE v_stat;
|
501
|
+
|
502
|
+
DEBUG_PRINT("capture_stats");
|
503
|
+
GetCapture(self, cap);
|
504
|
+
|
505
|
+
if (pcap_stats(cap->pcap, &stat) == -1)
|
506
|
+
return Qnil;
|
507
|
+
|
508
|
+
v_stat = rb_funcall(cPcapStat, rb_intern("new"), 3,
|
509
|
+
UINT2NUM(stat.ps_recv),
|
510
|
+
UINT2NUM(stat.ps_drop),
|
511
|
+
UINT2NUM(stat.ps_ifdrop));
|
512
|
+
|
513
|
+
return v_stat;
|
514
|
+
}
|
515
|
+
|
516
|
+
static VALUE
|
517
|
+
capture_inject(self, v_buf)
|
518
|
+
VALUE self;
|
519
|
+
VALUE v_buf;
|
520
|
+
{
|
521
|
+
struct capture_object *cap;
|
522
|
+
const void *buf;
|
523
|
+
size_t bufsiz;
|
524
|
+
int r;
|
525
|
+
|
526
|
+
DEBUG_PRINT("capture_inject");
|
527
|
+
GetCapture(self, cap);
|
528
|
+
|
529
|
+
Check_Type(v_buf, T_STRING);
|
530
|
+
buf = (void *)RSTRING_PTR(v_buf);
|
531
|
+
bufsiz = RSTRING_LEN(v_buf);
|
532
|
+
|
533
|
+
r = pcap_inject(cap->pcap, buf, bufsiz);
|
534
|
+
if (0 > r) {
|
535
|
+
rb_raise(ePcapError, "pcap_inject failure: %s", pcap_geterr(cap->pcap));
|
536
|
+
}
|
537
|
+
if (bufsiz != r) {
|
538
|
+
rb_raise(ePcapError, "pcap_inject expected to write %d but actually wrote %d", bufsiz, r);
|
539
|
+
}
|
540
|
+
return Qnil;
|
541
|
+
}
|
542
|
+
|
543
|
+
/*
|
544
|
+
* Dumper object
|
545
|
+
*/
|
546
|
+
|
547
|
+
struct dumper_object {
|
548
|
+
pcap_dumper_t *pcap_dumper;
|
549
|
+
int dl_type;
|
550
|
+
bpf_u_int32 snaplen;
|
551
|
+
};
|
552
|
+
|
553
|
+
static void
|
554
|
+
closed_dumper()
|
555
|
+
{
|
556
|
+
rb_raise(rb_eRuntimeError, "dumper is already closed");
|
557
|
+
}
|
558
|
+
|
559
|
+
#define GetDumper(obj, dumper) {\
|
560
|
+
Data_Get_Struct(obj, struct dumper_object, dumper);\
|
561
|
+
if (dumper->pcap_dumper == NULL) closed_dumper();\
|
562
|
+
}
|
563
|
+
|
564
|
+
/* called from GC */
|
565
|
+
static void
|
566
|
+
free_dumper(dumper)
|
567
|
+
struct dumper_object *dumper;
|
568
|
+
{
|
569
|
+
DEBUG_PRINT("free_dumper");
|
570
|
+
if (dumper->pcap_dumper != NULL) {
|
571
|
+
DEBUG_PRINT("closing dumper");
|
572
|
+
pcap_dump_close(dumper->pcap_dumper);
|
573
|
+
dumper->pcap_dumper = NULL;
|
574
|
+
}
|
575
|
+
free(dumper);
|
576
|
+
}
|
577
|
+
|
578
|
+
static VALUE
|
579
|
+
dumper_open(class, v_cap, v_fname)
|
580
|
+
VALUE class;
|
581
|
+
VALUE v_cap;
|
582
|
+
VALUE v_fname;
|
583
|
+
{
|
584
|
+
struct dumper_object *dumper;
|
585
|
+
struct capture_object *cap;
|
586
|
+
pcap_dumper_t *pcap_dumper;
|
587
|
+
VALUE self;
|
588
|
+
|
589
|
+
DEBUG_PRINT("dumper_open");
|
590
|
+
|
591
|
+
CheckClass(v_cap, cCapture);
|
592
|
+
GetCapture(v_cap, cap);
|
593
|
+
Check_SafeStr(v_fname);
|
594
|
+
|
595
|
+
pcap_dumper = pcap_dump_open(cap->pcap, RSTRING_PTR(v_fname));
|
596
|
+
if (pcap_dumper == NULL) {
|
597
|
+
rb_raise(ePcapError, "dumper_open: %s", pcap_geterr(cap->pcap));
|
598
|
+
}
|
599
|
+
|
600
|
+
self = Data_Make_Struct(class, struct dumper_object, 0,
|
601
|
+
free_dumper, dumper);
|
602
|
+
dumper->pcap_dumper = pcap_dumper;
|
603
|
+
dumper->dl_type = cap->dl_type;
|
604
|
+
dumper->snaplen = pcap_snapshot(cap->pcap);
|
605
|
+
|
606
|
+
return self;
|
607
|
+
}
|
608
|
+
|
609
|
+
static VALUE
|
610
|
+
dumper_close(self)
|
611
|
+
VALUE self;
|
612
|
+
{
|
613
|
+
struct dumper_object *dumper;
|
614
|
+
|
615
|
+
DEBUG_PRINT("dumper_close");
|
616
|
+
GetDumper(self, dumper);
|
617
|
+
|
618
|
+
pcap_dump_close(dumper->pcap_dumper);
|
619
|
+
dumper->pcap_dumper = NULL;
|
620
|
+
return Qnil;
|
621
|
+
}
|
622
|
+
|
623
|
+
static VALUE
|
624
|
+
dumper_dump(self, v_pkt)
|
625
|
+
VALUE self;
|
626
|
+
VALUE v_pkt;
|
627
|
+
{
|
628
|
+
struct dumper_object *dumper;
|
629
|
+
struct packet_object *pkt;
|
630
|
+
|
631
|
+
DEBUG_PRINT("dumper_dump");
|
632
|
+
GetDumper(self, dumper);
|
633
|
+
|
634
|
+
CheckClass(v_pkt, cPacket);
|
635
|
+
GetPacket(v_pkt, pkt);
|
636
|
+
if (pkt->hdr.dl_type != dumper->dl_type)
|
637
|
+
rb_raise(rb_eArgError, "Cannot dump this packet: data-link type mismatch");
|
638
|
+
if (pkt->hdr.pkthdr.caplen > dumper->snaplen)
|
639
|
+
rb_raise(rb_eArgError, "Cannot dump this packet: too large caplen");
|
640
|
+
|
641
|
+
pcap_dump((u_char *)dumper->pcap_dumper, &pkt->hdr.pkthdr, pkt->data);
|
642
|
+
return Qnil;
|
643
|
+
}
|
644
|
+
|
645
|
+
static VALUE
|
646
|
+
dumper_dump_raw(self, v_buf)
|
647
|
+
VALUE self;
|
648
|
+
VALUE v_buf;
|
649
|
+
{
|
650
|
+
struct dumper_object *dumper;
|
651
|
+
const u_char *buf;
|
652
|
+
struct pcap_pkthdr pkt_hdr;
|
653
|
+
|
654
|
+
DEBUG_PRINT("dumper_dump_raw");
|
655
|
+
GetDumper(self, dumper);
|
656
|
+
|
657
|
+
Check_Type(v_buf, T_STRING);
|
658
|
+
buf = (void *)RSTRING_PTR(v_buf);
|
659
|
+
|
660
|
+
gettimeofday(&(pkt_hdr.ts), NULL);
|
661
|
+
pkt_hdr.caplen = dumper->snaplen;
|
662
|
+
pkt_hdr.len = RSTRING_LEN(v_buf);
|
663
|
+
|
664
|
+
pcap_dump((u_char *)dumper->pcap_dumper, &pkt_hdr, buf);
|
665
|
+
return Qnil;
|
666
|
+
}
|
667
|
+
|
668
|
+
/*
|
669
|
+
* Filter object
|
670
|
+
*/
|
671
|
+
|
672
|
+
/* called from GC */
|
673
|
+
static void
|
674
|
+
mark_filter(filter)
|
675
|
+
struct filter_object *filter;
|
676
|
+
{
|
677
|
+
rb_gc_mark(filter->param);
|
678
|
+
rb_gc_mark(filter->optimize);
|
679
|
+
rb_gc_mark(filter->netmask);
|
680
|
+
}
|
681
|
+
|
682
|
+
static void
|
683
|
+
free_filter(filter)
|
684
|
+
struct filter_object *filter;
|
685
|
+
{
|
686
|
+
free(filter->expr);
|
687
|
+
free(filter);
|
688
|
+
/*
|
689
|
+
* This cause memory leak because filter->program hold some memory.
|
690
|
+
* We overlook it because libpcap does not implement pcap_freecode().
|
691
|
+
*/
|
692
|
+
}
|
693
|
+
|
694
|
+
static VALUE
|
695
|
+
filter_new(argc, argv, class)
|
696
|
+
int argc;
|
697
|
+
VALUE *argv;
|
698
|
+
VALUE class;
|
699
|
+
{
|
700
|
+
VALUE self, v_expr, v_optimize, v_capture, v_netmask;
|
701
|
+
struct filter_object *filter;
|
702
|
+
struct capture_object *capture;
|
703
|
+
pcap_t *pcap;
|
704
|
+
char *expr;
|
705
|
+
int n, optimize, snaplen, linktype;
|
706
|
+
bpf_u_int32 netmask;
|
707
|
+
|
708
|
+
n = rb_scan_args(argc, argv, "13", &v_expr, &v_capture,
|
709
|
+
&v_optimize, &v_netmask);
|
710
|
+
/* filter expression */
|
711
|
+
Check_Type(v_expr, T_STRING);
|
712
|
+
expr = StringValuePtr(v_expr);
|
713
|
+
/* capture object */
|
714
|
+
if (IsKindOf(v_capture, cCapture)) {
|
715
|
+
CheckClass(v_capture, cCapture);
|
716
|
+
GetCapture(v_capture, capture);
|
717
|
+
pcap = capture->pcap;
|
718
|
+
} else if (NIL_P(v_capture)) {
|
719
|
+
/* assume most common case */
|
720
|
+
snaplen = DEFAULT_SNAPLEN;
|
721
|
+
linktype = DEFAULT_DATALINK;
|
722
|
+
pcap = 0;
|
723
|
+
} else {
|
724
|
+
snaplen = NUM2INT(rb_funcall(v_capture, rb_intern("[]"), 1, INT2FIX(0)));
|
725
|
+
linktype = NUM2INT(rb_funcall(v_capture, rb_intern("[]"), 1, INT2FIX(1)));
|
726
|
+
pcap = 0;
|
727
|
+
}
|
728
|
+
/* optimize flag */
|
729
|
+
optimize = 1;
|
730
|
+
if (n >= 3) {
|
731
|
+
optimize = RTEST(v_optimize);
|
732
|
+
}
|
733
|
+
/* netmask */
|
734
|
+
netmask = 0;
|
735
|
+
if (n >= 4) {
|
736
|
+
bpf_u_int32 mask = NUM2UINT(v_netmask);
|
737
|
+
netmask = htonl(mask);
|
738
|
+
}
|
739
|
+
|
740
|
+
filter = (struct filter_object *)xmalloc(sizeof(struct filter_object));
|
741
|
+
if (pcap) {
|
742
|
+
if (pcap_compile(pcap, &filter->program, expr, optimize, netmask) < 0)
|
743
|
+
rb_raise(ePcapError, "%s", pcap_geterr(pcap));
|
744
|
+
filter->datalink = pcap_datalink(pcap);
|
745
|
+
filter->snaplen = pcap_snapshot(pcap);
|
746
|
+
} else {
|
747
|
+
#ifdef HAVE_PCAP_COMPILE_NOPCAP
|
748
|
+
if (pcap_compile_nopcap(snaplen, linktype, &filter->program, expr, optimize, netmask) < 0)
|
749
|
+
/* libpcap-0.5 provides no error report for pcap_compile_nopcap */
|
750
|
+
rb_raise(ePcapError, "pcap_compile_nopcap error");
|
751
|
+
filter->datalink = linktype;
|
752
|
+
filter->snaplen = snaplen;
|
753
|
+
#else
|
754
|
+
rb_raise(rb_eArgError, "pcap_compile_nopcap needs libpcap-0.5 or later");
|
755
|
+
#endif
|
756
|
+
}
|
757
|
+
self = Data_Wrap_Struct(class, mark_filter, free_filter, filter);
|
758
|
+
filter->expr = strdup(expr);
|
759
|
+
filter->param = v_capture;
|
760
|
+
filter->optimize = optimize ? Qtrue : Qfalse;
|
761
|
+
filter->netmask = INT2NUM(ntohl(netmask));
|
762
|
+
|
763
|
+
return self;
|
764
|
+
}
|
765
|
+
|
766
|
+
VALUE
|
767
|
+
filter_match(self, v_pkt)
|
768
|
+
VALUE self, v_pkt;
|
769
|
+
{
|
770
|
+
struct filter_object *filter;
|
771
|
+
struct packet_object *pkt;
|
772
|
+
struct pcap_pkthdr *h;
|
773
|
+
|
774
|
+
GetFilter(self, filter);
|
775
|
+
CheckClass(v_pkt, cPacket);
|
776
|
+
GetPacket(v_pkt, pkt);
|
777
|
+
h = &pkt->hdr.pkthdr;
|
778
|
+
|
779
|
+
if (filter->datalink != pkt->hdr.dl_type)
|
780
|
+
rb_raise(rb_eRuntimeError, "Incompatible datalink type");
|
781
|
+
if (filter->snaplen < h->caplen)
|
782
|
+
rb_raise(rb_eRuntimeError, "Incompatible snaplen");
|
783
|
+
|
784
|
+
if (bpf_filter(filter->program.bf_insns, pkt->data, h->len, h->caplen))
|
785
|
+
return Qtrue;
|
786
|
+
else
|
787
|
+
return Qfalse;
|
788
|
+
}
|
789
|
+
|
790
|
+
static VALUE
|
791
|
+
filter_source(self)
|
792
|
+
VALUE self;
|
793
|
+
{
|
794
|
+
struct filter_object *filter;
|
795
|
+
|
796
|
+
GetFilter(self, filter);
|
797
|
+
return rb_str_new2(filter->expr);
|
798
|
+
}
|
799
|
+
|
800
|
+
static VALUE
|
801
|
+
new_filter(expr, param, optimize, netmask)
|
802
|
+
char *expr;
|
803
|
+
VALUE param, optimize, netmask;
|
804
|
+
{
|
805
|
+
return rb_funcall(cFilter,
|
806
|
+
rb_intern("new"), 4,
|
807
|
+
rb_str_new2(expr), param, optimize, netmask);
|
808
|
+
}
|
809
|
+
|
810
|
+
static VALUE
|
811
|
+
filter_or(self, other)
|
812
|
+
VALUE self, other;
|
813
|
+
{
|
814
|
+
struct filter_object *filter, *filter2;
|
815
|
+
char *expr;
|
816
|
+
|
817
|
+
CheckClass(other, cFilter);
|
818
|
+
GetFilter(self, filter);
|
819
|
+
GetFilter(other, filter2);
|
820
|
+
|
821
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + strlen(filter2->expr) + 16);
|
822
|
+
sprintf(expr, "( %s ) or ( %s )", filter->expr, filter2->expr);
|
823
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
824
|
+
}
|
825
|
+
|
826
|
+
static VALUE
|
827
|
+
filter_and(self, other)
|
828
|
+
VALUE self, other;
|
829
|
+
{
|
830
|
+
struct filter_object *filter, *filter2;
|
831
|
+
char *expr;
|
832
|
+
|
833
|
+
CheckClass(other, cFilter);
|
834
|
+
GetFilter(self, filter);
|
835
|
+
GetFilter(other, filter2);
|
836
|
+
|
837
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + strlen(filter2->expr) + 16);
|
838
|
+
sprintf(expr, "( %s ) and ( %s )", filter->expr, filter2->expr);
|
839
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
840
|
+
}
|
841
|
+
|
842
|
+
static VALUE
|
843
|
+
filter_not(self)
|
844
|
+
VALUE self;
|
845
|
+
{
|
846
|
+
struct filter_object *filter;
|
847
|
+
char *expr;
|
848
|
+
|
849
|
+
GetFilter(self, filter);
|
850
|
+
expr = ALLOCA_N(char, strlen(filter->expr) + 16);
|
851
|
+
sprintf(expr, "not ( %s )", filter->expr);
|
852
|
+
return new_filter(expr, filter->param, filter->optimize, filter->netmask);
|
853
|
+
}
|
854
|
+
|
855
|
+
/*
|
856
|
+
* Class definition
|
857
|
+
*/
|
858
|
+
|
859
|
+
void
|
860
|
+
Init_pcap(void)
|
861
|
+
{
|
862
|
+
DEBUG_PRINT("Init_pcap");
|
863
|
+
|
864
|
+
/* define module Pcap */
|
865
|
+
mPcap = rb_define_module("Pcap");
|
866
|
+
rb_define_module_function(mPcap, "lookupdev", pcap_s_lookupdev, 0);
|
867
|
+
rb_define_module_function(mPcap, "findalldevs", pcap_s_findalldevs, 0);
|
868
|
+
rb_define_module_function(mPcap, "lookupnet", pcap_s_lookupnet, 1);
|
869
|
+
rb_global_variable(&rbpcap_convert);
|
870
|
+
rb_define_singleton_method(mPcap, "convert?", pcap_s_convert, 0);
|
871
|
+
rb_define_singleton_method(mPcap, "convert=", pcap_s_convert_set, 1);
|
872
|
+
rb_define_const(mPcap, "DLT_NULL", INT2NUM(DLT_NULL));
|
873
|
+
rb_define_const(mPcap, "DLT_EN10MB", INT2NUM(DLT_EN10MB));
|
874
|
+
rb_define_const(mPcap, "DLT_EN3MB", INT2NUM(DLT_EN3MB));
|
875
|
+
rb_define_const(mPcap, "DLT_AX25", INT2NUM(DLT_AX25));
|
876
|
+
rb_define_const(mPcap, "DLT_PRONET", INT2NUM(DLT_PRONET));
|
877
|
+
rb_define_const(mPcap, "DLT_CHAOS", INT2NUM(DLT_CHAOS));
|
878
|
+
rb_define_const(mPcap, "DLT_IEEE802", INT2NUM(DLT_IEEE802));
|
879
|
+
rb_define_const(mPcap, "DLT_ARCNET", INT2NUM(DLT_ARCNET));
|
880
|
+
rb_define_const(mPcap, "DLT_SLIP", INT2NUM(DLT_SLIP));
|
881
|
+
rb_define_const(mPcap, "DLT_PPP", INT2NUM(DLT_PPP));
|
882
|
+
rb_define_const(mPcap, "DLT_FDDI", INT2NUM(DLT_FDDI));
|
883
|
+
rb_define_const(mPcap, "DLT_ATM_RFC1483", INT2NUM(DLT_ATM_RFC1483));
|
884
|
+
#ifdef DLT_RAW
|
885
|
+
rb_define_const(mPcap, "DLT_RAW", INT2NUM(DLT_RAW));
|
886
|
+
rb_define_const(mPcap, "DLT_SLIP_BSDOS", INT2NUM(DLT_SLIP_BSDOS));
|
887
|
+
rb_define_const(mPcap, "DLT_PPP_BSDOS", INT2NUM(DLT_PPP_BSDOS));
|
888
|
+
#endif
|
889
|
+
|
890
|
+
/* define class Capture */
|
891
|
+
cCapture = rb_define_class_under(mPcap, "Capture", rb_cObject);
|
892
|
+
rb_include_module(cCapture, rb_mEnumerable);
|
893
|
+
rb_define_singleton_method(cCapture, "open_live", capture_open_live, -1);
|
894
|
+
rb_define_singleton_method(cCapture, "open_offline", capture_open_offline, 1);
|
895
|
+
rb_define_singleton_method(cCapture, "open_dead", capture_open_dead, -1);
|
896
|
+
rb_define_method(cCapture, "close", capture_close, 0);
|
897
|
+
rb_define_method(cCapture, "dispatch", capture_dispatch, -1);
|
898
|
+
rb_define_method(cCapture, "loop", capture_loop, -1);
|
899
|
+
rb_define_method(cCapture, "each_packet", capture_loop, -1);
|
900
|
+
rb_define_method(cCapture, "each", capture_loop, -1);
|
901
|
+
rb_define_method(cCapture, "fh", capture_fh, -1);
|
902
|
+
rb_define_method(cCapture, "setfilter", capture_setfilter, -1);
|
903
|
+
rb_define_method(cCapture, "datalink", capture_datalink, 0);
|
904
|
+
rb_define_method(cCapture, "snapshot", capture_snapshot, 0);
|
905
|
+
rb_define_method(cCapture, "snaplen", capture_snapshot, 0);
|
906
|
+
rb_define_method(cCapture, "stats", capture_stats, 0);
|
907
|
+
rb_define_method(cCapture, "inject", capture_inject, 1);
|
908
|
+
|
909
|
+
/* define class Dumper */
|
910
|
+
cDumper = rb_define_class_under(mPcap, "Dumper", rb_cObject);
|
911
|
+
rb_define_singleton_method(cDumper, "open", dumper_open, 2);
|
912
|
+
rb_define_method(cDumper, "close", dumper_close, 0);
|
913
|
+
rb_define_method(cDumper, "dump", dumper_dump, 1);
|
914
|
+
rb_define_method(cDumper, "dump_raw", dumper_dump_raw, 1);
|
915
|
+
|
916
|
+
/* define class Filter */
|
917
|
+
cFilter = rb_define_class_under(mPcap, "Filter", rb_cObject);
|
918
|
+
rb_define_singleton_method(cFilter, "new", filter_new, -1);
|
919
|
+
rb_define_singleton_method(cFilter, "compile", filter_new, -1);
|
920
|
+
rb_define_method(cFilter, "=~", filter_match, 1);
|
921
|
+
rb_define_method(cFilter, "===", filter_match, 1);
|
922
|
+
rb_define_method(cFilter, "source", filter_source, 0);
|
923
|
+
rb_define_method(cFilter, "|", filter_or, 1);
|
924
|
+
rb_define_method(cFilter, "&", filter_and, 1);
|
925
|
+
rb_define_method(cFilter, "~@", filter_not, 0);
|
926
|
+
/*rb_define_method(cFilter, "&", filter_and, 1);*/
|
927
|
+
|
928
|
+
/* define class PcapStat */
|
929
|
+
cPcapStat = rb_struct_define(NULL, "recv", "drop", "ifdrop", NULL);
|
930
|
+
rb_define_const(mPcap, "Stat", cPcapStat);
|
931
|
+
|
932
|
+
/* define exception classes */
|
933
|
+
ePcapError = rb_define_class_under(mPcap, "PcapError", rb_eStandardError);
|
934
|
+
eTruncatedPacket = rb_define_class_under(mPcap, "TruncatedPacket", ePcapError);
|
935
|
+
|
936
|
+
Init_packet();
|
937
|
+
rb_f_require(Qnil, rb_str_new2("pcap_misc"));
|
938
|
+
}
|