blackfoundry-pcap 0.1

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