ahobson-pcap 0.7.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.
@@ -0,0 +1,378 @@
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
+ #define CheckTruncateIp(pkt, need) \
16
+ CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IP")
17
+
18
+ VALUE
19
+ setup_ip_packet(pkt, nl_len)
20
+ struct packet_object *pkt;
21
+ int nl_len;
22
+ {
23
+ VALUE class;
24
+
25
+ DEBUG_PRINT("setup_ip_packet");
26
+
27
+ if (nl_len > 0 && IP_HDR(pkt)->ip_v != 4) {
28
+ return cPacket;
29
+ }
30
+
31
+ class = cIPPacket;
32
+ nl_len = MIN(nl_len, ntohs(IP_HDR(pkt)->ip_len));
33
+ if (nl_len > 20) {
34
+ int hl = IP_HDR(pkt)->ip_hl * 4;
35
+ int tl_len = nl_len - hl;
36
+ if (tl_len > 0) {
37
+ pkt->hdr.layer4_off = pkt->hdr.layer3_off + hl;
38
+ /* if this is fragment zero, setup upper layer */
39
+ if ((ntohs(IP_HDR(pkt)->ip_off) & IP_OFFMASK) == 0) {
40
+ switch (IP_HDR(pkt)->ip_p) {
41
+ case IPPROTO_TCP:
42
+ class = setup_tcp_packet(pkt, tl_len);
43
+ break;
44
+ case IPPROTO_UDP:
45
+ class = setup_udp_packet(pkt, tl_len);
46
+ break;
47
+ case IPPROTO_ICMP:
48
+ class = setup_icmp_packet(pkt, tl_len);
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ return class;
56
+ }
57
+
58
+ #define IPP_METHOD(func, need, val) \
59
+ static VALUE\
60
+ (func)(self)\
61
+ VALUE self;\
62
+ {\
63
+ struct packet_object *pkt;\
64
+ struct ip *ip;\
65
+ \
66
+ DEBUG_PRINT(#func);\
67
+ GetPacket(self, pkt);\
68
+ CheckTruncateIp(pkt, (need));\
69
+ ip = IP_HDR(pkt);\
70
+ return (val);\
71
+ }
72
+
73
+ IPP_METHOD(ipp_ver, 1, INT2FIX(ip->ip_v))
74
+ IPP_METHOD(ipp_hlen, 1, INT2FIX(ip->ip_hl))
75
+ IPP_METHOD(ipp_tos, 2, INT2FIX(ip->ip_tos))
76
+ IPP_METHOD(ipp_len, 4, INT2FIX(ntohs(ip->ip_len)))
77
+ IPP_METHOD(ipp_id, 6, INT2FIX(ntohs(ip->ip_id)))
78
+ IPP_METHOD(ipp_flags, 8, INT2FIX((ntohs(ip->ip_off) & ~IP_OFFMASK) >> 13))
79
+ IPP_METHOD(ipp_df, 8, ntohs(ip->ip_off) & IP_DF ? Qtrue : Qfalse)
80
+ IPP_METHOD(ipp_mf, 8, ntohs(ip->ip_off) & IP_MF ? Qtrue : Qfalse)
81
+ IPP_METHOD(ipp_off, 8, INT2FIX(ntohs(ip->ip_off) & IP_OFFMASK))
82
+ IPP_METHOD(ipp_ttl, 9, INT2FIX(ip->ip_ttl))
83
+ IPP_METHOD(ipp_proto, 10, INT2FIX(ip->ip_p))
84
+ IPP_METHOD(ipp_sum, 12, INT2FIX(ntohs(ip->ip_sum)))
85
+ IPP_METHOD(ipp_src, 16, new_ipaddr(&ip->ip_src))
86
+ IPP_METHOD(ipp_dst, 20, new_ipaddr(&ip->ip_dst))
87
+
88
+
89
+ #define IPP_SET_METHOD(func, need, member) \
90
+ static VALUE \
91
+ (func)(self, val) \
92
+ VALUE self; \
93
+ VALUE val; \
94
+ { \
95
+ struct packet_object *pkt; \
96
+ struct ip *ip; \
97
+ \
98
+ DEBUG_PRINT(#func); \
99
+ GetPacket(self, pkt); \
100
+ CheckTruncateIp(pkt, (need)); \
101
+ ip = IP_HDR(pkt); \
102
+ \
103
+ switch(TYPE(val)) { \
104
+ case T_STRING: \
105
+ (member).s_addr = inet_addr(RSTRING(val)->ptr); \
106
+ break; \
107
+ case T_BIGNUM: \
108
+ (member).s_addr = NUM2UINT(val); \
109
+ break; \
110
+ case T_DATA: \
111
+ (member).s_addr = ((struct in_addr *)&(DATA_PTR(val)))->s_addr; \
112
+ } \
113
+ return val; \
114
+ }
115
+
116
+
117
+ IPP_SET_METHOD(ipp_set_src, 16, ip->ip_src)
118
+ IPP_SET_METHOD(ipp_set_dst, 20, ip->ip_dst)
119
+
120
+ static VALUE
121
+ ipp_sumok(self)
122
+ VALUE self;
123
+ {
124
+ struct packet_object *pkt;
125
+ struct ip *ip;
126
+ int hlen, i, sum;
127
+ unsigned short *ipus;
128
+
129
+ GetPacket(self, pkt);
130
+ CheckTruncateIp(pkt, 20);
131
+ ip = IP_HDR(pkt);
132
+
133
+ hlen = ip->ip_hl * 4;
134
+ CheckTruncateIp(pkt, hlen);
135
+
136
+ ipus = (unsigned short *)ip;
137
+ sum = 0;
138
+ hlen /= 2; /* 16-bit word */
139
+ for (i = 0; i < hlen; i++) {
140
+ sum += ntohs(ipus[i]);
141
+ sum = (sum & 0xffff) + (sum >> 16);
142
+ }
143
+ if (sum == 0xffff)
144
+ return Qtrue;
145
+ return Qfalse;
146
+ }
147
+
148
+ static VALUE
149
+ ipp_data(self)
150
+ VALUE self;
151
+ {
152
+ struct packet_object *pkt;
153
+ struct ip *ip;
154
+ int len, hlen;
155
+
156
+ DEBUG_PRINT("ipp_data");
157
+ GetPacket(self, pkt);
158
+ CheckTruncateIp(pkt, 20);
159
+ ip = IP_HDR(pkt);
160
+
161
+ hlen = ip->ip_hl * 4;
162
+ len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - hlen;
163
+ return rb_str_new((u_char *)ip + hlen, len);
164
+ }
165
+
166
+ /*
167
+ * IPAddress
168
+ */
169
+
170
+ /* IPv4 adress (32bit) is stored by immediate value */
171
+ #if SIZEOF_VOIDP < 4
172
+ # error IPAddress assumes sizeof(void *) >= 4
173
+ #endif
174
+
175
+ #define GetIPAddress(obj, addr) {\
176
+ Check_Type(obj, T_DATA);\
177
+ addr = (struct in_addr *)&(DATA_PTR(obj));\
178
+ }
179
+
180
+ VALUE
181
+ new_ipaddr(addr)
182
+ struct in_addr *addr;
183
+ {
184
+ VALUE self;
185
+
186
+ self = Data_Wrap_Struct(cIPAddress, 0, 0, (void *)addr->s_addr);
187
+ return self;
188
+ }
189
+
190
+ #ifndef INADDR_NONE
191
+ # define INADDR_NONE (0xffffffff)
192
+ #endif
193
+ static VALUE
194
+ ipaddr_s_new(self, val)
195
+ VALUE self, val;
196
+ {
197
+ struct in_addr addr;
198
+ struct hostent *hent;
199
+ char *hname;
200
+
201
+ switch(TYPE(val)) {
202
+ case T_STRING:
203
+ hname = RSTRING(val)->ptr;
204
+ hent = gethostbyname(hname);
205
+ if (hent == NULL) {
206
+ extern int h_errno;
207
+ switch (h_errno) {
208
+ case HOST_NOT_FOUND:
209
+ rb_raise(ePcapError, "host not found: %s", hname);
210
+ break;
211
+ default:
212
+ #ifdef HAVE_HSTRERROR
213
+ rb_raise(ePcapError, (char *)hstrerror(h_errno));
214
+ #else
215
+ rb_raise(ePcapError, "host not found: %s", hname);
216
+ #endif
217
+ }
218
+ }
219
+ addr = *(struct in_addr *)hent->h_addr;
220
+ break;
221
+ case T_FIXNUM:
222
+ case T_BIGNUM:
223
+ addr.s_addr = htonl(NUM2ULONG(val));
224
+ break;
225
+ default:
226
+ rb_raise(rb_eTypeError, "String or Integer required");
227
+ }
228
+ return new_ipaddr(&addr);
229
+ }
230
+
231
+ static VALUE
232
+ ipaddr_to_i(self)
233
+ VALUE self;
234
+ {
235
+ struct in_addr *addr;
236
+
237
+ GetIPAddress(self, addr);
238
+ return UINT32_2_NUM(ntohl(addr->s_addr));
239
+ }
240
+
241
+ static VALUE
242
+ ipaddr_num_s(self)
243
+ VALUE self;
244
+ {
245
+ struct in_addr *addr;
246
+
247
+ GetIPAddress(self, addr);
248
+ return rb_str_new2(inet_ntoa(*addr));
249
+ }
250
+
251
+ static VALUE
252
+ ipaddr_hostname(self)
253
+ VALUE self;
254
+ {
255
+ struct in_addr *addr;
256
+ struct hostent *host;
257
+
258
+ GetIPAddress(self, addr);
259
+ host = gethostbyaddr((char *)&addr->s_addr, sizeof addr->s_addr, AF_INET);
260
+ if (host == NULL)
261
+ return ipaddr_num_s(self);
262
+ return rb_str_new2(host->h_name);
263
+ }
264
+
265
+ static VALUE
266
+ ipaddr_to_s(self)
267
+ VALUE self;
268
+ {
269
+ if (RTEST(rbpcap_convert))
270
+ return ipaddr_hostname(self);
271
+ else
272
+ return ipaddr_num_s(self);
273
+ }
274
+
275
+ static VALUE
276
+ ipaddr_equal(self, other)
277
+ VALUE self, other;
278
+ {
279
+ struct in_addr *addr1;
280
+ struct in_addr *addr2;
281
+
282
+ GetIPAddress(self, addr1);
283
+ if (rb_class_of(other) == cIPAddress) {
284
+ GetIPAddress(other, addr2);
285
+ if (addr1->s_addr == addr2->s_addr)
286
+ return Qtrue;
287
+ }
288
+ return Qfalse;
289
+ }
290
+
291
+ static VALUE
292
+ ipaddr_hash(self)
293
+ VALUE self;
294
+ {
295
+ struct in_addr *addr;
296
+
297
+ GetIPAddress(self, addr);
298
+ return INT2FIX(ntohl(addr->s_addr));
299
+ }
300
+
301
+ static VALUE
302
+ ipaddr_dump(self, limit)
303
+ VALUE self;
304
+ VALUE limit;
305
+ {
306
+ struct in_addr *addr;
307
+
308
+ GetIPAddress(self, addr);
309
+ return rb_str_new((char *)addr, sizeof addr);
310
+ }
311
+
312
+ static VALUE
313
+ ipaddr_s_load(klass, str)
314
+ VALUE klass;
315
+ VALUE str;
316
+ {
317
+ struct in_addr addr;
318
+ int i;
319
+
320
+ if (RSTRING(str)->len != sizeof addr) {
321
+ rb_raise(rb_eArgError, "dump format error (IPAddress)");
322
+ }
323
+ for (i = 0; i < sizeof addr; i++) {
324
+ ((char *)&addr)[i] = RSTRING(str)->ptr[i];
325
+ }
326
+ return new_ipaddr(&addr);
327
+ }
328
+
329
+ void
330
+ Init_ip_packet(void)
331
+ {
332
+ DEBUG_PRINT("Init_ip_packet");
333
+
334
+ cIPPacket = rb_define_class_under(mPcap, "IPPacket", cPacket);
335
+
336
+ rb_define_method(cIPPacket, "ip_ver", ipp_ver, 0);
337
+ rb_define_method(cIPPacket, "ip_hlen", ipp_hlen, 0);
338
+ rb_define_method(cIPPacket, "ip_tos", ipp_tos, 0);
339
+ rb_define_method(cIPPacket, "ip_len", ipp_len, 0);
340
+ rb_define_method(cIPPacket, "ip_id", ipp_id, 0);
341
+ rb_define_method(cIPPacket, "ip_flags", ipp_flags, 0);
342
+ rb_define_method(cIPPacket, "ip_df?", ipp_df, 0);
343
+ rb_define_method(cIPPacket, "ip_mf?", ipp_mf, 0);
344
+ rb_define_method(cIPPacket, "ip_off", ipp_off, 0);
345
+ rb_define_method(cIPPacket, "ip_ttl", ipp_ttl, 0);
346
+ rb_define_method(cIPPacket, "ip_proto", ipp_proto, 0);
347
+ rb_define_method(cIPPacket, "ip_sum", ipp_sum, 0);
348
+ rb_define_method(cIPPacket, "ip_sumok?", ipp_sumok, 0);
349
+ rb_define_method(cIPPacket, "ip_src", ipp_src, 0);
350
+ rb_define_method(cIPPacket, "src", ipp_src, 0);
351
+ rb_define_method(cIPPacket, "ip_src=", ipp_set_src, 1);
352
+ rb_define_method(cIPPacket, "src=", ipp_set_src, 1);
353
+ rb_define_method(cIPPacket, "ip_dst", ipp_dst, 0);
354
+ rb_define_method(cIPPacket, "dst", ipp_dst, 0);
355
+ rb_define_method(cIPPacket, "ip_dst=", ipp_set_dst, 1);
356
+ rb_define_method(cIPPacket, "dst=", ipp_set_dst, 1);
357
+ rb_define_method(cIPPacket, "ip_data", ipp_data, 0);
358
+
359
+ cIPAddress = rb_define_class_under(mPcap, "IPAddress", rb_cObject);
360
+ rb_define_singleton_method(cIPAddress, "new", ipaddr_s_new, 1);
361
+ rb_define_method(cIPAddress, "to_i", ipaddr_to_i, 0);
362
+ rb_define_method(cIPAddress, "to_s", ipaddr_to_s, 0);
363
+ rb_define_method(cIPAddress, "num_s", ipaddr_num_s, 0);
364
+ rb_define_method(cIPAddress, "to_num_s", ipaddr_num_s, 0); /* BWC */
365
+ rb_define_method(cIPAddress, "hostname", ipaddr_hostname, 0);
366
+ rb_define_method(cIPAddress, "sym_s", ipaddr_hostname, 0);
367
+ rb_define_method(cIPAddress, "==", ipaddr_equal, 1);
368
+ rb_define_method(cIPAddress, "===", ipaddr_equal, 1);
369
+ rb_define_method(cIPAddress, "eql?", ipaddr_equal, 1);
370
+ rb_define_method(cIPAddress, "hash", ipaddr_hash, 0);
371
+
372
+ rb_define_method(cIPAddress, "_dump", ipaddr_dump, 1);
373
+ rb_define_singleton_method(cIPAddress, "_load", ipaddr_s_load, 1);
374
+
375
+ Init_tcp_packet();
376
+ Init_udp_packet();
377
+ Init_icmp_packet();
378
+ }
@@ -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(str)->ptr;
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(str)->len - 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_BIGNUM);
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
+ }