ruby-pcap 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }