ruby-pcap 0.7.9 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -4
- data/ext/pcap/Pcap.c +125 -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 +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 78bf37291d08a1c9dbe2ab08269e494dbb8f3c5d6a37932e3468ca30c4899648
|
4
|
+
data.tar.gz: 42cb108300efda78d65a7f742f691863a226cd4365339ef0a68a97ebfae0987e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5572b9bdb5361c4b2e5061e20af5c15257e1c22dee6c747b86edff3053949795003ab892fb1b3e4f0ce77363a1f2c046a3a696d79cc047f3d178d81360a777e7
|
7
|
+
data.tar.gz: 28cb162c6fdd85499effb7c397364e1f90828292c9da9465d789a8d798c594e8f45632fd62955900a015961701f01e0ecbfb5b8c61a0440a687dd26263c786c8
|
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
## ruby-pcap
|
2
3
|
|
3
4
|
[![Build Status](https://travis-ci.org/ickymettle/ruby-pcap.svg)](https://travis-ci.org/ickymettle/ruby-pcap)
|
@@ -26,10 +27,6 @@ Directory 'examples' contains some simple scripts.
|
|
26
27
|
|
27
28
|
Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
|
28
29
|
|
29
|
-
## Maintained by
|
30
|
-
|
31
|
-
Marcus Barczak <mbarczak@etsy.com>
|
32
|
-
|
33
30
|
## Copyright
|
34
31
|
|
35
32
|
ruby-pcap is copyrighted free software by Masaki Fukushima.
|
data/ext/pcap/Pcap.c
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
*/
|
8
8
|
|
9
9
|
#include "ruby_pcap.h"
|
10
|
-
#include "rubysig.h"
|
11
10
|
#include <sys/time.h>
|
12
11
|
#include <sys/types.h>
|
13
12
|
#include <unistd.h>
|
@@ -318,36 +317,112 @@ handler(cap, pkthdr, data)
|
|
318
317
|
rb_yield(new_packet(data, pkthdr, cap->dl_type));
|
319
318
|
}
|
320
319
|
|
320
|
+
#define DST_ADDR(data) INT2FIX(ntohl(*((unsigned int *) (data + 30))))
|
321
|
+
#define SRC_ADDR(data) INT2FIX(ntohl(*((unsigned int *) (data + 26))))
|
322
|
+
|
323
|
+
static void
|
324
|
+
dst_ipv4_addr_handler(cap, pkthdr, data)
|
325
|
+
struct capture_object *cap;
|
326
|
+
const struct pcap_pkthdr *pkthdr;
|
327
|
+
const u_char *data;
|
328
|
+
{
|
329
|
+
rb_yield(DST_ADDR(data));
|
330
|
+
}
|
331
|
+
|
332
|
+
static void
|
333
|
+
src_ipv4_addr_handler(cap, pkthdr, data)
|
334
|
+
struct capture_object *cap;
|
335
|
+
const struct pcap_pkthdr *pkthdr;
|
336
|
+
const u_char *data;
|
337
|
+
{
|
338
|
+
rb_yield(SRC_ADDR(data));
|
339
|
+
}
|
340
|
+
|
341
|
+
#define SRCV6_ADDR(data) rb_integer_unpack((u_char *) (data + 22), 16, 1, 0, INTEGER_PACK_BIG_ENDIAN)
|
342
|
+
#define DSTV6_ADDR(data) rb_integer_unpack((u_char *) (data + 38), 16, 1, 0, INTEGER_PACK_BIG_ENDIAN)
|
343
|
+
|
344
|
+
static void
|
345
|
+
dst_ipv6_addr_handler(cap, pkthdr, data)
|
346
|
+
struct capture_object *cap;
|
347
|
+
const struct pcap_pkthdr *pkthdr;
|
348
|
+
const u_char *data;
|
349
|
+
{
|
350
|
+
rb_yield(DSTV6_ADDR(data));
|
351
|
+
}
|
352
|
+
|
353
|
+
static void
|
354
|
+
src_ipv6_addr_handler(cap, pkthdr, data)
|
355
|
+
struct capture_object *cap;
|
356
|
+
const struct pcap_pkthdr *pkthdr;
|
357
|
+
const u_char *data;
|
358
|
+
{
|
359
|
+
rb_yield(SRCV6_ADDR(data));
|
360
|
+
}
|
361
|
+
|
362
|
+
void parse_opts(VALUE v_opts, void **default_handler)
|
363
|
+
{
|
364
|
+
if (NIL_P(v_opts)) {
|
365
|
+
DEBUG_PRINT("using default capture handler");
|
366
|
+
*default_handler = &handler;
|
367
|
+
} else {
|
368
|
+
// raise error if second argument is not a symbol
|
369
|
+
Check_Type(v_opts, T_SYMBOL);
|
370
|
+
// only :source, :destination are supported
|
371
|
+
if (SYM2ID(v_opts) == rb_intern("source")) {
|
372
|
+
DEBUG_PRINT("yeilding only source ipv4 addresses");
|
373
|
+
*default_handler = &src_ipv4_addr_handler;
|
374
|
+
} else if (SYM2ID(v_opts) == rb_intern("destination")) {
|
375
|
+
DEBUG_PRINT("yeilding only destination ipv4 addresses");
|
376
|
+
*default_handler = &dst_ipv4_addr_handler;
|
377
|
+
} else if (SYM2ID(v_opts) == rb_intern("destinationv6")) {
|
378
|
+
DEBUG_PRINT("yeilding only destination ipv6 addresses");
|
379
|
+
*default_handler = &dst_ipv6_addr_handler;
|
380
|
+
} else if (SYM2ID(v_opts) == rb_intern("sourcev6")) {
|
381
|
+
DEBUG_PRINT("yeilding only source ipv6 addresses");
|
382
|
+
*default_handler = &src_ipv6_addr_handler;
|
383
|
+
} else {
|
384
|
+
// unkonw keyword passed, use default capture handler
|
385
|
+
DEBUG_PRINT("unknown option, using default capture handler");
|
386
|
+
*default_handler = &handler;
|
387
|
+
}
|
388
|
+
}
|
389
|
+
}
|
390
|
+
|
321
391
|
static VALUE
|
322
392
|
capture_dispatch(argc, argv, self)
|
323
393
|
int argc;
|
324
394
|
VALUE *argv;
|
325
395
|
VALUE self;
|
326
396
|
{
|
327
|
-
VALUE v_cnt;
|
328
|
-
int cnt;
|
397
|
+
VALUE v_cnt, v_opts;
|
398
|
+
int ret = 0, cnt = 0;
|
399
|
+
unsigned int cap_cnt = 0;
|
329
400
|
struct capture_object *cap;
|
330
|
-
|
401
|
+
void *default_handler;
|
331
402
|
|
332
403
|
DEBUG_PRINT("capture_dispatch");
|
333
404
|
GetCapture(self, cap);
|
334
405
|
|
335
406
|
/* scan arg */
|
336
|
-
|
337
|
-
|
338
|
-
|
407
|
+
rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
|
408
|
+
if (NIL_P(v_cnt)) {
|
409
|
+
cnt = -1;
|
339
410
|
} else {
|
340
|
-
|
411
|
+
FIXNUM_P(v_cnt);
|
412
|
+
cnt = FIX2INT(v_cnt);
|
341
413
|
}
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
414
|
+
parse_opts(v_opts, &default_handler);
|
415
|
+
// call dispatch with 10,000 and break if we have reached desired amount
|
416
|
+
// if dispatch is called with -1/0 sometimes it dispatches millions of packets
|
417
|
+
for (cap_cnt = 0; cap_cnt < cnt; cap_cnt += ret ) {
|
418
|
+
MAYBE_TRAP_BEG;
|
419
|
+
ret = pcap_dispatch(cap->pcap, 10000, default_handler, (u_char *)cap);
|
420
|
+
MAYBE_TRAP_END;
|
421
|
+
if (ret < 0) {
|
347
422
|
rb_raise(ePcapError, "dispatch: %s", pcap_geterr(cap->pcap));
|
423
|
+
}
|
348
424
|
}
|
349
|
-
|
350
|
-
return INT2FIX(ret);
|
425
|
+
return UINT2NUM(cap_cnt);
|
351
426
|
}
|
352
427
|
|
353
428
|
static VALUE
|
@@ -373,25 +448,27 @@ capture_loop(argc, argv, self)
|
|
373
448
|
VALUE *argv;
|
374
449
|
VALUE self;
|
375
450
|
{
|
376
|
-
VALUE v_cnt;
|
451
|
+
VALUE v_cnt, v_opts;
|
377
452
|
int cnt;
|
378
453
|
struct capture_object *cap;
|
379
454
|
int ret;
|
455
|
+
void *default_handler;
|
380
456
|
|
381
457
|
DEBUG_PRINT("capture_loop");
|
382
458
|
GetCapture(self, cap);
|
383
459
|
|
384
460
|
/* scan arg */
|
385
|
-
|
386
|
-
|
387
|
-
|
461
|
+
rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
|
462
|
+
if (NIL_P(v_cnt)) {
|
463
|
+
cnt = -1;
|
388
464
|
} else {
|
389
|
-
|
465
|
+
FIXNUM_P(v_cnt);
|
466
|
+
cnt = FIX2INT(v_cnt);
|
390
467
|
}
|
391
|
-
|
468
|
+
parse_opts(v_opts, &default_handler);
|
392
469
|
if (pcap_file(cap->pcap) != NULL) {
|
393
470
|
MAYBE_TRAP_BEG;
|
394
|
-
ret = pcap_loop(cap->pcap, cnt,
|
471
|
+
ret = pcap_loop(cap->pcap, cnt, default_handler, (u_char *)cap);
|
395
472
|
MAYBE_TRAP_END;
|
396
473
|
}
|
397
474
|
else {
|
@@ -409,7 +486,7 @@ capture_loop(argc, argv, self)
|
|
409
486
|
rb_thread_wait_fd(fd);
|
410
487
|
}
|
411
488
|
MAYBE_TRAP_BEG;
|
412
|
-
ret = pcap_dispatch(cap->pcap, 1,
|
489
|
+
ret = pcap_dispatch(cap->pcap, 1, default_handler, (u_char *)cap);
|
413
490
|
MAYBE_TRAP_END;
|
414
491
|
} while (ret == 0);
|
415
492
|
|
@@ -540,6 +617,30 @@ capture_inject(self, v_buf)
|
|
540
617
|
return Qnil;
|
541
618
|
}
|
542
619
|
|
620
|
+
// configure capture direction: IN/OUT packets
|
621
|
+
static VALUE
|
622
|
+
capture_direction(self, direction)
|
623
|
+
VALUE direction;
|
624
|
+
VALUE self;
|
625
|
+
{
|
626
|
+
struct capture_object *cap;
|
627
|
+
// default value is in and out packets
|
628
|
+
int v_direction = PCAP_D_INOUT;
|
629
|
+
|
630
|
+
DEBUG_PRINT("capture_direction");
|
631
|
+
GetCapture(self, cap);
|
632
|
+
Check_Type(direction, T_SYMBOL);
|
633
|
+
// set desired direction: :in,:out or both
|
634
|
+
if (SYM2ID(direction) == rb_intern("in")) {
|
635
|
+
DEBUG_PRINT("setting capture direction IN");
|
636
|
+
v_direction = PCAP_D_IN;
|
637
|
+
} else if (SYM2ID(direction) == rb_intern("out")) {
|
638
|
+
DEBUG_PRINT("setting capture direction OUT");
|
639
|
+
v_direction = PCAP_D_OUT;
|
640
|
+
}
|
641
|
+
return INT2NUM(pcap_setdirection(cap->pcap, v_direction));
|
642
|
+
}
|
643
|
+
|
543
644
|
/*
|
544
645
|
* Dumper object
|
545
646
|
*/
|
@@ -905,6 +1006,7 @@ Init_pcap(void)
|
|
905
1006
|
rb_define_method(cCapture, "snaplen", capture_snapshot, 0);
|
906
1007
|
rb_define_method(cCapture, "stats", capture_stats, 0);
|
907
1008
|
rb_define_method(cCapture, "inject", capture_inject, 1);
|
1009
|
+
rb_define_method(cCapture, "direction", capture_direction, 1);
|
908
1010
|
|
909
1011
|
/* define class Dumper */
|
910
1012
|
cDumper = rb_define_class_under(mPcap, "Dumper", rb_cObject);
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/*
|
2
|
+
* arp_packet.c
|
3
|
+
*
|
4
|
+
* $Id: arp_packet.c,v 0.1
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "ruby_pcap.h"
|
9
|
+
#include <netdb.h>
|
10
|
+
|
11
|
+
struct arphdr
|
12
|
+
{
|
13
|
+
unsigned short int ar_hrd; /* Format of hardware address. */
|
14
|
+
unsigned short int ar_pro; /* Format of protocol address. */
|
15
|
+
unsigned char ar_hln; /* Length of hardware address. */
|
16
|
+
unsigned char ar_pln; /* Length of protocol address. */
|
17
|
+
unsigned short int ar_op; /* ARP opcode (command). */
|
18
|
+
unsigned char ar_sha[6]; /* Sender hardware address. */
|
19
|
+
unsigned char ar_sip[4]; /* Sender IP address. */
|
20
|
+
unsigned char ar_tha[6]; /* Target hardware address. */
|
21
|
+
unsigned char ar_tip[4]; /* Target IP address. */
|
22
|
+
};
|
23
|
+
|
24
|
+
|
25
|
+
VALUE cARPPacket;
|
26
|
+
|
27
|
+
VALUE
|
28
|
+
setup_arp_packet(pkt, nl_len)
|
29
|
+
struct packet_object *pkt;
|
30
|
+
int nl_len;
|
31
|
+
{
|
32
|
+
VALUE class;
|
33
|
+
|
34
|
+
DEBUG_PRINT("setup_arp_packet");
|
35
|
+
|
36
|
+
class = cARPPacket;
|
37
|
+
|
38
|
+
return class;
|
39
|
+
}
|
40
|
+
|
41
|
+
#define ARP_HDR(pkt) ((struct arphdr *)LAYER3_HDR(pkt))
|
42
|
+
|
43
|
+
#define ARPP_METHOD(func, val) \
|
44
|
+
static VALUE\
|
45
|
+
(func)(self)\
|
46
|
+
VALUE self;\
|
47
|
+
{\
|
48
|
+
struct packet_object *pkt;\
|
49
|
+
struct arphdr *arp;\
|
50
|
+
DEBUG_PRINT(#func);\
|
51
|
+
GetPacket(self, pkt);\
|
52
|
+
arp = ARP_HDR(pkt);\
|
53
|
+
return (val);\
|
54
|
+
}
|
55
|
+
|
56
|
+
ARPP_METHOD(arpp_hw, INT2FIX(ntohs(arp->ar_hrd)))
|
57
|
+
ARPP_METHOD(arpp_prot, INT2FIX(ntohs(arp->ar_pro)))
|
58
|
+
ARPP_METHOD(arpp_hlen, INT2FIX(arp->ar_hln))
|
59
|
+
ARPP_METHOD(arpp_plen, INT2FIX(arp->ar_pln))
|
60
|
+
ARPP_METHOD(arpp_op, INT2FIX(ntohs(arp->ar_op)))
|
61
|
+
ARPP_METHOD(arpp_s_hw, rb_str_new(arp->ar_sha,6))
|
62
|
+
ARPP_METHOD(arpp_s_ip, UINT32_2_NUM(ntohl( *((unsigned long int *) arp->ar_sip))))
|
63
|
+
ARPP_METHOD(arpp_t_hw, rb_str_new(arp->ar_tha,6))
|
64
|
+
ARPP_METHOD(arpp_t_ip, UINT32_2_NUM(ntohl( *((unsigned long int *) arp->ar_tip))))
|
65
|
+
|
66
|
+
|
67
|
+
void
|
68
|
+
Init_arp_packet(void)
|
69
|
+
{
|
70
|
+
DEBUG_PRINT("Init_arp_packet");
|
71
|
+
|
72
|
+
cARPPacket = rb_define_class_under(mPcap, "ARPPacket", cPacket);
|
73
|
+
rb_define_method(cARPPacket, "hw", arpp_hw, 0);
|
74
|
+
rb_define_method(cARPPacket, "protocol", arpp_prot, 0);
|
75
|
+
rb_define_method(cARPPacket, "hwlen", arpp_hlen, 0);
|
76
|
+
rb_define_method(cARPPacket, "plen", arpp_plen, 0);
|
77
|
+
rb_define_method(cARPPacket, "op_code", arpp_op, 0);
|
78
|
+
rb_define_method(cARPPacket, "sender_hw", arpp_s_hw, 0);
|
79
|
+
rb_define_method(cARPPacket, "sender_ip", arpp_s_ip, 0);
|
80
|
+
rb_define_method(cARPPacket, "target_hw", arpp_t_hw, 0);
|
81
|
+
rb_define_method(cARPPacket, "target_ip", arpp_t_ip, 0);
|
82
|
+
}
|
data/ext/pcap/icmp_packet.c
CHANGED
@@ -232,6 +232,40 @@ icmpp_radv(self, ind)
|
|
232
232
|
rb_ary_push(ary, INT2NUM(ntohl(IDRD(icmp)->ird_pref)));
|
233
233
|
return ary;
|
234
234
|
}
|
235
|
+
static VALUE
|
236
|
+
icmpp_csumok(self)
|
237
|
+
VALUE self;
|
238
|
+
{
|
239
|
+
struct packet_object *pkt;
|
240
|
+
struct ip *ip;
|
241
|
+
struct icmp *icmp;
|
242
|
+
GetPacket(self, pkt);
|
243
|
+
ip = IP_HDR(pkt);
|
244
|
+
icmp = ICMP_HDR(pkt);
|
245
|
+
|
246
|
+
long sum = 0;
|
247
|
+
unsigned short *temp = (unsigned short *)icmp;
|
248
|
+
int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
|
249
|
+
int csum = ntohs(icmp->icmp_cksum); // keep the checksum in packet
|
250
|
+
|
251
|
+
icmp->icmp_cksum = 0;
|
252
|
+
while(len > 1){
|
253
|
+
sum += ntohs(*temp++);
|
254
|
+
len -= 2;
|
255
|
+
}
|
256
|
+
if(len)
|
257
|
+
sum += ntohs((unsigned short) *((unsigned char *)temp));
|
258
|
+
while(sum>>16)
|
259
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
260
|
+
unsigned short answer = ~sum;
|
261
|
+
|
262
|
+
icmp->icmp_cksum = csum; //restore the checkum in packet
|
263
|
+
if (DEBUG_CHECKSUM)
|
264
|
+
printf("ICMP csum in packet:%d should be %d\n", csum, answer);
|
265
|
+
if (answer == csum)
|
266
|
+
return Qtrue;
|
267
|
+
return Qfalse;
|
268
|
+
}
|
235
269
|
|
236
270
|
#define time_new_msec(t) rb_time_new((t)/1000, (t)%1000 * 1000)
|
237
271
|
ICMPP_METHOD(icmpp_otime, 12, time_new_msec(ntohl(icmp->icmp_otime)))
|
@@ -336,6 +370,7 @@ Init_icmp_packet(void)
|
|
336
370
|
rb_define_method(cICMPPacket, "icmp_typestr", icmpp_typestr, 0);
|
337
371
|
rb_define_method(cICMPPacket, "icmp_code", icmpp_code, 0);
|
338
372
|
rb_define_method(cICMPPacket, "icmp_cksum", icmpp_cksum, 0);
|
373
|
+
rb_define_method(cICMPPacket, "icmp_csum_ok?", icmpp_csumok, 0);
|
339
374
|
|
340
375
|
klass = rb_define_class_under(mPcap, "ICMPEchoReply", cICMPPacket);
|
341
376
|
icmp_types[ICMP_ECHOREPLY].klass = klass;
|
@@ -0,0 +1,107 @@
|
|
1
|
+
/*
|
2
|
+
* icmpv6_packet.c
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "ruby_pcap.h"
|
6
|
+
|
7
|
+
#define ICMPV6_HDR(pkt) ((struct icmp6_hdr *)LAYER4_HDR(pkt))
|
8
|
+
#define ICMP_CAPLEN(pkt) (pkt->hdr.pkthdr.caplen - pkt->hdr.layer4_off)
|
9
|
+
|
10
|
+
VALUE cICMPv6Packet;
|
11
|
+
|
12
|
+
#define CheckTruncateICMP(pkt, need) CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated ICMPv6")
|
13
|
+
|
14
|
+
|
15
|
+
VALUE
|
16
|
+
setup_icmpv6_packet(pkt)
|
17
|
+
struct packet_object *pkt;
|
18
|
+
{
|
19
|
+
return cICMPv6Packet;
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
#define ICMPP_METHOD(func, need, val) \
|
24
|
+
static VALUE\
|
25
|
+
(func)(self)\
|
26
|
+
VALUE self;\
|
27
|
+
{\
|
28
|
+
struct packet_object *pkt;\
|
29
|
+
struct icmp6_hdr *icmp;\
|
30
|
+
GetPacket(self, pkt);\
|
31
|
+
CheckTruncateICMP(pkt, (need));\
|
32
|
+
icmp = ICMPV6_HDR(pkt);\
|
33
|
+
return (val);\
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
* Common methods based on icmp6_hdr
|
38
|
+
*/
|
39
|
+
|
40
|
+
ICMPP_METHOD(icmpp_type, 1, INT2FIX(icmp->icmp6_type))
|
41
|
+
ICMPP_METHOD(icmpp_code, 2, INT2FIX(icmp->icmp6_code))
|
42
|
+
ICMPP_METHOD(icmpp_cksum, 4, INT2FIX(ntohs(icmp->icmp6_cksum)))
|
43
|
+
/* 4 Bytes is the common ICMPv6 Header*/
|
44
|
+
ICMPP_METHOD(icmppv6_data, 5, rb_str_new(icmp->icmp6_data8, ICMP_CAPLEN(pkt)-4))
|
45
|
+
|
46
|
+
|
47
|
+
static VALUE
|
48
|
+
icmpp_csumokv6(self)
|
49
|
+
VALUE self;
|
50
|
+
{
|
51
|
+
struct packet_object *pkt;
|
52
|
+
struct ip6_hdr *ip;
|
53
|
+
struct icmp6_hdr *icmp;
|
54
|
+
GetPacket(self, pkt);
|
55
|
+
ip = IPV6_HDR(pkt);
|
56
|
+
icmp = ICMPV6_HDR(pkt);
|
57
|
+
|
58
|
+
long sum = 0;
|
59
|
+
unsigned short *temp = (unsigned short *)icmp;
|
60
|
+
int len = ntohs(ip->ip6_plen); // length of ip data
|
61
|
+
int csum = ntohs(icmp->icmp6_cksum); // keep the checksum in packet
|
62
|
+
unsigned short *ip_src = (void *)&ip->ip6_src.s6_addr;
|
63
|
+
unsigned short *ip_dst = (void *)&ip->ip6_dst.s6_addr;
|
64
|
+
|
65
|
+
// ICMPv6 now inclides pseudo header sum
|
66
|
+
int i = 1;
|
67
|
+
for (i = 0; i < 8; i++) {
|
68
|
+
sum += ntohs(*(ip_src));
|
69
|
+
sum += ntohs(*(ip_dst));
|
70
|
+
ip_src++;
|
71
|
+
ip_dst++;
|
72
|
+
}
|
73
|
+
sum += 58; // ICMPv6 next header value
|
74
|
+
sum += len;
|
75
|
+
|
76
|
+
icmp->icmp6_cksum = 0;
|
77
|
+
while(len > 1){
|
78
|
+
sum += ntohs(*temp++);
|
79
|
+
len -= 2;
|
80
|
+
}
|
81
|
+
if(len)
|
82
|
+
sum += ntohs((unsigned short) *((unsigned char *)temp));
|
83
|
+
while(sum>>16)
|
84
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
85
|
+
unsigned short answer = ~sum;
|
86
|
+
|
87
|
+
icmp->icmp6_cksum = csum; //restore the checkum in packet
|
88
|
+
if (DEBUG_CHECKSUM)
|
89
|
+
printf("ICMP csum in packet:%d should be %d\n", csum, answer);
|
90
|
+
if (answer == csum)
|
91
|
+
return Qtrue;
|
92
|
+
return Qfalse;
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
void
|
97
|
+
Init_icmpv6_packet(void)
|
98
|
+
{
|
99
|
+
|
100
|
+
cICMPv6Packet = rb_define_class_under(mPcap, "ICMPv6Packet", cIPv6Packet);
|
101
|
+
|
102
|
+
rb_define_method(cICMPv6Packet, "icmp_type", icmpp_type, 0);
|
103
|
+
rb_define_method(cICMPv6Packet, "icmp_code", icmpp_code, 0);
|
104
|
+
rb_define_method(cICMPv6Packet, "icmp_cksum", icmpp_cksum, 0);
|
105
|
+
rb_define_method(cICMPv6Packet, "icmp_csum_ok?", icmpp_csumokv6, 0);
|
106
|
+
rb_define_method(cICMPv6Packet, "icmp_data", icmppv6_data, 0);
|
107
|
+
}
|
data/ext/pcap/ip_packet.c
CHANGED
@@ -14,8 +14,7 @@ static VALUE cIPAddress;
|
|
14
14
|
|
15
15
|
static unsigned short in_cksum(unsigned char *data, int len);
|
16
16
|
|
17
|
-
#define CheckTruncateIp(pkt, need)
|
18
|
-
CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IP")
|
17
|
+
#define CheckTruncateIp(pkt, need) CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IP")
|
19
18
|
|
20
19
|
VALUE
|
21
20
|
setup_ip_packet(pkt, nl_len)
|
@@ -49,7 +48,7 @@ setup_ip_packet(pkt, nl_len)
|
|
49
48
|
case IPPROTO_ICMP:
|
50
49
|
class = setup_icmp_packet(pkt, tl_len);
|
51
50
|
break;
|
52
|
-
}
|
51
|
+
}
|
53
52
|
}
|
54
53
|
}
|
55
54
|
}
|
@@ -149,6 +148,19 @@ ipp_sumok(self)
|
|
149
148
|
return Qfalse;
|
150
149
|
}
|
151
150
|
|
151
|
+
static VALUE
|
152
|
+
ipp_truncated(self)
|
153
|
+
VALUE self;
|
154
|
+
{
|
155
|
+
struct packet_object *pkt;
|
156
|
+
struct ip *ip;
|
157
|
+
GetPacket(self, pkt);
|
158
|
+
ip = IP_HDR(pkt);
|
159
|
+
if IsTruncated(pkt, pkt->hdr.layer3_off, ntohs(ip->ip_len))
|
160
|
+
return Qtrue;
|
161
|
+
return Qfalse;
|
162
|
+
}
|
163
|
+
|
152
164
|
static unsigned short
|
153
165
|
in_cksum(unsigned char *data, int len)
|
154
166
|
{
|
@@ -401,6 +413,7 @@ Init_ip_packet(void)
|
|
401
413
|
rb_define_method(cIPPacket, "dst=", ipp_set_dst, 1);
|
402
414
|
rb_define_method(cIPPacket, "ip_data", ipp_data, 0);
|
403
415
|
rb_define_method(cIPPacket, "ip_sum_update!", ipp_sum_update, 0);
|
416
|
+
rb_define_method(cIPPacket, "ip_truncated?", ipp_truncated, 0);
|
404
417
|
|
405
418
|
cIPAddress = rb_define_class_under(mPcap, "IPAddress", rb_cObject);
|
406
419
|
rb_define_singleton_method(cIPAddress, "new", ipaddr_s_new, 1);
|
@@ -417,8 +430,4 @@ Init_ip_packet(void)
|
|
417
430
|
|
418
431
|
rb_define_method(cIPAddress, "_dump", ipaddr_dump, 1);
|
419
432
|
rb_define_singleton_method(cIPAddress, "_load", ipaddr_s_load, 1);
|
420
|
-
|
421
|
-
Init_tcp_packet();
|
422
|
-
Init_udp_packet();
|
423
|
-
Init_icmp_packet();
|
424
433
|
}
|
@@ -0,0 +1,162 @@
|
|
1
|
+
/*
|
2
|
+
* ipv6_packet.c
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "ruby_pcap.h"
|
6
|
+
|
7
|
+
VALUE cIPv6Packet;
|
8
|
+
|
9
|
+
#define CheckTruncateIpv6(pkt, need) CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IPv6")
|
10
|
+
#define IPV6_HL 40
|
11
|
+
|
12
|
+
VALUE
|
13
|
+
setup_ipv6_packet(pkt, nl_len)
|
14
|
+
struct packet_object *pkt;
|
15
|
+
int nl_len;
|
16
|
+
{
|
17
|
+
VALUE class;
|
18
|
+
|
19
|
+
class = cIPv6Packet;
|
20
|
+
pkt->hdr.layer4_off = pkt->hdr.layer3_off + IPV6_HL;
|
21
|
+
switch (IPV6_HDR(pkt)->ip6_nxt) {
|
22
|
+
case IPPROTO_TCP:
|
23
|
+
DEBUG_PRINT("setup_tcpv6_packet");
|
24
|
+
class = setup_tcpv6_packet(pkt, nl_len - IPV6_HL);
|
25
|
+
break;
|
26
|
+
case IPPROTO_UDP:
|
27
|
+
DEBUG_PRINT("setup_udpv6_packet");
|
28
|
+
class = setup_udpv6_packet(pkt, nl_len - IPV6_HL);
|
29
|
+
break;
|
30
|
+
case IPPROTO_ICMPV6:
|
31
|
+
DEBUG_PRINT("setup_icmpv6_packet");
|
32
|
+
class = setup_icmpv6_packet(pkt);
|
33
|
+
break;
|
34
|
+
}
|
35
|
+
return class;
|
36
|
+
}
|
37
|
+
|
38
|
+
#define IPV6P_METHOD(func, val) \
|
39
|
+
static VALUE\
|
40
|
+
(func)(self)\
|
41
|
+
VALUE self;\
|
42
|
+
{\
|
43
|
+
struct ip6_hdr *ip;\
|
44
|
+
\
|
45
|
+
DEBUG_PRINT(#func);\
|
46
|
+
ip = IPV6_HDR_OBJ(self);\
|
47
|
+
return (val);\
|
48
|
+
}
|
49
|
+
|
50
|
+
IPV6P_METHOD(ipp_ver, INT2FIX(ip->ip6_vfc >> 4))
|
51
|
+
/*
|
52
|
+
The bits of this field hold two values.
|
53
|
+
The six most-significant bits hold the Differentiated Services (DS) field, which is used to classify packets.
|
54
|
+
Currently, all standard DS fields end with a '0' bit. Any DS field that ends with two '1' bits is intended for local or experimental use.[4]
|
55
|
+
The remaining two bits are used for Explicit Congestion Notification (ECN);
|
56
|
+
priority values subdivide into ranges: traffic where the source provides congestion control and non-congestion control traffic.
|
57
|
+
*/
|
58
|
+
IPV6P_METHOD(ipp_tc, INT2FIX((ntohl(ip->ip6_flow) & 0x0FF00000) >> 20))
|
59
|
+
IPV6P_METHOD(ipp_ds, INT2FIX((ntohl(ip->ip6_flow) & 0x0FF00000) >> 22))
|
60
|
+
IPV6P_METHOD(ipp_ecn, INT2FIX((ntohl(ip->ip6_flow) & 0x00300000) >> 20))
|
61
|
+
IPV6P_METHOD(ipp_fl, INT2FIX(ntohl(ip->ip6_flow) & 0x000FFFFF))
|
62
|
+
IPV6P_METHOD(ipp_pl, INT2FIX(ntohs(ip->ip6_plen)))
|
63
|
+
IPV6P_METHOD(ipp_nh, INT2FIX(ip->ip6_nxt))
|
64
|
+
IPV6P_METHOD(ipp_hl, INT2FIX(ip->ip6_hlim))
|
65
|
+
|
66
|
+
|
67
|
+
static VALUE
|
68
|
+
ipp_truncated(self)
|
69
|
+
VALUE self;
|
70
|
+
{
|
71
|
+
struct packet_object *pkt;
|
72
|
+
struct ip6_hdr *ip;
|
73
|
+
GetPacket(self, pkt);
|
74
|
+
ip = IPV6_HDR(pkt);
|
75
|
+
if IsTruncated(pkt, pkt->hdr.layer3_off, ntohs(ip->ip6_plen))
|
76
|
+
return Qtrue;
|
77
|
+
return Qfalse;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE
|
81
|
+
ipp_data(self)
|
82
|
+
VALUE self;
|
83
|
+
{
|
84
|
+
struct packet_object *pkt;
|
85
|
+
struct ip6_hdr *ip;
|
86
|
+
int len;
|
87
|
+
|
88
|
+
GetPacket(self, pkt);
|
89
|
+
ip = IPV6_HDR(pkt);
|
90
|
+
CheckTruncateIpv6(pkt, 20);
|
91
|
+
len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - IPV6_HL;
|
92
|
+
return rb_str_new((u_char *)ip + IPV6_HL, len);
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* IPv6Address
|
97
|
+
*/
|
98
|
+
|
99
|
+
static VALUE
|
100
|
+
ipp_src_i(self)
|
101
|
+
VALUE self;
|
102
|
+
{
|
103
|
+
struct ip6_hdr *ip;
|
104
|
+
ip = (struct ip6_hdr *)IPV6_HDR_OBJ(self);
|
105
|
+
return rb_integer_unpack(ip->ip6_src.s6_addr, 16, 1, 0, INTEGER_PACK_BIG_ENDIAN);
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE
|
109
|
+
ipp_src_s(self)
|
110
|
+
VALUE self;
|
111
|
+
{
|
112
|
+
struct ip6_hdr *ip;
|
113
|
+
char buff[INET6_ADDRSTRLEN];
|
114
|
+
ip = (struct ip6_hdr *)IPV6_HDR_OBJ(self);
|
115
|
+
|
116
|
+
inet_ntop(AF_INET6, ip->ip6_src.s6_addr, buff, INET6_ADDRSTRLEN);
|
117
|
+
return rb_str_new2(buff);
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE
|
121
|
+
ipp_dst_i(self)
|
122
|
+
VALUE self;
|
123
|
+
{
|
124
|
+
struct ip6_hdr *ip;
|
125
|
+
ip = IPV6_HDR_OBJ(self);
|
126
|
+
return rb_integer_unpack(ip->ip6_dst.s6_addr, 16, 1, 0, INTEGER_PACK_BIG_ENDIAN);
|
127
|
+
}
|
128
|
+
|
129
|
+
static VALUE
|
130
|
+
ipp_dst_s(self)
|
131
|
+
VALUE self;
|
132
|
+
{
|
133
|
+
char buff[INET6_ADDRSTRLEN];
|
134
|
+
struct ip6_hdr *ip;
|
135
|
+
ip = IPV6_HDR_OBJ(self);
|
136
|
+
|
137
|
+
inet_ntop(AF_INET6, ip->ip6_dst.s6_addr, buff, INET6_ADDRSTRLEN);
|
138
|
+
return rb_str_new2(buff);
|
139
|
+
}
|
140
|
+
|
141
|
+
void
|
142
|
+
Init_ipv6_packet(void)
|
143
|
+
{
|
144
|
+
DEBUG_PRINT("Init_ipv6_packet");
|
145
|
+
|
146
|
+
cIPv6Packet = rb_define_class_under(mPcap, "IPv6Packet", cPacket);
|
147
|
+
|
148
|
+
rb_define_method(cIPv6Packet, "ip_ver", ipp_ver, 0);
|
149
|
+
rb_define_method(cIPv6Packet, "ip_tc", ipp_tc, 0);
|
150
|
+
rb_define_method(cIPv6Packet, "ip_ds", ipp_ds, 0);
|
151
|
+
rb_define_method(cIPv6Packet, "ip_ecn", ipp_ecn, 0);
|
152
|
+
rb_define_method(cIPv6Packet, "ip_fl", ipp_fl, 0); /* IPv6 flow label */
|
153
|
+
rb_define_method(cIPv6Packet, "ip_pl", ipp_pl, 0); /* IPv6 Payload length */
|
154
|
+
rb_define_method(cIPv6Packet, "ip_nh", ipp_nh, 0); /* IPv6 Next header */
|
155
|
+
rb_define_method(cIPv6Packet, "ip_hl", ipp_hl, 0); /* IPv6 Hop limit */
|
156
|
+
rb_define_method(cIPv6Packet, "src_s", ipp_src_s, 0);
|
157
|
+
rb_define_method(cIPv6Packet, "dst_s", ipp_dst_s, 0);
|
158
|
+
rb_define_method(cIPv6Packet, "src_i", ipp_src_i, 0);
|
159
|
+
rb_define_method(cIPv6Packet, "dst_i", ipp_dst_i, 0);
|
160
|
+
rb_define_method(cIPv6Packet, "ip_data", ipp_data, 0);
|
161
|
+
rb_define_method(cIPv6Packet, "ip_truncated?", ipp_truncated, 0);
|
162
|
+
}
|