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.
@@ -0,0 +1,424 @@
1
+ /*
2
+ * ip_packet.c
3
+ *
4
+ * $Id: ip_packet.c,v 1.1.1.1 1999/10/27 09:54:38 fukusima Exp $
5
+ *
6
+ * Copyright (C) 1998, 1999 Masaki Fukushima
7
+ */
8
+
9
+ #include "ruby_pcap.h"
10
+ #include <netdb.h>
11
+
12
+ VALUE cIPPacket;
13
+ static VALUE cIPAddress;
14
+
15
+ static unsigned short in_cksum(unsigned char *data, int len);
16
+
17
+ #define CheckTruncateIp(pkt, need) \
18
+ CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IP")
19
+
20
+ VALUE
21
+ setup_ip_packet(pkt, nl_len)
22
+ struct packet_object *pkt;
23
+ int nl_len;
24
+ {
25
+ VALUE class;
26
+
27
+ DEBUG_PRINT("setup_ip_packet");
28
+
29
+ if (nl_len > 0 && IP_HDR(pkt)->ip_v != 4) {
30
+ return cPacket;
31
+ }
32
+
33
+ class = cIPPacket;
34
+ nl_len = MIN(nl_len, ntohs(IP_HDR(pkt)->ip_len));
35
+ if (nl_len > 20) {
36
+ int hl = IP_HDR(pkt)->ip_hl * 4;
37
+ int tl_len = nl_len - hl;
38
+ if (tl_len > 0) {
39
+ pkt->hdr.layer4_off = pkt->hdr.layer3_off + hl;
40
+ /* if this is fragment zero, setup upper layer */
41
+ if ((ntohs(IP_HDR(pkt)->ip_off) & IP_OFFMASK) == 0) {
42
+ switch (IP_HDR(pkt)->ip_p) {
43
+ case IPPROTO_TCP:
44
+ class = setup_tcp_packet(pkt, tl_len);
45
+ break;
46
+ case IPPROTO_UDP:
47
+ class = setup_udp_packet(pkt, tl_len);
48
+ break;
49
+ case IPPROTO_ICMP:
50
+ class = setup_icmp_packet(pkt, tl_len);
51
+ break;
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ return class;
58
+ }
59
+
60
+ #define IPP_METHOD(func, need, val) \
61
+ static VALUE\
62
+ (func)(self)\
63
+ VALUE self;\
64
+ {\
65
+ struct packet_object *pkt;\
66
+ struct ip *ip;\
67
+ \
68
+ DEBUG_PRINT(#func);\
69
+ GetPacket(self, pkt);\
70
+ CheckTruncateIp(pkt, (need));\
71
+ ip = IP_HDR(pkt);\
72
+ return (val);\
73
+ }
74
+
75
+ IPP_METHOD(ipp_ver, 1, INT2FIX(ip->ip_v))
76
+ IPP_METHOD(ipp_hlen, 1, INT2FIX(ip->ip_hl))
77
+ IPP_METHOD(ipp_tos, 2, INT2FIX(ip->ip_tos))
78
+ IPP_METHOD(ipp_len, 4, INT2FIX(ntohs(ip->ip_len)))
79
+ IPP_METHOD(ipp_id, 6, INT2FIX(ntohs(ip->ip_id)))
80
+ IPP_METHOD(ipp_flags, 8, INT2FIX((ntohs(ip->ip_off) & ~IP_OFFMASK) >> 13))
81
+ IPP_METHOD(ipp_df, 8, ntohs(ip->ip_off) & IP_DF ? Qtrue : Qfalse)
82
+ IPP_METHOD(ipp_mf, 8, ntohs(ip->ip_off) & IP_MF ? Qtrue : Qfalse)
83
+ IPP_METHOD(ipp_off, 8, INT2FIX(ntohs(ip->ip_off) & IP_OFFMASK))
84
+ IPP_METHOD(ipp_ttl, 9, INT2FIX(ip->ip_ttl))
85
+ IPP_METHOD(ipp_proto, 10, INT2FIX(ip->ip_p))
86
+ IPP_METHOD(ipp_sum, 12, INT2FIX(ntohs(ip->ip_sum)))
87
+ IPP_METHOD(ipp_src, 16, new_ipaddr(&ip->ip_src))
88
+ IPP_METHOD(ipp_dst, 20, new_ipaddr(&ip->ip_dst))
89
+
90
+
91
+ #define IPP_SET_METHOD(func, need, member) \
92
+ static VALUE \
93
+ (func)(self, val) \
94
+ VALUE self; \
95
+ VALUE val; \
96
+ { \
97
+ struct packet_object *pkt; \
98
+ struct ip *ip; \
99
+ \
100
+ DEBUG_PRINT(#func); \
101
+ GetPacket(self, pkt); \
102
+ CheckTruncateIp(pkt, (need)); \
103
+ ip = IP_HDR(pkt); \
104
+ \
105
+ switch(TYPE(val)) { \
106
+ case T_STRING: \
107
+ (member).s_addr = inet_addr(RSTRING_PTR(val)); \
108
+ break; \
109
+ case T_BIGNUM: \
110
+ (member).s_addr = NUM2UINT(val); \
111
+ break; \
112
+ case T_DATA: \
113
+ (member).s_addr = ((struct in_addr *)&(DATA_PTR(val)))->s_addr; \
114
+ } \
115
+ ip->ip_sum = 0; \
116
+ ip->ip_sum = in_cksum((unsigned char *)ip, ip->ip_hl*4); \
117
+ return val; \
118
+ }
119
+
120
+
121
+ IPP_SET_METHOD(ipp_set_src, 16, ip->ip_src)
122
+ IPP_SET_METHOD(ipp_set_dst, 20, ip->ip_dst)
123
+
124
+ static VALUE
125
+ ipp_sumok(self)
126
+ VALUE self;
127
+ {
128
+ struct packet_object *pkt;
129
+ struct ip *ip;
130
+ int hlen, i, sum;
131
+ unsigned short *ipus;
132
+
133
+ GetPacket(self, pkt);
134
+ CheckTruncateIp(pkt, 20);
135
+ ip = IP_HDR(pkt);
136
+
137
+ hlen = ip->ip_hl * 4;
138
+ CheckTruncateIp(pkt, hlen);
139
+
140
+ ipus = (unsigned short *)ip;
141
+ sum = 0;
142
+ hlen /= 2; /* 16-bit word */
143
+ for (i = 0; i < hlen; i++) {
144
+ sum += ntohs(ipus[i]);
145
+ sum = (sum & 0xffff) + (sum >> 16);
146
+ }
147
+ if (sum == 0xffff)
148
+ return Qtrue;
149
+ return Qfalse;
150
+ }
151
+
152
+ static unsigned short
153
+ in_cksum(unsigned char *data, int len)
154
+ {
155
+ long sum = 0; /* assume 32 bit long, 16 bit short */
156
+ unsigned short *temp = (unsigned short *)data;
157
+
158
+ while(len > 1){
159
+ sum += *temp++;
160
+ if(sum & 0x80000000) /* if high order bit set, fold */
161
+ sum = (sum & 0xFFFF) + (sum >> 16);
162
+ len -= 2;
163
+ }
164
+ if(len) /* take care of left over byte */
165
+ sum += (unsigned short) *((unsigned char *)temp);
166
+
167
+ while(sum>>16)
168
+ sum = (sum & 0xFFFF) + (sum >> 16);
169
+
170
+ return ~sum;
171
+ }
172
+
173
+
174
+ static VALUE
175
+ ipp_sum_update(self)
176
+ VALUE self;
177
+ {
178
+ struct packet_object *pkt;
179
+ struct ip *ip;
180
+
181
+ GetPacket(self, pkt);
182
+ CheckTruncateIp(pkt, 20);
183
+ ip = IP_HDR(pkt);
184
+
185
+ ip->ip_sum = 0;
186
+ ip->ip_sum = in_cksum((unsigned char *)ip, ip->ip_hl*4);
187
+ return INT2FIX(ntohs(ip->ip_sum));
188
+ }
189
+
190
+
191
+ static VALUE
192
+ ipp_data(self)
193
+ VALUE self;
194
+ {
195
+ struct packet_object *pkt;
196
+ struct ip *ip;
197
+ int len, hlen;
198
+
199
+ DEBUG_PRINT("ipp_data");
200
+ GetPacket(self, pkt);
201
+ CheckTruncateIp(pkt, 20);
202
+ ip = IP_HDR(pkt);
203
+
204
+ hlen = ip->ip_hl * 4;
205
+ len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - hlen;
206
+ return rb_str_new((u_char *)ip + hlen, len);
207
+ }
208
+
209
+ /*
210
+ * IPAddress
211
+ */
212
+
213
+ /* IPv4 adress (32bit) is stored by immediate value */
214
+ #if SIZEOF_VOIDP < 4
215
+ # error IPAddress assumes sizeof(void *) >= 4
216
+ #endif
217
+
218
+ #define GetIPAddress(obj, addr) {\
219
+ Check_Type(obj, T_DATA);\
220
+ addr = (struct in_addr *)&(DATA_PTR(obj));\
221
+ }
222
+
223
+ VALUE
224
+ new_ipaddr(addr)
225
+ struct in_addr *addr;
226
+ {
227
+ VALUE self;
228
+
229
+ self = Data_Wrap_Struct(cIPAddress, 0, 0, (void *)addr->s_addr);
230
+ return self;
231
+ }
232
+
233
+
234
+
235
+ #ifndef INADDR_NONE
236
+ # define INADDR_NONE (0xffffffff)
237
+ #endif
238
+ static VALUE
239
+ ipaddr_s_new(self, val)
240
+ VALUE self, val;
241
+ {
242
+ struct in_addr addr;
243
+ struct hostent *hent;
244
+ char *hname;
245
+
246
+ switch(TYPE(val)) {
247
+ case T_STRING:
248
+ hname = RSTRING_PTR(val);
249
+ hent = gethostbyname(hname);
250
+ if (hent == NULL) {
251
+ extern int h_errno;
252
+ switch (h_errno) {
253
+ case HOST_NOT_FOUND:
254
+ rb_raise(ePcapError, "host not found: %s", hname);
255
+ break;
256
+ default:
257
+ #ifdef HAVE_HSTRERROR
258
+ rb_raise(ePcapError, (char *)hstrerror(h_errno));
259
+ #else
260
+ rb_raise(ePcapError, "host not found: %s", hname);
261
+ #endif
262
+ }
263
+ }
264
+ addr = *(struct in_addr *)hent->h_addr;
265
+ break;
266
+ case T_FIXNUM:
267
+ case T_BIGNUM:
268
+ addr.s_addr = htonl(NUM2ULONG(val));
269
+ break;
270
+ default:
271
+ rb_raise(rb_eTypeError, "String or Integer required");
272
+ }
273
+ return new_ipaddr(&addr);
274
+ }
275
+
276
+ static VALUE
277
+ ipaddr_to_i(self)
278
+ VALUE self;
279
+ {
280
+ struct in_addr *addr;
281
+
282
+ GetIPAddress(self, addr);
283
+ return UINT32_2_NUM(ntohl(addr->s_addr));
284
+ }
285
+
286
+ static VALUE
287
+ ipaddr_num_s(self)
288
+ VALUE self;
289
+ {
290
+ struct in_addr *addr;
291
+
292
+ GetIPAddress(self, addr);
293
+ return rb_str_new2(inet_ntoa(*addr));
294
+ }
295
+
296
+ static VALUE
297
+ ipaddr_hostname(self)
298
+ VALUE self;
299
+ {
300
+ struct in_addr *addr;
301
+ struct hostent *host;
302
+
303
+ GetIPAddress(self, addr);
304
+ host = gethostbyaddr((char *)&addr->s_addr, sizeof addr->s_addr, AF_INET);
305
+ if (host == NULL)
306
+ return ipaddr_num_s(self);
307
+ return rb_str_new2(host->h_name);
308
+ }
309
+
310
+ static VALUE
311
+ ipaddr_to_s(self)
312
+ VALUE self;
313
+ {
314
+ if (RTEST(rbpcap_convert))
315
+ return ipaddr_hostname(self);
316
+ else
317
+ return ipaddr_num_s(self);
318
+ }
319
+
320
+ static VALUE
321
+ ipaddr_equal(self, other)
322
+ VALUE self, other;
323
+ {
324
+ struct in_addr *addr1;
325
+ struct in_addr *addr2;
326
+
327
+ GetIPAddress(self, addr1);
328
+ if (rb_class_of(other) == cIPAddress) {
329
+ GetIPAddress(other, addr2);
330
+ if (addr1->s_addr == addr2->s_addr)
331
+ return Qtrue;
332
+ }
333
+ return Qfalse;
334
+ }
335
+
336
+ static VALUE
337
+ ipaddr_hash(self)
338
+ VALUE self;
339
+ {
340
+ struct in_addr *addr;
341
+
342
+ GetIPAddress(self, addr);
343
+ return INT2FIX(ntohl(addr->s_addr));
344
+ }
345
+
346
+ static VALUE
347
+ ipaddr_dump(self, limit)
348
+ VALUE self;
349
+ VALUE limit;
350
+ {
351
+ struct in_addr *addr;
352
+
353
+ GetIPAddress(self, addr);
354
+ return rb_str_new((char *)addr, sizeof addr);
355
+ }
356
+
357
+ static VALUE
358
+ ipaddr_s_load(klass, str)
359
+ VALUE klass;
360
+ VALUE str;
361
+ {
362
+ struct in_addr addr;
363
+ int i;
364
+
365
+ if (RSTRING_LEN(str) != sizeof addr) {
366
+ rb_raise(rb_eArgError, "dump format error (IPAddress)");
367
+ }
368
+ for (i = 0; i < sizeof addr; i++) {
369
+ ((char *)&addr)[i] = RSTRING_PTR(str)[i];
370
+ }
371
+ return new_ipaddr(&addr);
372
+ }
373
+
374
+ void
375
+ Init_ip_packet(void)
376
+ {
377
+ DEBUG_PRINT("Init_ip_packet");
378
+
379
+ cIPPacket = rb_define_class_under(mPcap, "IPPacket", cPacket);
380
+
381
+ rb_define_method(cIPPacket, "ip_ver", ipp_ver, 0);
382
+ rb_define_method(cIPPacket, "ip_hlen", ipp_hlen, 0);
383
+ rb_define_method(cIPPacket, "ip_tos", ipp_tos, 0);
384
+ rb_define_method(cIPPacket, "ip_len", ipp_len, 0);
385
+ rb_define_method(cIPPacket, "ip_id", ipp_id, 0);
386
+ rb_define_method(cIPPacket, "ip_flags", ipp_flags, 0);
387
+ rb_define_method(cIPPacket, "ip_df?", ipp_df, 0);
388
+ rb_define_method(cIPPacket, "ip_mf?", ipp_mf, 0);
389
+ rb_define_method(cIPPacket, "ip_off", ipp_off, 0);
390
+ rb_define_method(cIPPacket, "ip_ttl", ipp_ttl, 0);
391
+ rb_define_method(cIPPacket, "ip_proto", ipp_proto, 0);
392
+ rb_define_method(cIPPacket, "ip_sum", ipp_sum, 0);
393
+ rb_define_method(cIPPacket, "ip_sumok?", ipp_sumok, 0);
394
+ rb_define_method(cIPPacket, "ip_src", ipp_src, 0);
395
+ rb_define_method(cIPPacket, "src", ipp_src, 0);
396
+ rb_define_method(cIPPacket, "ip_src=", ipp_set_src, 1);
397
+ rb_define_method(cIPPacket, "src=", ipp_set_src, 1);
398
+ rb_define_method(cIPPacket, "ip_dst", ipp_dst, 0);
399
+ rb_define_method(cIPPacket, "dst", ipp_dst, 0);
400
+ rb_define_method(cIPPacket, "ip_dst=", ipp_set_dst, 1);
401
+ rb_define_method(cIPPacket, "dst=", ipp_set_dst, 1);
402
+ rb_define_method(cIPPacket, "ip_data", ipp_data, 0);
403
+ rb_define_method(cIPPacket, "ip_sum_update!", ipp_sum_update, 0);
404
+
405
+ cIPAddress = rb_define_class_under(mPcap, "IPAddress", rb_cObject);
406
+ rb_define_singleton_method(cIPAddress, "new", ipaddr_s_new, 1);
407
+ rb_define_method(cIPAddress, "to_i", ipaddr_to_i, 0);
408
+ rb_define_method(cIPAddress, "to_s", ipaddr_to_s, 0);
409
+ rb_define_method(cIPAddress, "num_s", ipaddr_num_s, 0);
410
+ rb_define_method(cIPAddress, "to_num_s", ipaddr_num_s, 0); /* BWC */
411
+ rb_define_method(cIPAddress, "hostname", ipaddr_hostname, 0);
412
+ rb_define_method(cIPAddress, "sym_s", ipaddr_hostname, 0);
413
+ rb_define_method(cIPAddress, "==", ipaddr_equal, 1);
414
+ rb_define_method(cIPAddress, "===", ipaddr_equal, 1);
415
+ rb_define_method(cIPAddress, "eql?", ipaddr_equal, 1);
416
+ rb_define_method(cIPAddress, "hash", ipaddr_hash, 0);
417
+
418
+ rb_define_method(cIPAddress, "_dump", ipaddr_dump, 1);
419
+ rb_define_singleton_method(cIPAddress, "_load", ipaddr_s_load, 1);
420
+
421
+ Init_tcp_packet();
422
+ Init_udp_packet();
423
+ Init_icmp_packet();
424
+ }
@@ -0,0 +1,328 @@
1
+ /*
2
+ * packet.c
3
+ *
4
+ * $Id: packet.c,v 1.4 2000/08/13 06:56:15 fukusima Exp $
5
+ *
6
+ * Copyright (C) 1998-2000 Masaki Fukushima
7
+ */
8
+
9
+ #include "ruby.h"
10
+ #include "ruby_pcap.h"
11
+ #include <sys/socket.h>
12
+ #include <net/if.h>
13
+ #include <netinet/if_ether.h>
14
+
15
+ #define DL_HDR(pkt) ((u_char *)LAYER2_HDR(pkt))
16
+ #define DL_DATA(pkt) ((u_char *)LAYER3_HDR(pkt))
17
+
18
+ VALUE cPacket;
19
+ static VALUE mMarshal;
20
+ int id_load;
21
+ int id_dump;
22
+
23
+ /* called from GC */
24
+ static void
25
+ free_packet(pkt)
26
+ struct packet_object *pkt;
27
+ {
28
+ DEBUG_PRINT("free_packet");
29
+ free(pkt);
30
+ }
31
+
32
+ /* called from GC */
33
+ static void
34
+ mark_packet(pkt)
35
+ struct packet_object *pkt;
36
+ {
37
+ DEBUG_PRINT("mark_packet");
38
+ if (pkt->udata != Qnil)
39
+ rb_gc_mark(pkt->udata);
40
+ }
41
+
42
+ struct datalink_type {
43
+ int nltype_off; /* offset of network-layer type field */
44
+ int nl_off; /* offset of network-layer header */
45
+ };
46
+
47
+ static struct datalink_type datalinks[] = {
48
+ #if 0
49
+ { 0, 4 }, /* 0: DLT_NULL */
50
+ #else
51
+ { -1, 4 }, /* 0: DLT_NULL */
52
+ #endif
53
+ { 12, 14 }, /* 1: DLT_EN10MB */
54
+ { -1, -1 }, /* 2: DLT_EN3MB */
55
+ { -1, -1 }, /* 3: DLT_AX25 */
56
+ { -1, -1 }, /* 4: DLT_PRONET */
57
+ { -1, -1 }, /* 5: DLT_CHAOS */
58
+ { 20, 22 }, /* 6: DLT_IEEE802 */
59
+ { -1, -1 }, /* 7: DLT_ARCNET */
60
+ { -1, 16 }, /* 8: DLT_SLIP */
61
+ { 2, 4 }, /* 9: DLT_PPP */
62
+ #ifndef PCAP_FDDIPAD
63
+ { 19, 21 }, /* 10: DLT_FDDI */
64
+ #else
65
+ { 19 + PCAP_FDDIPAD, 21 + PCAP_FDDIPAD },
66
+ #endif
67
+ { 6, 8 }, /* 11: DLT_ATM_RFC1483 */
68
+ { -1, 0 }, /* 12: DLT_RAW */
69
+ { -1, 24 }, /* 13: DLT_SLIP_BSDOS */
70
+ { 5, 24 } /* 14: DLT_PPP_BSDOS */
71
+ #define DATALINK_MAX 14
72
+ };
73
+
74
+ VALUE
75
+ new_packet(data, pkthdr, dl_type)
76
+ const u_char *data;
77
+ const struct pcap_pkthdr *pkthdr;
78
+ int dl_type;
79
+ {
80
+ VALUE class;
81
+ struct packet_object *pkt;
82
+ int nl_off, nl_len, nltype_off, nl_type, pad;
83
+
84
+ DEBUG_PRINT("new_packet");
85
+
86
+ /* check nework layer type and offset */
87
+ if (dl_type > DATALINK_MAX) {
88
+ rb_raise(ePcapError, "Unknown data-link type (%d)", dl_type);
89
+ }
90
+ nltype_off = datalinks[dl_type].nltype_off;
91
+ nl_off = datalinks[dl_type].nl_off;
92
+ if (nl_off < 0) {
93
+ rb_raise(ePcapError, "Unsupported data-link type (%d)", dl_type);
94
+ }
95
+ if (nltype_off == -1) {
96
+ /* assume IP */
97
+ nl_type = ETHERTYPE_IP;
98
+ } else {
99
+ /* assume Ether Type value */
100
+ nl_type = ntohs(*(u_short *)(data + nltype_off));
101
+ }
102
+
103
+ /* alloc memory and setup packet_object */
104
+ pad = nl_off % 4; /* align network layer header */
105
+ pkt = xmalloc(sizeof(*pkt) + pad + pkthdr->caplen);
106
+ pkt->hdr.version = PACKET_MARSHAL_VERSION;
107
+ pkt->hdr.flags = 0;
108
+ pkt->hdr.dl_type = dl_type;
109
+ pkt->hdr.layer3_off = OFF_NONEXIST;
110
+ pkt->hdr.layer4_off = OFF_NONEXIST;
111
+ pkt->hdr.layer5_off = OFF_NONEXIST;
112
+ pkt->hdr.pkthdr = *pkthdr;
113
+ pkt->data = (u_char *)pkt + sizeof(*pkt) + pad;
114
+ pkt->udata = Qnil;
115
+ memcpy(pkt->data, data, pkthdr->caplen);
116
+
117
+ nl_len = pkthdr->caplen - nl_off;
118
+ if (nl_off >= 0 && nl_len > 0)
119
+ pkt->hdr.layer3_off = nl_off;
120
+
121
+ /* setup upper layer */
122
+ class = cPacket;
123
+ if (pkt->hdr.layer3_off != OFF_NONEXIST) {
124
+ switch (nl_type) {
125
+ case ETHERTYPE_IP:
126
+ class = setup_ip_packet(pkt, nl_len);
127
+ break;
128
+ }
129
+ }
130
+ #if DEBUG
131
+ if (ruby_debug && TYPE(class) != T_CLASS) {
132
+ rb_fatal("not class");
133
+ }
134
+ #endif
135
+ return Data_Wrap_Struct(class, mark_packet, free_packet, pkt);
136
+ }
137
+
138
+ static VALUE
139
+ packet_load(class, str)
140
+ VALUE class;
141
+ VALUE str;
142
+ {
143
+ struct packet_object *pkt = NULL;
144
+ struct packet_object_header *hdr;
145
+ int version;
146
+ u_char *str_ptr;
147
+
148
+ DEBUG_PRINT("packet_load");
149
+
150
+ str_ptr = RSTRING_PTR(str);
151
+ hdr = (struct packet_object_header *)str_ptr;
152
+ version = hdr->version;
153
+ if (version == PACKET_MARSHAL_VERSION) {
154
+ bpf_u_int32 caplen;
155
+ u_short layer3_off;
156
+ int pad;
157
+
158
+ caplen = ntohl(hdr->pkthdr.caplen);
159
+ layer3_off = ntohs(hdr->layer3_off);
160
+ pad = layer3_off % 4; /* align network layer header */
161
+ pkt = (struct packet_object *)xmalloc(sizeof(*pkt) + pad + caplen);
162
+
163
+ pkt->hdr.version = PACKET_MARSHAL_VERSION;
164
+ pkt->hdr.flags = hdr->flags;
165
+ pkt->hdr.dl_type = hdr->dl_type;
166
+ pkt->hdr.layer3_off = ntohs(hdr->layer3_off);
167
+ pkt->hdr.layer4_off = ntohs(hdr->layer4_off);
168
+ pkt->hdr.layer5_off = ntohs(hdr->layer5_off);
169
+ pkt->hdr.pkthdr.ts.tv_sec = ntohl(hdr->pkthdr.ts.tv_sec);
170
+ pkt->hdr.pkthdr.ts.tv_usec = ntohl(hdr->pkthdr.ts.tv_usec);
171
+ pkt->hdr.pkthdr.caplen = ntohl(hdr->pkthdr.caplen);
172
+ pkt->hdr.pkthdr.len = ntohl(hdr->pkthdr.len);
173
+
174
+ pkt->data = (u_char *)pkt + sizeof(*pkt) + pad;
175
+ memcpy(pkt->data, str_ptr + sizeof(*hdr), caplen);
176
+ if (PKTFLAG_TEST(pkt, POH_UDATA)) {
177
+ int l = sizeof(*hdr) + caplen;
178
+ VALUE ustr = rb_str_substr(str, l, RSTRING_LEN(str) - l);
179
+ pkt->udata = rb_funcall(mMarshal, id_load, 1, ustr);
180
+ } else {
181
+ pkt->udata = Qnil;
182
+ }
183
+ PKTFLAG_SET(pkt, POH_UDATA, (pkt->udata != Qnil));
184
+ } else {
185
+ rb_raise(rb_eArgError, "unknown packet marshal version(0x%x)", version);
186
+ }
187
+
188
+ if (pkt != NULL)
189
+ return Data_Wrap_Struct(class, mark_packet, free_packet, pkt);
190
+ else
191
+ return Qnil;
192
+ }
193
+
194
+ static VALUE
195
+ packet_dump(self, limit)
196
+ VALUE self;
197
+ VALUE limit;
198
+ {
199
+ struct packet_object *pkt;
200
+ struct packet_object_header hdr;
201
+ VALUE str;
202
+
203
+ DEBUG_PRINT("packet_dump");
204
+ GetPacket(self, pkt);
205
+
206
+ hdr.version = PACKET_MARSHAL_VERSION;
207
+ hdr.flags = pkt->hdr.flags;
208
+ hdr.dl_type = pkt->hdr.dl_type;
209
+ hdr.layer3_off = htons(pkt->hdr.layer3_off);
210
+ hdr.layer4_off = htons(pkt->hdr.layer4_off);
211
+ hdr.layer5_off = htons(pkt->hdr.layer5_off);
212
+ hdr.pkthdr.ts.tv_sec = htonl(pkt->hdr.pkthdr.ts.tv_sec);
213
+ hdr.pkthdr.ts.tv_usec = htonl(pkt->hdr.pkthdr.ts.tv_usec);
214
+ hdr.pkthdr.caplen = htonl(pkt->hdr.pkthdr.caplen);
215
+ hdr.pkthdr.len = htonl(pkt->hdr.pkthdr.len);
216
+
217
+ str = rb_str_new((char *)&hdr, sizeof(hdr));
218
+ rb_str_cat(str, pkt->data, pkt->hdr.pkthdr.caplen);
219
+ if (pkt->udata != Qnil) {
220
+ VALUE ustr;
221
+ ustr = rb_funcall(mMarshal, id_dump, 1, pkt->udata);
222
+ rb_str_concat(str, ustr);
223
+ }
224
+ return str;
225
+ }
226
+
227
+ static VALUE
228
+ packet_set_udata(self, val)
229
+ VALUE self;
230
+ VALUE val;
231
+ {
232
+ struct packet_object *pkt;
233
+
234
+ DEBUG_PRINT("packet_set_udata");
235
+ GetPacket(self, pkt);
236
+
237
+ pkt->udata = val;
238
+ PKTFLAG_SET(pkt, POH_UDATA, (val != Qnil));
239
+ return val;
240
+ }
241
+
242
+ static VALUE
243
+ packet_set_time_i(self, val)
244
+ VALUE self;
245
+ VALUE val;
246
+ {
247
+ struct packet_object *pkt;
248
+ unsigned int time_i;
249
+
250
+ DEBUG_PRINT("packet_set_time_i");
251
+ GetPacket(self, pkt);
252
+ Check_Type(val, T_FIXNUM);
253
+ time_i = NUM2UINT(val);
254
+
255
+ pkt->hdr.pkthdr.ts.tv_sec = time_i;
256
+ return val;
257
+ }
258
+
259
+ static VALUE
260
+ packet_match(self, expr)
261
+ VALUE self;
262
+ VALUE expr;
263
+ {
264
+ if (IsKindOf(expr, cFilter)) {
265
+ return filter_match(expr, self);
266
+ }
267
+ rb_raise(rb_eArgError, "Not Filter");
268
+ }
269
+
270
+ #define PACKET_METHOD(func, val) \
271
+ static VALUE\
272
+ (func)(self)\
273
+ VALUE self;\
274
+ {\
275
+ struct packet_object *pkt;\
276
+ \
277
+ DEBUG_PRINT(#func);\
278
+ GetPacket(self, pkt);\
279
+ return (val);\
280
+ }
281
+
282
+ PACKET_METHOD(packet_get_udata, pkt->udata);
283
+ PACKET_METHOD(packet_datalink, INT2FIX(pkt->hdr.dl_type));
284
+ PACKET_METHOD(packet_ip, rb_obj_is_kind_of(self, cIPPacket));
285
+ PACKET_METHOD(packet_tcp, rb_obj_is_kind_of(self, cTCPPacket));
286
+ PACKET_METHOD(packet_udp, rb_obj_is_kind_of(self, cUDPPacket));
287
+ PACKET_METHOD(packet_length, UINT32_2_NUM(pkt->hdr.pkthdr.len));
288
+ PACKET_METHOD(packet_caplen, UINT32_2_NUM(pkt->hdr.pkthdr.caplen));
289
+ PACKET_METHOD(packet_time, rb_time_new(pkt->hdr.pkthdr.ts.tv_sec,
290
+ pkt->hdr.pkthdr.ts.tv_usec));
291
+ PACKET_METHOD(packet_time_i, rb_int2inum(pkt->hdr.pkthdr.ts.tv_sec));
292
+ PACKET_METHOD(packet_raw_data, rb_str_new(pkt->data, pkt->hdr.pkthdr.caplen));
293
+
294
+ void
295
+ Init_packet(void)
296
+ {
297
+ DEBUG_PRINT("Init_packet");
298
+
299
+ /* define class Packet */
300
+ cPacket = rb_define_class_under(mPcap, "Packet", rb_cObject);
301
+
302
+ rb_define_singleton_method(cPacket, "_load", packet_load, 1);
303
+ rb_define_method(cPacket, "_dump", packet_dump, 1);
304
+ /* marshal backward compatibility */
305
+ rb_define_singleton_method(cPacket, "_load_from", packet_load, 1);
306
+ rb_define_method(cPacket, "_dump_to", packet_dump, 1);
307
+
308
+ rb_define_method(cPacket, "udata", packet_get_udata, 0);
309
+ rb_define_method(cPacket, "udata=", packet_set_udata, 1);
310
+ rb_define_method(cPacket, "datalink", packet_datalink, 0);
311
+ rb_define_method(cPacket, "ip?", packet_ip, 0);
312
+ rb_define_method(cPacket, "tcp?", packet_tcp, 0);
313
+ rb_define_method(cPacket, "udp?", packet_udp, 0);
314
+ rb_define_method(cPacket, "length", packet_length, 0);
315
+ rb_define_method(cPacket, "size", packet_length, 0);
316
+ rb_define_method(cPacket, "caplen", packet_caplen, 0);
317
+ rb_define_method(cPacket, "time", packet_time, 0);
318
+ rb_define_method(cPacket, "time_i", packet_time_i, 0);
319
+ rb_define_method(cPacket, "time_i=", packet_set_time_i, 1);
320
+ rb_define_method(cPacket, "raw_data", packet_raw_data, 0);
321
+ rb_define_method(cPacket, "=~", packet_match, 1);
322
+
323
+ /* mMarshal in ruby/marshal.c is static. Why? */
324
+ mMarshal = rb_eval_string("Marshal");
325
+ id_load = rb_intern("load");
326
+ id_dump = rb_intern("dump");
327
+ Init_ip_packet();
328
+ }