rb-pcap 0.1.0
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/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
|
+
|