blackfoundry-pcap 0.1

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,342 @@
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
+ static VALUE
89
+ ipp_sumok(self)
90
+ VALUE self;
91
+ {
92
+ struct packet_object *pkt;
93
+ struct ip *ip;
94
+ int hlen, i, sum;
95
+ unsigned short *ipus;
96
+
97
+ GetPacket(self, pkt);
98
+ CheckTruncateIp(pkt, 20);
99
+ ip = IP_HDR(pkt);
100
+
101
+ hlen = ip->ip_hl * 4;
102
+ CheckTruncateIp(pkt, hlen);
103
+
104
+ ipus = (unsigned short *)ip;
105
+ sum = 0;
106
+ hlen /= 2; /* 16-bit word */
107
+ for (i = 0; i < hlen; i++) {
108
+ sum += ntohs(ipus[i]);
109
+ sum = (sum & 0xffff) + (sum >> 16);
110
+ }
111
+ if (sum == 0xffff)
112
+ return Qtrue;
113
+ return Qfalse;
114
+ }
115
+
116
+ static VALUE
117
+ ipp_data(self)
118
+ VALUE self;
119
+ {
120
+ struct packet_object *pkt;
121
+ struct ip *ip;
122
+ int len, hlen;
123
+
124
+ DEBUG_PRINT("ipp_data");
125
+ GetPacket(self, pkt);
126
+ CheckTruncateIp(pkt, 20);
127
+ ip = IP_HDR(pkt);
128
+
129
+ hlen = ip->ip_hl * 4;
130
+ len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - hlen;
131
+ return rb_str_new((u_char *)ip + hlen, len);
132
+ }
133
+
134
+ /*
135
+ * IPAddress
136
+ */
137
+
138
+ /* IPv4 adress (32bit) is stored by immediate value */
139
+ #if SIZEOF_VOIDP < 4
140
+ # error IPAddress assumes sizeof(void *) >= 4
141
+ #endif
142
+
143
+ #define GetIPAddress(obj, addr) {\
144
+ Check_Type(obj, T_DATA);\
145
+ addr = (struct in_addr *)&(DATA_PTR(obj));\
146
+ }
147
+
148
+ VALUE
149
+ new_ipaddr(addr)
150
+ struct in_addr *addr;
151
+ {
152
+ VALUE self;
153
+
154
+ self = Data_Wrap_Struct(cIPAddress, 0, 0, (void *)addr->s_addr);
155
+ return self;
156
+ }
157
+
158
+ #ifndef INADDR_NONE
159
+ # define INADDR_NONE (0xffffffff)
160
+ #endif
161
+ static VALUE
162
+ ipaddr_s_new(self, val)
163
+ VALUE self, val;
164
+ {
165
+ struct in_addr addr;
166
+ struct hostent *hent;
167
+ char *hname;
168
+
169
+ switch(TYPE(val)) {
170
+ case T_STRING:
171
+ hname = RSTRING(val)->ptr;
172
+ hent = gethostbyname(hname);
173
+ if (hent == NULL) {
174
+ extern int h_errno;
175
+ switch (h_errno) {
176
+ case HOST_NOT_FOUND:
177
+ rb_raise(ePcapError, "host not found: %s", hname);
178
+ break;
179
+ default:
180
+ #ifdef HAVE_HSTRERROR
181
+ rb_raise(ePcapError, (char *)hstrerror(h_errno));
182
+ #else
183
+ rb_raise(ePcapError, "host not found: %s", hname);
184
+ #endif
185
+ }
186
+ }
187
+ addr = *(struct in_addr *)hent->h_addr;
188
+ break;
189
+ case T_FIXNUM:
190
+ case T_BIGNUM:
191
+ addr.s_addr = htonl(NUM2ULONG(val));
192
+ break;
193
+ default:
194
+ rb_raise(rb_eTypeError, "String or Integer required");
195
+ }
196
+ return new_ipaddr(&addr);
197
+ }
198
+
199
+ static VALUE
200
+ ipaddr_to_i(self)
201
+ VALUE self;
202
+ {
203
+ struct in_addr *addr;
204
+
205
+ GetIPAddress(self, addr);
206
+ return UINT32_2_NUM(ntohl(addr->s_addr));
207
+ }
208
+
209
+ static VALUE
210
+ ipaddr_num_s(self)
211
+ VALUE self;
212
+ {
213
+ struct in_addr *addr;
214
+
215
+ GetIPAddress(self, addr);
216
+ return rb_str_new2(inet_ntoa(*addr));
217
+ }
218
+
219
+ static VALUE
220
+ ipaddr_hostname(self)
221
+ VALUE self;
222
+ {
223
+ struct in_addr *addr;
224
+ struct hostent *host;
225
+
226
+ GetIPAddress(self, addr);
227
+ host = gethostbyaddr((char *)&addr->s_addr, sizeof addr->s_addr, AF_INET);
228
+ if (host == NULL)
229
+ return ipaddr_num_s(self);
230
+ return rb_str_new2(host->h_name);
231
+ }
232
+
233
+ static VALUE
234
+ ipaddr_to_s(self)
235
+ VALUE self;
236
+ {
237
+ if (RTEST(rbpcap_convert))
238
+ return ipaddr_hostname(self);
239
+ else
240
+ return ipaddr_num_s(self);
241
+ }
242
+
243
+ static VALUE
244
+ ipaddr_equal(self, other)
245
+ VALUE self, other;
246
+ {
247
+ struct in_addr *addr1;
248
+ struct in_addr *addr2;
249
+
250
+ GetIPAddress(self, addr1);
251
+ if (rb_class_of(other) == cIPAddress) {
252
+ GetIPAddress(other, addr2);
253
+ if (addr1->s_addr == addr2->s_addr)
254
+ return Qtrue;
255
+ }
256
+ return Qfalse;
257
+ }
258
+
259
+ static VALUE
260
+ ipaddr_hash(self)
261
+ VALUE self;
262
+ {
263
+ struct in_addr *addr;
264
+
265
+ GetIPAddress(self, addr);
266
+ return INT2FIX(ntohl(addr->s_addr));
267
+ }
268
+
269
+ static VALUE
270
+ ipaddr_dump(self, limit)
271
+ VALUE self;
272
+ VALUE limit;
273
+ {
274
+ struct in_addr *addr;
275
+
276
+ GetIPAddress(self, addr);
277
+ return rb_str_new((char *)addr, sizeof addr);
278
+ }
279
+
280
+ static VALUE
281
+ ipaddr_s_load(klass, str)
282
+ VALUE klass;
283
+ VALUE str;
284
+ {
285
+ struct in_addr addr;
286
+ int i;
287
+
288
+ if (RSTRING(str)->len != sizeof addr) {
289
+ rb_raise(rb_eArgError, "dump format error (IPAddress)");
290
+ }
291
+ for (i = 0; i < sizeof addr; i++) {
292
+ ((char *)&addr)[i] = RSTRING(str)->ptr[i];
293
+ }
294
+ return new_ipaddr(&addr);
295
+ }
296
+
297
+ void
298
+ Init_ip_packet(void)
299
+ {
300
+ DEBUG_PRINT("Init_ip_packet");
301
+
302
+ cIPPacket = rb_define_class_under(mPcap, "IPPacket", cPacket);
303
+
304
+ rb_define_method(cIPPacket, "ip_ver", ipp_ver, 0);
305
+ rb_define_method(cIPPacket, "ip_hlen", ipp_hlen, 0);
306
+ rb_define_method(cIPPacket, "ip_tos", ipp_tos, 0);
307
+ rb_define_method(cIPPacket, "ip_len", ipp_len, 0);
308
+ rb_define_method(cIPPacket, "ip_id", ipp_id, 0);
309
+ rb_define_method(cIPPacket, "ip_flags", ipp_flags, 0);
310
+ rb_define_method(cIPPacket, "ip_df?", ipp_df, 0);
311
+ rb_define_method(cIPPacket, "ip_mf?", ipp_mf, 0);
312
+ rb_define_method(cIPPacket, "ip_off", ipp_off, 0);
313
+ rb_define_method(cIPPacket, "ip_ttl", ipp_ttl, 0);
314
+ rb_define_method(cIPPacket, "ip_proto", ipp_proto, 0);
315
+ rb_define_method(cIPPacket, "ip_sum", ipp_sum, 0);
316
+ rb_define_method(cIPPacket, "ip_sumok?", ipp_sumok, 0);
317
+ rb_define_method(cIPPacket, "ip_src", ipp_src, 0);
318
+ rb_define_method(cIPPacket, "src", ipp_src, 0);
319
+ rb_define_method(cIPPacket, "ip_dst", ipp_dst, 0);
320
+ rb_define_method(cIPPacket, "dst", ipp_dst, 0);
321
+ rb_define_method(cIPPacket, "ip_data", ipp_data, 0);
322
+
323
+ cIPAddress = rb_define_class_under(mPcap, "IPAddress", rb_cObject);
324
+ rb_define_singleton_method(cIPAddress, "new", ipaddr_s_new, 1);
325
+ rb_define_method(cIPAddress, "to_i", ipaddr_to_i, 0);
326
+ rb_define_method(cIPAddress, "to_s", ipaddr_to_s, 0);
327
+ rb_define_method(cIPAddress, "num_s", ipaddr_num_s, 0);
328
+ rb_define_method(cIPAddress, "to_num_s", ipaddr_num_s, 0); /* BWC */
329
+ rb_define_method(cIPAddress, "hostname", ipaddr_hostname, 0);
330
+ rb_define_method(cIPAddress, "sym_s", ipaddr_hostname, 0);
331
+ rb_define_method(cIPAddress, "==", ipaddr_equal, 1);
332
+ rb_define_method(cIPAddress, "===", ipaddr_equal, 1);
333
+ rb_define_method(cIPAddress, "eql?", ipaddr_equal, 1);
334
+ rb_define_method(cIPAddress, "hash", ipaddr_hash, 0);
335
+
336
+ rb_define_method(cIPAddress, "_dump", ipaddr_dump, 1);
337
+ rb_define_singleton_method(cIPAddress, "_load", ipaddr_s_load, 1);
338
+
339
+ Init_tcp_packet();
340
+ Init_udp_packet();
341
+ Init_icmp_packet();
342
+ }
@@ -0,0 +1,310 @@
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_match(self, expr)
244
+ VALUE self;
245
+ VALUE expr;
246
+ {
247
+ if (IsKindOf(expr, cFilter)) {
248
+ return filter_match(expr, self);
249
+ }
250
+ rb_raise(rb_eArgError, "Not Filter");
251
+ }
252
+
253
+ #define PACKET_METHOD(func, val) \
254
+ static VALUE\
255
+ (func)(self)\
256
+ VALUE self;\
257
+ {\
258
+ struct packet_object *pkt;\
259
+ \
260
+ DEBUG_PRINT(#func);\
261
+ GetPacket(self, pkt);\
262
+ return (val);\
263
+ }
264
+
265
+ PACKET_METHOD(packet_get_udata, pkt->udata);
266
+ PACKET_METHOD(packet_datalink, INT2FIX(pkt->hdr.dl_type));
267
+ PACKET_METHOD(packet_ip, rb_obj_is_kind_of(self, cIPPacket));
268
+ PACKET_METHOD(packet_tcp, rb_obj_is_kind_of(self, cTCPPacket));
269
+ PACKET_METHOD(packet_udp, rb_obj_is_kind_of(self, cUDPPacket));
270
+ PACKET_METHOD(packet_length, UINT32_2_NUM(pkt->hdr.pkthdr.len));
271
+ PACKET_METHOD(packet_caplen, UINT32_2_NUM(pkt->hdr.pkthdr.caplen));
272
+ PACKET_METHOD(packet_time, rb_time_new(pkt->hdr.pkthdr.ts.tv_sec,
273
+ pkt->hdr.pkthdr.ts.tv_usec));
274
+ PACKET_METHOD(packet_time_i, rb_int2inum(pkt->hdr.pkthdr.ts.tv_sec));
275
+ PACKET_METHOD(packet_raw_data, rb_str_new(pkt->data, pkt->hdr.pkthdr.caplen));
276
+
277
+ void
278
+ Init_packet(void)
279
+ {
280
+ DEBUG_PRINT("Init_packet");
281
+
282
+ /* define class Packet */
283
+ cPacket = rb_define_class_under(mPcap, "Packet", rb_cObject);
284
+
285
+ rb_define_singleton_method(cPacket, "_load", packet_load, 1);
286
+ rb_define_method(cPacket, "_dump", packet_dump, 1);
287
+ /* marshal backward compatibility */
288
+ rb_define_singleton_method(cPacket, "_load_from", packet_load, 1);
289
+ rb_define_method(cPacket, "_dump_to", packet_dump, 1);
290
+
291
+ rb_define_method(cPacket, "udata", packet_get_udata, 0);
292
+ rb_define_method(cPacket, "udata=", packet_set_udata, 1);
293
+ rb_define_method(cPacket, "datalink", packet_datalink, 0);
294
+ rb_define_method(cPacket, "ip?", packet_ip, 0);
295
+ rb_define_method(cPacket, "tcp?", packet_tcp, 0);
296
+ rb_define_method(cPacket, "udp?", packet_udp, 0);
297
+ rb_define_method(cPacket, "length", packet_length, 0);
298
+ rb_define_method(cPacket, "size", packet_length, 0);
299
+ rb_define_method(cPacket, "caplen", packet_caplen, 0);
300
+ rb_define_method(cPacket, "time", packet_time, 0);
301
+ rb_define_method(cPacket, "time_i", packet_time_i, 0);
302
+ rb_define_method(cPacket, "raw_data", packet_raw_data, 0);
303
+ rb_define_method(cPacket, "=~", packet_match, 1);
304
+
305
+ /* mMarshal in ruby/marshal.c is static. Why? */
306
+ mMarshal = rb_eval_string("Marshal");
307
+ id_load = rb_intern("load");
308
+ id_dump = rb_intern("dump");
309
+ Init_ip_packet();
310
+ }