ruby-pcap 0.7.9 → 0.8.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 913aacfd45979834125fde75053c925015ee8b45
4
- data.tar.gz: 97499258d1aa138e73950474e439f9ec538a8aa2
2
+ SHA256:
3
+ metadata.gz: 78bf37291d08a1c9dbe2ab08269e494dbb8f3c5d6a37932e3468ca30c4899648
4
+ data.tar.gz: 42cb108300efda78d65a7f742f691863a226cd4365339ef0a68a97ebfae0987e
5
5
  SHA512:
6
- metadata.gz: ee7bca3fd1b84ccf63ba4e008a770f80e561b7eab224de77f3c6406963e302a4a737f06aebbda7d048b4269117d79babd30991a31fb31ae406bbd7296f6b4e2f
7
- data.tar.gz: f4c6a018d754462db3f34ab5006ad5cb0a910a7bda315248f0352f0acf727eb34de29f49e32035085ba44b557e7489d473312208deb49fc5971e3b0b4f59e2d2
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
- int ret;
401
+ void *default_handler;
331
402
 
332
403
  DEBUG_PRINT("capture_dispatch");
333
404
  GetCapture(self, cap);
334
405
 
335
406
  /* scan arg */
336
- if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
337
- FIXNUM_P(v_cnt);
338
- cnt = FIX2INT(v_cnt);
407
+ rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
408
+ if (NIL_P(v_cnt)) {
409
+ cnt = -1;
339
410
  } else {
340
- cnt = -1;
411
+ FIXNUM_P(v_cnt);
412
+ cnt = FIX2INT(v_cnt);
341
413
  }
342
-
343
- MAYBE_TRAP_BEG;
344
- ret = pcap_dispatch(cap->pcap, cnt, handler, (u_char *)cap);
345
- MAYBE_TRAP_END;
346
- if (ret == -1) {
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
- if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
386
- FIXNUM_P(v_cnt);
387
- cnt = FIX2INT(v_cnt);
461
+ rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
462
+ if (NIL_P(v_cnt)) {
463
+ cnt = -1;
388
464
  } else {
389
- cnt = -1;
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, handler, (u_char *)cap);
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, handler, (u_char *)cap);
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
+ }
@@ -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
+ }