romanbsd-pcap 0.7.0

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