ruby-pcap 0.7.9 → 0.8.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.
@@ -14,10 +14,12 @@
14
14
  #define TCP_DATALEN(pkt) (ntohs(IP_HDR(pkt)->ip_len) - \
15
15
  (IP_HDR(pkt)->ip_hl + TCP_HDR(pkt)->th_off) * 4)
16
16
 
17
+ #define TCP_OPTIONS(pkt) ((u_char *) &TCP_HDR(pkt)->th_urp + 2)
18
+ #define TCP_OPTIONS_LEN(pkt) (((TCP_HDR(pkt)->th_off) * 4) - 20)
19
+
17
20
  VALUE cTCPPacket;
18
21
 
19
- #define CheckTruncateTcp(pkt, need) \
20
- CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated TCP")
22
+ #define CheckTruncateTcp(pkt, need) CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated TCP")
21
23
 
22
24
  VALUE
23
25
  setup_tcp_packet(pkt, tl_len)
@@ -64,8 +66,8 @@ TCPP_METHOD(tcpp_win, 16, INT2FIX(ntohs(tcp->th_win)))
64
66
  TCPP_METHOD(tcpp_sum, 18, INT2FIX(ntohs(tcp->th_sum)))
65
67
  TCPP_METHOD(tcpp_urp, 20, INT2FIX(ntohs(tcp->th_urp)))
66
68
 
67
- #define TCPP_FLAG(func, flag) \
68
- TCPP_METHOD(func, 14, (tcp->th_flags & flag) ? Qtrue : Qfalse)
69
+ #define TCPP_FLAG(func, flag) TCPP_METHOD(func, 14, (tcp->th_flags & flag) ? Qtrue : Qfalse)
70
+
69
71
  TCPP_FLAG(tcpp_fin, TH_FIN)
70
72
  TCPP_FLAG(tcpp_syn, TH_SYN)
71
73
  TCPP_FLAG(tcpp_rst, TH_RST)
@@ -78,7 +80,6 @@ tcpp_data(self)
78
80
  VALUE self;
79
81
  {
80
82
  struct packet_object *pkt;
81
- VALUE v_len;
82
83
  int len;
83
84
 
84
85
  DEBUG_PRINT("tcpp_data");
@@ -91,6 +92,308 @@ tcpp_data(self)
91
92
  return rb_str_new(TCP_DATA(pkt), len);
92
93
  }
93
94
 
