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.
- checksums.yaml +5 -5
- data/.github/workflows/build.yml +26 -0
- data/README.md +3 -7
- data/examples/capture_duration.rb +28 -0
- data/ext/pcap/Pcap.c +152 -23
- data/ext/pcap/arp_packet.c +82 -0
- data/ext/pcap/icmp_packet.c +35 -0
- data/ext/pcap/icmpv6_packet.c +107 -0
- data/ext/pcap/ip_packet.c +16 -7
- data/ext/pcap/ipv6_packet.c +162 -0
- data/ext/pcap/packet.c +36 -8
- data/ext/pcap/ruby_pcap.h +34 -4
- data/ext/pcap/slow_protocol_packet.c +29 -0
- data/ext/pcap/tcp_packet.c +346 -6
- data/ext/pcap/udp_packet.c +262 -1
- data/lib/pcap/packet.rb +123 -11
- data/ruby-pcap.gemspec +4 -4
- metadata +16 -10
- data/.travis.yml +0 -13
data/ext/pcap/tcp_packet.c
CHANGED
@@ -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
|
-
|
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
|
}
|
data/ext/pcap/udp_packet.c
CHANGED
@@ -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
|
}
|