rb-pcap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ rb-pcap
2
+ =======
3
+
4
+ A simple ruby wrapper for the pcap library.
5
+
6
+ Compiling
7
+ ---------
8
+
9
+ ruby extconf.rb
10
+ make
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('pcap')
4
+ fail "Couldn't find libpcap." unless have_library("pcap", "pcap_open_live", "pcap.h")
5
+
6
+ create_makefile("rb_pcap")
@@ -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
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef __RB_PCAP_H__
2
+ #define __RB_PCAP_H__
3
+
4
+ #include "rb_pcap_capture.h"
5
+ #include "rb_pcap_filter.h"
6
+
7
+ VALUE cCapture;
8
+ VALUE cFilter;
9
+ VALUE eCaptureError;
10
+ VALUE eTruncatedPacket;
11
+
12
+ #endif
@@ -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
@@ -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
+