95
+ static VALUE
96
+ tcpp_options(self)
97
+ VALUE self;
98
+ {
99
+ struct packet_object *pkt;
100
+ int len;
101
+
102
+ DEBUG_PRINT("tcpp_options");
103
+ GetPacket(self, pkt);
104
+ len = TCP_OPTIONS_LEN(pkt);
105
+ if (len < 1 ) return Qnil;
106
+ return rb_str_new(TCP_OPTIONS(pkt), len);
107
+ }
108
+
109
+ static VALUE
110
+ tcpp_csumok(self)
111
+ VALUE self;
112
+ {
113
+ struct packet_object *pkt;
114
+ struct ip *ip;
115
+ struct tcphdr *tcp;
116
+ GetPacket(self, pkt);
117
+ ip = IP_HDR(pkt);
118
+ tcp = TCP_HDR(pkt);
119
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
120
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
121
+ long sum = 0;
122
+ unsigned short *temp = (unsigned short *)tcp;
123
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
124
+ unsigned short csum = ntohs(tcp->th_sum); // keep the checksum in packet
125
+
126
+ // pseudo header sum
127
+ sum += ntohs(*(ip_src++));
128
+ sum += ntohs(*ip_src);
129
+ sum += ntohs(*(ip_dst++));
130
+ sum += ntohs(*ip_dst);
131
+ sum += 6;
132
+ sum += len;
133
+ // set checksum to zero and sum
134
+ tcp->th_sum = 0;
135
+ while(len > 1){
136
+ sum += ntohs(*temp++);
137
+ len -= 2;
138
+ }
139
+ if(len)
140
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
141
+ while(sum>>16)
142
+ sum = (sum & 0xFFFF) + (sum >> 16);
143
+ unsigned short answer = ~sum;
144
+
145
+ tcp->th_sum = htons(csum); //restore the checkum in packet
146
+ if (DEBUG_CHECKSUM)
147
+ printf("TCP csum in packet:%d should be %d\n", csum, answer);
148
+ if (answer == csum)
149
+ return Qtrue;
150
+ return Qfalse;
151
+ }
152
+
153
+ static VALUE
154
+ tcpp_truncated(self)
155
+ VALUE self;
156
+ {
157
+ struct packet_object *pkt;
158
+ struct ip *ip;
159
+ struct tcphdr *tcp;
160
+ GetPacket(self, pkt);
161
+ ip = IP_HDR(pkt);
162
+ tcp = TCP_HDR(pkt);
163
+ if IsTruncated(pkt, pkt->hdr.layer3_off, ip->ip_hl * 4 + tcp->th_off * 4)
164
+ return Qtrue;
165
+ return Qfalse;
166
+ }
167
+
168
+ static VALUE
169
+ tcpp_data_len(self)
170
+ VALUE self;
171
+ {
172
+ struct packet_object *pkt;
173
+ GetPacket(self, pkt);
174
+
175
+ return INT2FIX(TCP_DATALEN(pkt));
176
+ }
177
+
178
+ /*
179
+ Calculate TCP checksum and update it in packet
180
+ */
181
+ static VALUE
182
+ tcpp_csum_update(self)
183
+ VALUE self;
184
+ {
185
+ struct packet_object *pkt;
186
+ struct ip *ip;
187
+ struct tcphdr *tcp;
188
+ GetPacket(self, pkt);
189
+ ip = IP_HDR(pkt);
190
+ tcp = TCP_HDR(pkt);
191
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
192
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
193
+ long sum = 0;
194
+ /* save checksum in packet */
195
+ unsigned short th_sum = ntohs(tcp->th_sum);
196
+ unsigned short *temp = (unsigned short *)tcp;
197
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
198
+
199
+ // pseudo header sum
200
+ sum += ntohs(*(ip_src++));
201
+ sum += ntohs(*ip_src);
202
+ sum += ntohs(*(ip_dst++));
203
+ sum += ntohs(*ip_dst);
204
+ sum += 6;
205
+ sum += len;
206
+ // set checksum to zero and sum
207
+ tcp->th_sum = 0;
208
+ while(len > 1){
209
+ sum += ntohs(*temp++);
210
+ len -= 2;
211
+ }
212
+ if(len)
213
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
214
+ while(sum>>16)
215
+ sum = (sum & 0xFFFF) + (sum >> 16);
216
+ unsigned short answer = ~sum;
217
+ /*
218
+ * set checkum in packet
219
+ */
220
+ tcp->th_sum = htons(answer);
221
+ /*
222
+ * no change, return nil
223
+ */
224
+ if (answer == th_sum)
225
+ return Qnil;
226
+ /*
227
+ * return new checkum
228
+ */
229
+ return UINT2NUM(answer);
230
+ }
231
+
232
+ /*
233
+ * Set TCP source port and update checksum
234
+ */
235
+ static VALUE
236
+ tcpp_sport_set(self, val)
237
+ VALUE self, val;
238
+ {
239
+ struct packet_object *pkt;
240
+ struct tcphdr *tcp;
241
+ GetPacket(self, pkt);
242
+ tcp = TCP_HDR(pkt);
243
+ long sum = 0;
244
+ /*
245
+ * https://tools.ietf.org/html/rfc1624
246
+ * HC' = ~(C + (-m) + m')
247
+ */
248
+ sum = ~(~ntohs(tcp->th_sum) - ntohs(tcp->th_sport) + NUM2USHORT(val));
249
+ while(sum>>16)
250
+ sum = (sum & 0xFFFF) + (sum >> 16);
251
+ /*
252
+ * ttps://tools.ietf.org/html/rfc1624 boundary conditions
253
+ */
254
+ if (sum == 0xFFFF)
255
+ sum = ~sum;
256
+ /*
257
+ * set desired value and new checksum
258
+ */
259
+ tcp->th_sport = htons(NUM2USHORT(val));
260
+ tcp->th_sum = htons(sum);
261
+ return val;
262
+ }
263
+
264
+ /*
265
+ Set TCP destination port and update checksum
266
+ */
267
+ static VALUE
268
+ tcpp_dport_set(self, val)
269
+ VALUE self, val;
270
+ {
271
+ struct packet_object *pkt;
272
+ struct tcphdr *tcp;
273
+ GetPacket(self, pkt);
274
+ tcp = TCP_HDR(pkt);
275
+ long sum = 0;
276
+ /*
277
+ * https://tools.ietf.org/html/rfc1624
278
+ * HC' = ~(C + (-m) + m')
279
+ */
280
+ sum = ~(~ntohs(tcp->th_sum) - ntohs(tcp->th_dport) + NUM2USHORT(val));
281
+ while(sum>>16)
282
+ sum = (sum & 0xFFFF) + (sum >> 16);
283
+ /*
284
+ * ttps://tools.ietf.org/html/rfc1624 boundary conditions
285
+ */
286
+ if (sum == 0xFFFF)
287
+ sum = ~sum;
288
+ /*
289
+ * set desired value and new checksum
290
+ */
291
+ tcp->th_dport = htons(NUM2USHORT(val));
292
+ tcp->th_sum = htons(sum);
293
+ return val;
294
+ }
295
+
296
+ /*
297
+ * IPv6 Specific methods
298
+ */
299
+
300
+ VALUE cTCPv6Packet;
301
+
302
+ #define TCPV6_DATALEN(pkt) (ntohs(IPV6_HDR(pkt)->ip6_plen) - TCP_HDR(pkt)->th_off * 4)
303
+
304
+ VALUE
305
+ setup_tcpv6_packet(pkt, tl_len)
306
+ struct packet_object *pkt;
307
+ int tl_len;
308
+ {
309
+ VALUE class;
310
+
311
+ class = cTCPv6Packet;
312
+ if (tl_len > 20) {
313
+ int hl = TCP_HDR(pkt)->th_off * 4;
314
+ int layer5_len = tl_len - hl;
315
+ if (layer5_len > 0) {
316
+ pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
317
+ /* upper layer */
318
+ }
319
+ }
320
+ return class;
321
+ }
322
+
323
+ static VALUE
324
+ tcppv6_data_len(self)
325
+ VALUE self;
326
+ {
327
+ struct packet_object *pkt;
328
+ GetPacket(self, pkt);
329
+
330
+ return INT2FIX(TCPV6_DATALEN(pkt));
331
+ }
332
+
333
+ static VALUE
334
+ tcppv6_data(self)
335
+ VALUE self;
336
+ {
337
+ struct packet_object *pkt;
338
+ int len;
339
+
340
+ DEBUG_PRINT("tcppv6_data");
341
+ GetPacket(self, pkt);
342
+
343
+ if (pkt->hdr.layer5_off == OFF_NONEXIST) return Qnil;
344
+
345
+ len = MIN(Caplen(pkt, pkt->hdr.layer5_off), TCPV6_DATALEN(pkt));
346
+ if (len < 1) return Qnil;
347
+ return rb_str_new(TCP_DATA(pkt), len);
348
+ }
349
+
350
+ static VALUE
351
+ tcpp_csumokv6(self)
352
+ VALUE self;
353
+ {
354
+ struct packet_object *pkt;
355
+ struct ip6_hdr *ip;
356
+ struct tcphdr *tcp;
357
+ GetPacket(self, pkt);
358
+ ip = IPV6_HDR(pkt);
359
+ tcp = TCP_HDR(pkt);
360
+ unsigned short *ip_src = (void *)&ip->ip6_src.s6_addr;
361
+ unsigned short *ip_dst = (void *)&ip->ip6_dst.s6_addr;
362
+ unsigned long sum = 0;
363
+ unsigned short *temp = (unsigned short *)tcp;
364
+ int len = ntohs(ip->ip6_plen); // length of ip data
365
+ unsigned short csum = ntohs(tcp->th_sum); // keep the checksum in packet
366
+
367
+ // pseudo header sum
368
+ int i = 1;
369
+ for (i = 0; i < 8; i++) {
370
+ sum += ntohs(*(ip_src));
371
+ sum += ntohs(*(ip_dst));
372
+ ip_src++;
373
+ ip_dst++;
374
+ }
375
+ sum += 0x6; /* TCP type */
376
+ sum += len; /* packet length */
377
+ // set checksum to zero and sum
378
+ tcp->th_sum = 0;
379
+ while(len > 1){
380
+ sum += ntohs(*temp++);
381
+ len -= 2;
382
+ }
383
+ if(len)
384
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
385
+ while(sum>>16)
386
+ sum = (sum & 0xFFFF) + (sum >> 16);
387
+ unsigned short answer = ~sum;
388
+
389
+ tcp->th_sum = htons(csum); //restore the checkum in packet
390
+ if (DEBUG_CHECKSUM)
391
+ printf("TCPv6 csum in packet:%d should be %d\n", csum, answer);
392
+ if (answer == csum)
393
+ return Qtrue;
394
+ return Qfalse;
395
+ }
396
+
94
397
  void
