ruby-pcap 0.7.9 → 0.8.1

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