rb-pcap 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +10 -0
- data/ext/extconf.rb +6 -0
- data/ext/rb_pcap.c +29 -0
- data/ext/rb_pcap.h +12 -0
- data/ext/rb_pcap_capture.c +365 -0
- data/ext/rb_pcap_capture.h +53 -0
- data/ext/rb_pcap_filter.c +85 -0
- data/ext/rb_pcap_filter.h +28 -0
- data/lib/rb-pcap.rb +1 -0
- metadata +64 -0
data/README.markdown
ADDED
data/ext/extconf.rb
ADDED
data/ext/rb_pcap.c
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "rb_pcap.h"
|
2
|
+
|
3
|
+
void Init_rb_pcap() {
|
4
|
+
cCapture = rb_define_class("Capture", rb_cObject);
|
5
|
+
rb_include_module(cCapture, rb_mEnumerable);
|
6
|
+
rb_define_singleton_method(cCapture, "open", capture_open, -1);
|
7
|
+
rb_define_singleton_method(cCapture, "open_offline", capture_open_offline, 1);
|
8
|
+
rb_define_method(cCapture, "close", capture_close, 0);
|
9
|
+
rb_define_method(cCapture, "dispatch", capture_dispatch, -1);
|
10
|
+
rb_define_method(cCapture, "each", capture_loop, -1);
|
11
|
+
rb_define_method(cCapture, "each_packet", capture_loop, -1);
|
12
|
+
rb_define_method(cCapture, "filter=", capture_setfilter, 1);
|
13
|
+
rb_define_method(cCapture, "limit", capture_getlimit, 0);
|
14
|
+
rb_define_method(cCapture, "limit=", capture_setlimit, 1);
|
15
|
+
rb_define_method(cCapture, "dissector", capture_getdissector, 0);
|
16
|
+
rb_define_method(cCapture, "dissector=", capture_setdissector, 0);
|
17
|
+
rb_define_method(cCapture, "datalink", capture_datalink, 0);
|
18
|
+
rb_define_method(cCapture, "snapshot_length", capture_snapshot, 0);
|
19
|
+
|
20
|
+
cFilter = rb_define_class_under(cCapture, "Filter", rb_cObject);
|
21
|
+
rb_define_alloc_func(cFilter, filter_alloc);
|
22
|
+
rb_define_method(cFilter, "initialize", filter_init, -1);
|
23
|
+
rb_define_method(cFilter, "expression", filter_source, 0);
|
24
|
+
rb_define_method(cFilter, "=~", filter_match, 1);
|
25
|
+
rb_define_method(cFilter, "===", filter_match, 1);
|
26
|
+
|
27
|
+
eCaptureError = rb_define_class_under(cCapture, "CaptureError", rb_eStandardError);
|
28
|
+
eTruncatedPacket = rb_define_class_under(cCapture, "TruncatedPacket", eCaptureError);
|
29
|
+
}
|
data/ext/rb_pcap.h
ADDED
@@ -0,0 +1,365 @@
|
|
1
|
+
#include "rb_pcap_capture.h"
|
2
|
+
|
3
|
+
void closed_capture()
|
4
|
+
{
|
5
|
+
rb_raise(rb_eRuntimeError, "device is already closed");
|
6
|
+
}
|
7
|
+
|
8
|
+
void free_capture(struct capture_object *cap)
|
9
|
+
{
|
10
|
+
if (cap->pcap != NULL) {
|
11
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
12
|
+
pcap_close(cap->pcap);
|
13
|
+
cap->pcap = NULL;
|
14
|
+
}
|
15
|
+
|
16
|
+
free(cap);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE capture_close(VALUE self)
|
20
|
+
{
|
21
|
+
struct capture_object *cap;
|
22
|
+
|
23
|
+
GetCapture(self, cap);
|
24
|
+
|
25
|
+
if (cap->dumper) {
|
26
|
+
pcap_dump_close(cap->dumper);
|
27
|
+
}
|
28
|
+
|
29
|
+
rb_thread_fd_close(pcap_fileno(cap->pcap));
|
30
|
+
pcap_close(cap->pcap);
|
31
|
+
cap->pcap = NULL;
|
32
|
+
return Qnil;
|
33
|
+
}
|
34
|
+
|
35
|
+
VALUE capture_setfilter(VALUE self, VALUE v_filter)
|
36
|
+
{
|
37
|
+
struct capture_object *cap;
|
38
|
+
struct bpf_program program;
|
39
|
+
|
40
|
+
GetCapture(self, cap);
|
41
|
+
|
42
|
+
if (IsKindOf(v_filter, cFilter)) {
|
43
|
+
struct filter_object *f;
|
44
|
+
GetFilter(v_filter, f);
|
45
|
+
program = f->program;
|
46
|
+
} else {
|
47
|
+
Check_Type(v_filter, T_STRING);
|
48
|
+
char *filter = RSTRING(v_filter)->ptr;
|
49
|
+
|
50
|
+
if (pcap_compile(cap->pcap, &program, filter, 1, cap->netmask) < 0) {
|
51
|
+
rb_raise(eCaptureError, "setfilter: %s", pcap_geterr(cap->pcap));
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
if (pcap_setfilter(cap->pcap, &program) < 0) {
|
56
|
+
rb_raise(eCaptureError, "setfilter: %s", pcap_geterr(cap->pcap));
|
57
|
+
}
|
58
|
+
|
59
|
+
return v_filter;
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
VALUE capture_setdissector(VALUE self, VALUE dissector)
|
64
|
+
{
|
65
|
+
if (!(IsKindOf(dissector, rb_cProc) || dissector == Qnil)) {
|
66
|
+
rb_raise(rb_eArgError, "dissector must be proc or nil");
|
67
|
+
}
|
68
|
+
|
69
|
+
struct capture_object *cap;
|
70
|
+
GetCapture(self, cap);
|
71
|
+
|
72
|
+
cap->dissector = dissector;
|
73
|
+
|
74
|
+
return dissector;
|
75
|
+
}
|
76
|
+
|
77
|
+
VALUE capture_open(int argc, VALUE *argv, VALUE class)
|
78
|
+
{
|
79
|
+
VALUE v_device, v_snaplen = Qnil, v_promisc = Qnil, v_to_ms = Qnil, v_filter = Qnil, v_limit = Qnil, v_dissector = Qnil, v_dump = Qnil;
|
80
|
+
char *device;
|
81
|
+
char *dump;
|
82
|
+
int snaplen, promisc, to_ms;
|
83
|
+
int rs;
|
84
|
+
VALUE self;
|
85
|
+
struct capture_object *cap;
|
86
|
+
pcap_t *pcap;
|
87
|
+
bpf_u_int32 net, netmask;
|
88
|
+
|
89
|
+
rs = rb_scan_args(argc, argv, "13", &v_device, &v_snaplen,&v_promisc, &v_to_ms);
|
90
|
+
|
91
|
+
if (IsKindOf(v_device, rb_cHash)) {
|
92
|
+
v_snaplen = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("snapshot_length")));
|
93
|
+
v_to_ms = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("timeout")));
|
94
|
+
v_promisc = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("promiscuous")));
|
95
|
+
v_limit = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("limit")));
|
96
|
+
v_filter = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("filter")));
|
97
|
+
v_dissector = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("dissector")));
|
98
|
+
v_dump = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("dump")));
|
99
|
+
v_device = rb_funcall(v_device, rb_intern("[]"), 1, ID2SYM(rb_intern("device")));
|
100
|
+
|
101
|
+
if (v_device == Qnil) {
|
102
|
+
rb_raise(rb_eArgError, ":device must be specified");
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
Check_SafeStr(v_device);
|
107
|
+
device = RSTRING(v_device)->ptr;
|
108
|
+
|
109
|
+
if (v_snaplen != Qnil) {
|
110
|
+
Check_Type(v_snaplen, T_FIXNUM);
|
111
|
+
snaplen = FIX2INT(v_snaplen);
|
112
|
+
} else {
|
113
|
+
snaplen = DEFAULT_SNAPLEN;
|
114
|
+
}
|
115
|
+
|
116
|
+
if (snaplen < 0) {
|
117
|
+
rb_raise(rb_eArgError, "invalid snaplen");
|
118
|
+
}
|
119
|
+
|
120
|
+
if (v_promisc != Qnil) {
|
121
|
+
promisc = RTEST(v_promisc);
|
122
|
+
} else {
|
123
|
+
promisc = DEFAULT_PROMISC;
|
124
|
+
}
|
125
|
+
|
126
|
+
if (v_to_ms != Qnil) {
|
127
|
+
Check_Type(v_to_ms, T_FIXNUM);
|
128
|
+
to_ms = FIX2INT(v_to_ms);
|
129
|
+
} else {
|
130
|
+
to_ms = DEFAULT_TO_MS;
|
131
|
+
}
|
132
|
+
|
133
|
+
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
134
|
+
|
135
|
+
pcap = pcap_open_live(device, snaplen, promisc, to_ms, pcap_errbuf);
|
136
|
+
|
137
|
+
if (pcap == NULL) {
|
138
|
+
rb_raise(eCaptureError, "%s", pcap_errbuf);
|
139
|
+
}
|
140
|
+
|
141
|
+
if (pcap_lookupnet(device, &net, &netmask, pcap_errbuf) == -1) {
|
142
|
+
netmask = 0;
|
143
|
+
rb_warning("cannot lookup net: %s\n", pcap_errbuf);
|
144
|
+
}
|
145
|
+
|
146
|
+
self = Data_Make_Struct(class, struct capture_object, 0, free_capture, cap);
|
147
|
+
cap->pcap = pcap;
|
148
|
+
cap->netmask = netmask;
|
149
|
+
cap->dl_type = pcap_datalink(pcap);
|
150
|
+
capture_setdissector(self, v_dissector);
|
151
|
+
|
152
|
+
if (v_dump != Qnil) {
|
153
|
+
Check_Type(v_dump, T_STRING);
|
154
|
+
cap->dumper = pcap_dump_open(cap->pcap, RSTRING(v_dump)->ptr);
|
155
|
+
} else {
|
156
|
+
cap->dumper = NULL;
|
157
|
+
}
|
158
|
+
|
159
|
+
if (v_limit != Qnil) {
|
160
|
+
Check_Type(v_limit, T_FIXNUM);
|
161
|
+
cap->limit = FIX2INT(v_limit);
|
162
|
+
} else {
|
163
|
+
cap->limit = -1;
|
164
|
+
}
|
165
|
+
|
166
|
+
if (v_filter != Qnil) {
|
167
|
+
capture_setfilter(self, v_filter);
|
168
|
+
}
|
169
|
+
|
170
|
+
if (rb_block_given_p()) {
|
171
|
+
rb_yield(self);
|
172
|
+
capture_close(self);
|
173
|
+
return Qnil;
|
174
|
+
} else
|
175
|
+
return self;
|
176
|
+
}
|
177
|
+
|
178
|
+
VALUE capture_open_offline(VALUE class, VALUE fname)
|
179
|
+
{
|
180
|
+
VALUE self;
|
181
|
+
struct capture_object *cap;
|
182
|
+
pcap_t *pcap;
|
183
|
+
|
184
|
+
/* open offline */
|
185
|
+
Check_SafeStr(fname);
|
186
|
+
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
187
|
+
pcap = pcap_open_offline(RSTRING(fname)->ptr, pcap_errbuf);
|
188
|
+
if (pcap == NULL) {
|
189
|
+
rb_raise(eCaptureError, "%s", pcap_errbuf);
|
190
|
+
}
|
191
|
+
|
192
|
+
/* setup instance */
|
193
|
+
self = Data_Make_Struct(class, struct capture_object, 0, free_capture, cap);
|
194
|
+
cap->pcap = pcap;
|
195
|
+
cap->netmask = 0;
|
196
|
+
cap->dl_type = pcap_datalink(pcap);
|
197
|
+
|
198
|
+
return self;
|
199
|
+
}
|
200
|
+
|
201
|
+
void handler1(struct capture_object *cap, const struct pcap_pkthdr *pkthdr, const u_char *data)
|
202
|
+
{
|
203
|
+
if (cap->dissector != Qnil) {
|
204
|
+
VALUE dissected = rb_funcall(cap->dissector, rb_intern("call"), 1, rb_str_new((char *)data, pkthdr->caplen));
|
205
|
+
|
206
|
+
rb_yield_values(1, dissected); // not sure why rb_yield doesn't work here, but it wasn't for me
|
207
|
+
} else
|
208
|
+
rb_yield_values(1, rb_str_new((char *)data, pkthdr->caplen));
|
209
|
+
}
|
210
|
+
|
211
|
+
|
212
|
+
void handler2(struct capture_object *cap, const struct pcap_pkthdr *pkthdr, const u_char *data)
|
213
|
+
{
|
214
|
+
if (cap->dissector != Qnil) {
|
215
|
+
VALUE dissected = rb_funcall(cap->dissector, rb_intern("call"), 1, rb_str_new((char *)data, pkthdr->caplen));
|
216
|
+
|
217
|
+
rb_yield_values(2, dissected, rb_time_new(pkthdr->ts.tv_sec, pkthdr->ts.tv_usec));
|
218
|
+
} else
|
219
|
+
rb_yield_values(2, rb_str_new((char *)data, pkthdr->caplen), rb_time_new(pkthdr->ts.tv_sec, pkthdr->ts.tv_usec));
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE capture_dispatch(int argc, VALUE *argv, VALUE self)
|
223
|
+
{
|
224
|
+
VALUE v_cnt;
|
225
|
+
int cnt;
|
226
|
+
struct capture_object *cap;
|
227
|
+
int ret;
|
228
|
+
|
229
|
+
GetCapture(self, cap);
|
230
|
+
|
231
|
+
if (cap->dumper == NULL) {
|
232
|
+
rb_raise(rb_eRuntimeError, "No dump file specified, use each to retrieve packets.");
|
233
|
+
}
|
234
|
+
|
235
|
+
/*VALUE proc = rb_block_proc();
|
236
|
+
VALUE v_arity = rb_funcall(proc, rb_intern("arity"), 0);
|
237
|
+
|
238
|
+
int arity = FIX2INT(v_arity);
|
239
|
+
|
240
|
+
pcap_handler handler = (arity < 2) ? (pcap_handler)handler1 : (pcap_handler)handler2;
|
241
|
+
*/
|
242
|
+
|
243
|
+
/* scan arg */
|
244
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
245
|
+
FIXNUM_P(v_cnt);
|
246
|
+
cnt = FIX2INT(v_cnt);
|
247
|
+
} else {
|
248
|
+
cnt = -1;
|
249
|
+
}
|
250
|
+
|
251
|
+
TRAP_BEG;
|
252
|
+
ret = pcap_dispatch(cap->pcap, cnt, pcap_dump, (u_char *)cap->dumper);
|
253
|
+
TRAP_END;
|
254
|
+
|
255
|
+
if (ret == -1)
|
256
|
+
rb_raise(eCaptureError, "dispatch: %s", pcap_geterr(cap->pcap));
|
257
|
+
|
258
|
+
return INT2FIX(ret);
|
259
|
+
}
|
260
|
+
|
261
|
+
VALUE capture_loop(int argc, VALUE *argv, VALUE self)
|
262
|
+
{
|
263
|
+
VALUE v_cnt;
|
264
|
+
int cnt;
|
265
|
+
struct capture_object *cap;
|
266
|
+
int ret;
|
267
|
+
|
268
|
+
GetCapture(self, cap);
|
269
|
+
|
270
|
+
VALUE proc = rb_block_proc();
|
271
|
+
VALUE v_arity = rb_funcall(proc, rb_intern("arity"), 0);
|
272
|
+
|
273
|
+
int arity = FIX2INT(v_arity);
|
274
|
+
|
275
|
+
pcap_handler handler = (arity < 2) ? (pcap_handler)handler1 : (pcap_handler)handler2;
|
276
|
+
|
277
|
+
/* scan arg */
|
278
|
+
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
|
279
|
+
FIXNUM_P(v_cnt);
|
280
|
+
cnt = FIX2INT(v_cnt);
|
281
|
+
} else
|
282
|
+
cnt = cap->limit;
|
283
|
+
|
284
|
+
if (pcap_file(cap->pcap) != NULL) {
|
285
|
+
TRAP_BEG;
|
286
|
+
ret = pcap_loop(cap->pcap, cnt, handler, (u_char *)cap);
|
287
|
+
TRAP_END;
|
288
|
+
} else {
|
289
|
+
int fd = pcap_fileno(cap->pcap);
|
290
|
+
fd_set rset;
|
291
|
+
struct timeval tm;
|
292
|
+
|
293
|
+
FD_ZERO(&rset);
|
294
|
+
tm.tv_sec = 0;
|
295
|
+
tm.tv_usec = 0;
|
296
|
+
for (;;) {
|
297
|
+
do {
|
298
|
+
FD_SET(fd, &rset);
|
299
|
+
if (select(fd+1, &rset, NULL, NULL, &tm) == 0) {
|
300
|
+
rb_thread_wait_fd(fd);
|
301
|
+
}
|
302
|
+
TRAP_BEG;
|
303
|
+
ret = pcap_read(cap->pcap, 1, handler, (u_char *)cap);
|
304
|
+
TRAP_END;
|
305
|
+
} while (ret == 0);
|
306
|
+
if (ret <= 0)
|
307
|
+
break;
|
308
|
+
if (cnt > 0) {
|
309
|
+
cnt -= ret;
|
310
|
+
if (cnt <= 0)
|
311
|
+
break;
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
return INT2FIX(ret);
|
317
|
+
}
|
318
|
+
|
319
|
+
VALUE capture_datalink(VALUE self)
|
320
|
+
{
|
321
|
+
struct capture_object *cap;
|
322
|
+
|
323
|
+
GetCapture(self, cap);
|
324
|
+
|
325
|
+
return INT2NUM(pcap_datalink(cap->pcap));
|
326
|
+
}
|
327
|
+
|
328
|
+
VALUE capture_snapshot(VALUE self)
|
329
|
+
{
|
330
|
+
struct capture_object *cap;
|
331
|
+
|
332
|
+
GetCapture(self, cap);
|
333
|
+
|
334
|
+
return INT2NUM(pcap_snapshot(cap->pcap));
|
335
|
+
}
|
336
|
+
|
337
|
+
VALUE capture_getlimit(VALUE self)
|
338
|
+
{
|
339
|
+
struct capture_object *cap;
|
340
|
+
GetCapture(self, cap);
|
341
|
+
|
342
|
+
return INT2FIX(cap->limit);
|
343
|
+
}
|
344
|
+
|
345
|
+
|
346
|
+
VALUE capture_setlimit(VALUE self, VALUE limit)
|
347
|
+
{
|
348
|
+
Check_Type(limit, T_FIXNUM);
|
349
|
+
|
350
|
+
struct capture_object *cap;
|
351
|
+
GetCapture(self, cap);
|
352
|
+
|
353
|
+
cap->limit = FIX2INT(limit);
|
354
|
+
|
355
|
+
return limit;
|
356
|
+
}
|
357
|
+
|
358
|
+
VALUE capture_getdissector(VALUE self)
|
359
|
+
{
|
360
|
+
struct capture_object *cap;
|
361
|
+
GetCapture(self, cap);
|
362
|
+
|
363
|
+
return cap->dissector;
|
364
|
+
}
|
365
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#ifndef __RB_PCAP_CAPTURE_H__
|
2
|
+
#define __RB_PCAP_CAPTURE_H__
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <rubysig.h>
|
6
|
+
#include <pcap.h>
|
7
|
+
|
8
|
+
#include "rb_pcap_filter.h"
|
9
|
+
|
10
|
+
#define DEFAULT_DATALINK DLT_EN10MB
|
11
|
+
#define DEFAULT_SNAPLEN 256
|
12
|
+
#define DEFAULT_PROMISC 1
|
13
|
+
#define DEFAULT_TO_MS 1000
|
14
|
+
|
15
|
+
extern VALUE eCaptureError;
|
16
|
+
extern VALUE eTruncatedPacket;
|
17
|
+
extern VALUE cCapture;
|
18
|
+
|
19
|
+
struct capture_object {
|
20
|
+
pcap_t *pcap;
|
21
|
+
pcap_dumper_t *dumper;
|
22
|
+
int limit;
|
23
|
+
bpf_u_int32 netmask;
|
24
|
+
int dl_type;
|
25
|
+
VALUE dissector;
|
26
|
+
};
|
27
|
+
|
28
|
+
#define GetFilter(obj, filter) Data_Get_Struct(obj, struct filter_object, filter)
|
29
|
+
#define GetPacket(obj, pkt) Data_Get_Struct(obj, struct packet_object, pkt)
|
30
|
+
#define GetCapture(obj, cap) { Data_Get_Struct(obj, struct capture_object, cap); if (cap->pcap == NULL) closed_capture(); }
|
31
|
+
#define Caplen(pkt, from) ((pkt)->hdr.pkthdr.caplen - (from))
|
32
|
+
#define CheckTruncate(pkt, from, need, emsg) ((from) + (need) > (pkt)->hdr.pkthdr.caplen ? rb_raise(eTruncatedPacket, (emsg)) : 0)
|
33
|
+
#define IsKindOf(v, class) RTEST(rb_obj_is_kind_of(v, class))
|
34
|
+
#define CheckClass(v, class) ((IsKindOf(v, class)) ? 0 : rb_raise(rb_eTypeError, "wrong type %s (expected %s)", rb_class2name(CLASS_OF(v)), rb_class2name(class)))
|
35
|
+
|
36
|
+
void closed_capture();
|
37
|
+
void free_capture(struct capture_object *cap);
|
38
|
+
VALUE capture_close(VALUE self);
|
39
|
+
VALUE capture_setfilter(VALUE self, VALUE v_filter);
|
40
|
+
VALUE capture_setdissector(VALUE self, VALUE dissector);
|
41
|
+
VALUE capture_open(int argc, VALUE *argv, VALUE class);
|
42
|
+
VALUE capture_open_offline(VALUE class, VALUE fname);
|
43
|
+
void handler1(struct capture_object *cap, const struct pcap_pkthdr *pkthdr, const u_char *data);
|
44
|
+
void handler2(struct capture_object *cap, const struct pcap_pkthdr *pkthdr, const u_char *data);
|
45
|
+
VALUE capture_dispatch(int argc, VALUE *argv, VALUE self);
|
46
|
+
VALUE capture_loop(int argc, VALUE *argv, VALUE self);
|
47
|
+
VALUE capture_datalink(VALUE self);
|
48
|
+
VALUE capture_snapshot(VALUE self);
|
49
|
+
VALUE capture_getlimit(VALUE self);
|
50
|
+
VALUE capture_setlimit(VALUE self, VALUE limit);
|
51
|
+
VALUE capture_getdissector(VALUE self);
|
52
|
+
|
53
|
+
#endif
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#include "rb_pcap_filter.h"
|
2
|
+
|
3
|
+
void free_filter(struct filter_object *filter)
|
4
|
+
{
|
5
|
+
free(filter->expr);
|
6
|
+
free(filter);
|
7
|
+
}
|
8
|
+
|
9
|
+
VALUE filter_alloc(VALUE self)
|
10
|
+
{
|
11
|
+
struct filter_object *filter = (struct filter_object *)xmalloc(sizeof(struct filter_object));
|
12
|
+
|
13
|
+
filter->expr = NULL;
|
14
|
+
|
15
|
+
return Data_Wrap_Struct(self, NULL, free_filter, filter);
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE filter_init(int argc, VALUE* argv, VALUE self)
|
19
|
+
{
|
20
|
+
VALUE v_expr, v_optimize, v_netmask;
|
21
|
+
struct filter_object *filter;
|
22
|
+
char *expr;
|
23
|
+
int n, optimize, snaplen, linktype;
|
24
|
+
bpf_u_int32 netmask;
|
25
|
+
|
26
|
+
n = rb_scan_args(argc, argv, "12", &v_expr, &v_optimize, &v_netmask);
|
27
|
+
|
28
|
+
/* filter expression */
|
29
|
+
Check_Type(v_expr, T_STRING);
|
30
|
+
expr = STR2CSTR(v_expr);
|
31
|
+
|
32
|
+
snaplen = DEFAULT_SNAPLEN;
|
33
|
+
linktype = DEFAULT_DATALINK;
|
34
|
+
|
35
|
+
/* optimize flag */
|
36
|
+
optimize = 1;
|
37
|
+
if (n >= 3) {
|
38
|
+
optimize = RTEST(v_optimize);
|
39
|
+
}
|
40
|
+
/* netmask */
|
41
|
+
netmask = 0;
|
42
|
+
if (n >= 4) {
|
43
|
+
bpf_u_int32 mask = NUM2UINT(v_netmask);
|
44
|
+
netmask = htonl(mask);
|
45
|
+
}
|
46
|
+
|
47
|
+
GetFilter(self, filter);
|
48
|
+
|
49
|
+
if (pcap_compile_nopcap(snaplen, linktype, &filter->program, expr, optimize, netmask) == -1) {
|
50
|
+
rb_raise(eCaptureError, "pcap_compile_nopcap error");
|
51
|
+
}
|
52
|
+
|
53
|
+
filter->datalink = linktype;
|
54
|
+
filter->snaplen = snaplen;
|
55
|
+
filter->expr = strdup(expr);
|
56
|
+
filter->optimize = optimize ? Qtrue : Qfalse;
|
57
|
+
filter->netmask = INT2NUM(ntohl(netmask));
|
58
|
+
|
59
|
+
return self;
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE filter_source(VALUE self)
|
63
|
+
{
|
64
|
+
struct filter_object *filter;
|
65
|
+
|
66
|
+
GetFilter(self, filter);
|
67
|
+
return rb_str_new2(filter->expr);
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
VALUE filter_match(VALUE self, VALUE v_pkt)
|
72
|
+
{
|
73
|
+
struct filter_object *filter;
|
74
|
+
struct packet_object *pkt;
|
75
|
+
|
76
|
+
GetFilter(self, filter);
|
77
|
+
|
78
|
+
int v_pkt_len = RSTRING(v_pkt)->len;
|
79
|
+
|
80
|
+
if (bpf_filter(filter->program.bf_insns, (unsigned char *)StringValuePtr(v_pkt), v_pkt_len, v_pkt_len)) {
|
81
|
+
return Qtrue;
|
82
|
+
}
|
83
|
+
|
84
|
+
return Qfalse;
|
85
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#ifndef __RB_PCAP_FILTER_H__
|
2
|
+
#define __RB_PCAP_FILTER_H__
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <rubysig.h>
|
6
|
+
#include <pcap.h>
|
7
|
+
|
8
|
+
#include "rb_pcap_capture.h"
|
9
|
+
|
10
|
+
struct filter_object {
|
11
|
+
char *expr;
|
12
|
+
struct bpf_program program;
|
13
|
+
int datalink;
|
14
|
+
int snaplen;
|
15
|
+
VALUE optimize;
|
16
|
+
VALUE netmask;
|
17
|
+
};
|
18
|
+
|
19
|
+
extern VALUE cFilter;
|
20
|
+
|
21
|
+
void mark_filter(struct filter_object *filter);
|
22
|
+
void free_filter(struct filter_object *filter);
|
23
|
+
VALUE filter_alloc(VALUE self);
|
24
|
+
VALUE filter_init(int argc, VALUE *argv, VALUE class);
|
25
|
+
VALUE filter_source(VALUE self);
|
26
|
+
VALUE filter_match(VALUE self, VALUE v_pkt);
|
27
|
+
|
28
|
+
#endif
|
data/lib/rb-pcap.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rb_pcap'
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rb-pcap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cory T. Cornelius
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-08-02 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: See README.markdown for more information.
|
17
|
+
email:
|
18
|
+
- cory.t.cornelius@dartmouth.edu
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions:
|
22
|
+
- ext/extconf.rb
|
23
|
+
extra_rdoc_files: []
|
24
|
+
|
25
|
+
files:
|
26
|
+
- README.markdown
|
27
|
+
- lib/rb-pcap.rb
|
28
|
+
- ext/extconf.rb
|
29
|
+
- ext/rb_pcap_capture.c
|
30
|
+
- ext/rb_pcap_capture.h
|
31
|
+
- ext/rb_pcap_filter.c
|
32
|
+
- ext/rb_pcap_filter.h
|
33
|
+
- ext/rb_pcap.c
|
34
|
+
- ext/rb_pcap.h
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/dxoigmn/rb-pcap
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Simple libpcap wrapper.
|
63
|
+
test_files: []
|
64
|
+
|