95
398
  Init_tcp_packet(void)
96
399
  {
@@ -98,11 +401,15 @@ Init_tcp_packet(void)
98
401
 
99
402
  /* define class TcpPacket */
100
403
  cTCPPacket = rb_define_class_under(mPcap, "TCPPacket", cIPPacket);
101
-
404
+ /* define methods under IPv4 */
102
405
  rb_define_method(cTCPPacket, "tcp_sport", tcpp_sport, 0);
406
+ rb_define_method(cTCPPacket, "tcp_sport=", tcpp_sport_set, 1);
103
407
  rb_define_method(cTCPPacket, "sport", tcpp_sport, 0);
408
+ rb_define_method(cTCPPacket, "sport=", tcpp_sport_set, 1);
104
409
  rb_define_method(cTCPPacket, "tcp_dport", tcpp_dport, 0);
410
+ rb_define_method(cTCPPacket, "tcp_dport=", tcpp_dport_set, 1);
105
411
  rb_define_method(cTCPPacket, "dport", tcpp_dport, 0);
412
+ rb_define_method(cTCPPacket, "dport=", tcpp_dport_set, 1);
106
413
  rb_define_method(cTCPPacket, "tcp_seq", tcpp_seq, 0);
107
414
  rb_define_method(cTCPPacket, "tcp_ack", tcpp_acknum, 0);
108
415
  rb_define_method(cTCPPacket, "tcp_off", tcpp_off, 0);
@@ -118,4 +425,37 @@ Init_tcp_packet(void)
118
425
  rb_define_method(cTCPPacket, "tcp_ack?", tcpp_ack, 0);
119
426
  rb_define_method(cTCPPacket, "tcp_urg?", tcpp_urg, 0);
120
427
  rb_define_method(cTCPPacket, "tcp_data", tcpp_data, 0);
428
+ rb_define_method(cTCPPacket, "tcp_data_len", tcpp_data_len, 0);
429
+ rb_define_method(cTCPPacket, "tcp_options", tcpp_options, 0);
430
+ rb_define_method(cTCPPacket, "tcp_csum_ok?", tcpp_csumok, 0);
431
+ rb_define_method(cTCPPacket, "tcp_truncated?", tcpp_truncated, 0);
432
+ rb_define_method(cTCPPacket, "tcp_csum_update!", tcpp_csum_update, 0);
433
+
434
+ // IPv6
435
+ cTCPv6Packet = rb_define_class_under(mPcap, "TCPv6Packet", cIPv6Packet);
436
+ /* define methods under IPv6 */
437
+ rb_define_method(cTCPv6Packet, "tcp_sport", tcpp_sport, 0);
438
+ rb_define_method(cTCPv6Packet, "sport", tcpp_sport, 0);
439
+ rb_define_method(cTCPv6Packet, "tcp_dport", tcpp_dport, 0);
440
+ rb_define_method(cTCPv6Packet, "dport", tcpp_dport, 0);
441
+ rb_define_method(cTCPv6Packet, "tcp_seq", tcpp_seq, 0);
442
+ rb_define_method(cTCPv6Packet, "tcp_ack", tcpp_acknum, 0);
443
+ rb_define_method(cTCPv6Packet, "tcp_off", tcpp_off, 0);
444
+ rb_define_method(cTCPv6Packet, "tcp_hlen", tcpp_off, 0);
445
+ rb_define_method(cTCPv6Packet, "tcp_flags", tcpp_flags, 0);
446
+ rb_define_method(cTCPv6Packet, "tcp_win", tcpp_win, 0);
447
+ rb_define_method(cTCPv6Packet, "tcp_sum", tcpp_sum, 0);
448
+ rb_define_method(cTCPv6Packet, "tcp_csumok?", tcpp_csumokv6, 0);
449
+ rb_define_method(cTCPv6Packet, "tcp_urp", tcpp_urp, 0);
450
+ rb_define_method(cTCPv6Packet, "tcp_fin?", tcpp_fin, 0);
451
+ rb_define_method(cTCPv6Packet, "tcp_syn?", tcpp_syn, 0);
452
+ rb_define_method(cTCPv6Packet, "tcp_rst?", tcpp_rst, 0);
453
+ rb_define_method(cTCPv6Packet, "tcp_psh?", tcpp_psh, 0);
454
+ rb_define_method(cTCPv6Packet, "tcp_ack?", tcpp_ack, 0);
455
+ rb_define_method(cTCPv6Packet, "tcp_urg?", tcpp_urg, 0);
456
+ rb_define_method(cTCPv6Packet, "tcp_data", tcppv6_data, 0);
457
+ rb_define_method(cTCPv6Packet, "tcp_data_len", tcppv6_data_len, 0);
458
+ rb_define_method(cTCPv6Packet, "tcp_options", tcpp_options, 0);
459
+
460
+
121
461
  }
