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