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.
- 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
|
}
|