@@ -78,6 +78,250 @@ udpp_data(self)
78
78
  return rb_str_new(UDP_DATA(pkt), len);
79
79
  }
80
80
 
81
+ static VALUE
82
+ udpp_csum_update(self)
83
+ VALUE self;
84
+ {
85
+ struct packet_object *pkt;
86
+ struct ip *ip;
87
+ struct udphdr *udp;
88
+ GetPacket(self, pkt);
89
+ ip = IP_HDR(pkt);
90
+ udp = UDP_HDR(pkt);
91
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
92
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
93
+ long sum = 0;
94
+ /* save checksum in packet */
95
+ unsigned short uh_sum = ntohs(udp->uh_sum);
96
+ unsigned short answer = 0;
97
+ unsigned short *temp = (unsigned short *)udp;
98
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
99
+
100
+ // pseudo header sum
101
+ sum += ntohs(*(ip_src++));
102
+ sum += ntohs(*ip_src);
103
+ sum += ntohs(*(ip_dst++));
104
+ sum += ntohs(*ip_dst);
105
+ sum += 17;
106
+ sum += len;
107
+ // set checksum to zero and sum
108
+ udp->uh_sum = 0;
109
+ while (len > 1){
110
+ sum += ntohs(*temp++);
111
+ len -= 2;
112
+ }
113
+ if (len)
114
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
115
+ while(sum>>16)
116
+ sum = (sum & 0xFFFF) + (sum >> 16);
117
+
118
+ answer = ~sum;
119
+ if (answer == 0)
120
+ answer = ~answer;
121
+ /*
122
+ * set checkum in packet
123
+ */
124
+ udp->uh_sum = htons(answer);
125
+ /*
126
+ * no change, return nil
127
+ */
128
+ if (answer == uh_sum)
129
+ return Qnil;
130
+ /*
131
+ * return new checkum
132
+ */
133
+ return UINT2NUM(answer);
134
+ }
135
+
136
+ /*
137
+ Set UDP source port and update checksum
138
+ */
139
+ static VALUE
140
+ udpp_sport_set(self, val)
141
+ VALUE self, val;
142
+ {
143
+ struct packet_object *pkt;
144
+ struct udphdr *udp;
145
+ long sum = 0;
146
+ GetPacket(self, pkt);
147
+ udp = UDP_HDR(pkt);
148
+ /*
149
+ * https://tools.ietf.org/html/rfc1624
150
+ * HC' = ~(C + (-m) + m')
151
+ */
152
+ sum = ~(~ntohs(udp->uh_sum) - ntohs(udp->uh_sport) + NUM2USHORT(val));
153
+ while(sum>>16)
154
+ sum = (sum & 0xFFFF) + (sum >> 16);
155
+ /*
156
+ * set desired value and new checksum
157
+ */
158
+ udp->uh_sport = htons(NUM2USHORT(val));
159
+ udp->uh_sum = htons(sum);
160
+ return val;
161
+ }
162
+ /*
163
+ Set UDP destination port and update checksum
164
+ */
165
+ static VALUE
166
+ udpp_dport_set(self, val)
167
+ VALUE self, val;
168
+ {
169
+ struct packet_object *pkt;
170
+ struct udphdr *udp;
171
+ long sum = 0;
172
+ GetPacket(self, pkt);
173
+ udp = UDP_HDR(pkt);
174
+ /*
175
+ * https://tools.ietf.org/html/rfc1624
176
+ * HC' = ~(C + (-m) + m')
177
+ */
178
+ sum = ~(~ntohs(udp->uh_sum) - ntohs(udp->uh_dport) + NUM2USHORT(val));
179
+ while(sum>>16)
180
+ sum = (sum & 0xFFFF) + (sum >> 16);
181
+ /*
182
+ * set desired value and new checksum
183
+ */
184
+ udp->uh_dport = htons(NUM2USHORT(val));
185
+ udp->uh_sum = htons(sum);
186
+ return val;
187
+ }
188
+ /*
189
+ * IPv6 Specific methods
190
+ */
191
+ VALUE cUDPv6Packet;
192
+
193
+ VALUE
194
+ setup_udpv6_packet(pkt, tl_len)
195
+ struct packet_object *pkt;
196
+ int tl_len;
197
+ {
198
+ VALUE class;
199
+ DEBUG_PRINT("setup_udpv6_packet");
200
+ class = cUDPv6Packet;
201
+ if (tl_len > 8) {
202
+ int hl = 8;
203
+ int layer5_len;
204
+
205
+ tl_len = MIN(tl_len, UDP_LENGTH(pkt));
206
+ layer5_len = tl_len - hl;
207
+ if (layer5_len > 0) {
208
+ pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
209
+ /* upper layer */
210
+ }
211
+ }
212
+ return class;
213
+ }
214
+
215
+ static VALUE
216
+ udpp_csumokv6(self)
217
+ VALUE self;
218
+ {
219
+ struct packet_object *pkt;
220
+ struct ip6_hdr *ip;
221
+ struct udphdr *udp;
222
+ GetPacket(self, pkt);
223
+ ip = IPV6_HDR(pkt);
224
+ udp = UDP_HDR(pkt);
225
+ unsigned short *ip_src = (void *)&ip->ip6_src.s6_addr;
226
+ unsigned short *ip_dst = (void *)&ip->ip6_dst.s6_addr;
227
+ long sum = 0;
228
+ unsigned short answer = 0;
229
+ unsigned short *temp = (unsigned short *)udp;
230
+ int len = ntohs(ip->ip6_plen); // length of ip data
231
+ unsigned short csum = ntohs(udp->uh_sum); // keep the checksum in packet
232
+
233
+ // pseudo header sum
234
+ int i = 1;
235
+ for (i = 0; i < 8; i++) {
236
+ sum += ntohs(*(ip_src));
237
+ sum += ntohs(*(ip_dst));
238
+ ip_src++;
239
+ ip_dst++;
240
+ }
241
+ sum += 0x11; // UDP
242
+ sum += len;
243
+ // set checksum to zero and sum
244
+ udp->uh_sum = 0;
245
+ while (len > 1){
246
+ sum += ntohs(*temp++);
247
+ len -= 2;
248
+ }
249
+ if (len)
250
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
251
+ while(sum>>16)
252
+ sum = (sum & 0xFFFF) + (sum >> 16);
253
+ answer = ~sum;
254
+ if (answer == 0)
255
+ answer = ~answer;
256
+ udp->uh_sum = htons(csum); //restore the checkum in packet
257
+ if (DEBUG_CHECKSUM)
258
+ printf("UDP csum in packet:%d should be %d\n", csum, answer);
259
+ if (answer == csum)
260
+ return Qtrue;
261
+ return Qfalse;
262
+ }
263
+
264
+ static VALUE
265
+ udpp_csumok(self)
266
+ VALUE self;
267
+ {
268
+ struct packet_object *pkt;
269
+ struct ip *ip;
270
+ struct udphdr *udp;
271
+ GetPacket(self, pkt);
272
+ ip = IP_HDR(pkt);
273
+ udp = UDP_HDR(pkt);
274
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
275
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
276
+ long sum = 0;
277
+ unsigned short answer = 0;
278
+ unsigned short *temp = (unsigned short *)udp;
279
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
280
+ int csum = ntohs(udp->uh_sum); // keep the checksum in packet
281
+
282
+ // pseudo header sum
283
+ sum += ntohs(*(ip_src++));
284
+ sum += ntohs(*ip_src);
285
+ sum += ntohs(*(ip_dst++));
286
+ sum += ntohs(*ip_dst);
287
+ sum += 17;
288
+ sum += len;
289
+ // set checksum to zero and sum
290
+ udp->uh_sum = 0;
291
+ while (len > 1){
292
+ sum += ntohs(*temp++);
293
+ len -= 2;
294
+ }
295
+ if (len)
296
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
297
+ while(sum>>16)
298
+ sum = (sum & 0xFFFF) + (sum >> 16);
299
+
300
+ answer = ~sum;
301
+ if (answer == 0)
302
+ answer = ~answer;
303
+ udp->uh_sum = csum; //restore the checkum in packet
304
+ if (DEBUG_CHECKSUM)
305
+ printf("UDP csum in packet:%d should be %d\n", csum, answer);
306
+ if (answer == csum)
307
+ return Qtrue;
308
+ return Qfalse;
309
+ }
310
+ static VALUE
311
+ udpp_truncated(self)
312
+ VALUE self;
313
+ {
314
+ struct packet_object *pkt;
315
+ struct ip *ip;
316
+ struct udphdr *udp;
317
+ GetPacket(self, pkt);
318
+ ip = IP_HDR(pkt);
319
+ udp = UDP_HDR(pkt);
320
+ if IsTruncated(pkt, pkt->hdr.layer3_off, ip->ip_hl * 4 + ntohs(udp->uh_ulen))
321
+ return Qtrue;
322
+ return Qfalse;
323
+ }
324
+
81
325
  void
82
326
  Init_udp_packet(void)
83
327
  {
@@ -85,12 +329,29 @@ Init_udp_packet(void)
85
329
 
86
330
  /* define class UdpPacket */
87
331
  cUDPPacket = rb_define_class_under(mPcap, "UDPPacket", cIPPacket);
88
-
332
+ cUDPv6Packet = rb_define_class_under(mPcap, "UDPv6Packet", cIPv6Packet);
333
+ /* define methods under IPv4 */
89
334
  rb_define_method(cUDPPacket, "udp_sport", udpp_sport, 0);
335
+ rb_define_method(cUDPPacket, "udp_sport=", udpp_sport_set, 1);
90
336
  rb_define_method(cUDPPacket, "sport", udpp_sport, 0);
337
+ rb_define_method(cUDPPacket, "sport=", udpp_sport_set, 1);
91
338
  rb_define_method(cUDPPacket, "udp_dport", udpp_dport, 0);
339
+ rb_define_method(cUDPPacket, "udp_dport=", udpp_dport_set, 1);
92
340
  rb_define_method(cUDPPacket, "dport", udpp_dport, 0);
341
+ rb_define_method(cUDPPacket, "dport=", udpp_dport_set, 1);
93
342
  rb_define_method(cUDPPacket, "udp_len", udpp_len, 0);
94
343
  rb_define_method(cUDPPacket, "udp_sum", udpp_sum, 0);
95
344
  rb_define_method(cUDPPacket, "udp_data", udpp_data, 0);
345
+ rb_define_method(cUDPPacket, "udp_csum_ok?", udpp_csumok, 0);
346
+ rb_define_method(cUDPPacket, "udp_truncated?", udpp_truncated, 0);
347
+ rb_define_method(cUDPPacket, "udp_csum_update!", udpp_csum_update, 0);
348
+ /* define methods under IPv6 */
349
+ rb_define_method(cUDPv6Packet, "udp_sport", udpp_sport, 0);
350
+ rb_define_method(cUDPv6Packet, "sport", udpp_sport, 0);
351
+ rb_define_method(cUDPv6Packet, "udp_dport", udpp_dport, 0);
352
+ rb_define_method(cUDPv6Packet, "dport", udpp_dport, 0);
353
+ rb_define_method(cUDPv6Packet, "udp_len", udpp_len, 0);
354
+ rb_define_method(cUDPv6Packet, "udp_sum", udpp_sum, 0);
355
+ rb_define_method(cUDPv6Packet, "udp_data", udpp_data, 0);
356
+ rb_define_method(cUDPv6Packet, "udp_csum_ok?", udpp_csumokv6, 0);
96
357
  }