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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 913aacfd45979834125fde75053c925015ee8b45
4
- data.tar.gz: 97499258d1aa138e73950474e439f9ec538a8aa2
2
+ SHA256:
3
+ metadata.gz: 0c416ece1a8344e1f07c5170957aab941a4670eb422727dce36fc5c346db048f
4
+ data.tar.gz: 4b8f52b6059947608699b8fa125351990504ac027b8fdbf47780e76809885a99
5
5
  SHA512:
6
- metadata.gz: ee7bca3fd1b84ccf63ba4e008a770f80e561b7eab224de77f3c6406963e302a4a737f06aebbda7d048b4269117d79babd30991a31fb31ae406bbd7296f6b4e2f
7
- data.tar.gz: f4c6a018d754462db3f34ab5006ad5cb0a910a7bda315248f0352f0acf727eb34de29f49e32035085ba44b557e7489d473312208deb49fc5971e3b0b4f59e2d2
6
+ metadata.gz: c82fc770ddec96e61b75b099991a33a59d9fca0a575958d5101aff095acd4e81242c09d8a22a773a2b2348a9c7dcae23fed9d9f458179d57e6ffc626c7f4d6bf
7
+ data.tar.gz: cc556bf0383bf6babec625a01db347ea421894d67f45d0f69c33b3e9d847cda66abf60b1ede6c1ee8ce6186846e1cec4f2324ed74bb0e54603c785576079af40
@@ -0,0 +1,26 @@
1
+ name: build
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+ branches:
8
+ - master
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ['3.1', '3.0', '2.7','2.4','2.1']
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up ruby ${{ matrix.ruby_version}}
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ - name: Install system libs dependencies
22
+ run: sudo apt-get update -qq && sudo apt-get install -y libpcap-dev
23
+ - name: Get deps
24
+ run: bundle install
25
+ - name: Build it
26
+ run: bundle exec rake
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
+
1
2
  ## ruby-pcap
2
3
 
3
- [![Build Status](https://travis-ci.org/ickymettle/ruby-pcap.svg)](https://travis-ci.org/ickymettle/ruby-pcap)
4
+ [![build workflow](https://github.com/vitoshalabs/ruby-pcap/actions/workflows/build.yml/badge.svg)](https://github.com/vitoshalabs/ruby-pcap/actions/workflows/build.yml)
4
5
 
5
6
  ruby-pcap is a ruby extension to LBL libpcap (Packet Capture library).
6
7
  This library also includes classes to access TCP/IP header.
@@ -13,8 +14,7 @@ gem install ruby-pcap
13
14
 
14
15
  ### Requirements
15
16
 
16
- * ruby-1.9.3 or higher
17
- * May work with older ruby version but not being tested
17
+ * ruby-2.1 or higher
18
18
  * libpcap (http://www.tcpdump.org/)
19
19
 
20
20
  ## Usage
@@ -26,10 +26,6 @@ Directory 'examples' contains some simple scripts.
26
26
 
27
27
  Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
28
28
 
29
- ## Maintained by
30
-
31
- Marcus Barczak <mbarczak@etsy.com>
32
-
33
29
  ## Copyright
34
30
 
35
31
  ruby-pcap is copyrighted free software by Masaki Fukushima.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'pcap'
5
+ require 'pcap/pcaplet'
6
+
7
+ iface = ARGV[0] || 'en0'
8
+ duration = (ARGV[1] || 10).to_i
9
+ count = 0
10
+ capture = Pcap::Capture.open_live(iface, 65_535, true)
11
+ Thread.new do
12
+ sleep duration
13
+ if capture.closed?
14
+ puts 'device is already closed!'
15
+ else
16
+ puts 'signaling OS to stop capture!'
17
+ capture.breakloop
18
+ end
19
+ end
20
+ puts "starting capture on #{iface} for #{duration} seconds"
21
+ start_time = Time.now
22
+ capture.loop do |pkt|
23
+ puts "Got #{pkt}"
24
+ count += 1
25
+ end
26
+ capture.close
27
+ end_time = Time.now
28
+ puts "packets count #{count} completed in #{end_time - start_time} seconds"
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>
@@ -309,6 +308,19 @@ capture_close(self)
309
308
  return Qnil;
310
309
  }
311
310
 
311
+ static VALUE
312
+ is_capture_closed(self)
313
+ VALUE self;
314
+ {
315
+ struct capture_object *cap;
316
+ DEBUG_PRINT("is_capture_closed");
317
+ Data_Get_Struct(self, struct capture_object, cap);
318
+ if (cap->pcap == NULL) {
319
+ return Qtrue;
320
+ }
321
+ return Qfalse;
322
+ }
323
+
312
324
  static void
313
325
  handler(cap, pkthdr, data)
314
326
  struct capture_object *cap;
@@ -318,36 +330,112 @@ handler(cap, pkthdr, data)
318
330
  rb_yield(new_packet(data, pkthdr, cap->dl_type));
319
331
  }
320
332
 
333
+ #define DST_ADDR(data) INT2FIX(ntohl(*((unsigned int *) (data + 30))))
334
+ #define SRC_ADDR(data) INT2FIX(ntohl(*((unsigned int *) (data + 26))))
335
+
336
+ static void
337
+ dst_ipv4_addr_handler(cap, pkthdr, data)
338
+ struct capture_object *cap;
339
+ const struct pcap_pkthdr *pkthdr;
340
+ const u_char *data;
341
+ {
342
+ rb_yield(DST_ADDR(data));
343
+ }
344
+
345
+ static void
346
+ src_ipv4_addr_handler(cap, pkthdr, data)
347
+ struct capture_object *cap;
348
+ const struct pcap_pkthdr *pkthdr;
349
+ const u_char *data;
350
+ {
351
+ rb_yield(SRC_ADDR(data));
352
+ }
353
+
354
+ #define SRCV6_ADDR(data) rb_integer_unpack((u_char *) (data + 22), 16, 1, 0, INTEGER_PACK_BIG_ENDIAN)
355
+ #define DSTV6_ADDR(data) rb_integer_unpack((u_char *) (data + 38), 16, 1, 0, INTEGER_PACK_BIG_ENDIAN)
356
+
357
+ static void
358
+ dst_ipv6_addr_handler(cap, pkthdr, data)
359
+ struct capture_object *cap;
360
+ const struct pcap_pkthdr *pkthdr;
361
+ const u_char *data;
362
+ {
363
+ rb_yield(DSTV6_ADDR(data));
364
+ }
365
+
366
+ static void
367
+ src_ipv6_addr_handler(cap, pkthdr, data)
368
+ struct capture_object *cap;
369
+ const struct pcap_pkthdr *pkthdr;
370
+ const u_char *data;
371
+ {
372
+ rb_yield(SRCV6_ADDR(data));
373
+ }
374
+
375
+ void parse_opts(VALUE v_opts, void **default_handler)
376
+ {
377
+ if (NIL_P(v_opts)) {
378
+ DEBUG_PRINT("using default capture handler");
379
+ *default_handler = &handler;
380
+ } else {
381
+ // raise error if second argument is not a symbol
382
+ Check_Type(v_opts, T_SYMBOL);
383
+ // only :source, :destination are supported
384
+ if (SYM2ID(v_opts) == rb_intern("source")) {
385
+ DEBUG_PRINT("yeilding only source ipv4 addresses");
386
+ *default_handler = &src_ipv4_addr_handler;
387
+ } else if (SYM2ID(v_opts) == rb_intern("destination")) {
388
+ DEBUG_PRINT("yeilding only destination ipv4 addresses");
389
+ *default_handler = &dst_ipv4_addr_handler;
390
+ } else if (SYM2ID(v_opts) == rb_intern("destinationv6")) {
391
+ DEBUG_PRINT("yeilding only destination ipv6 addresses");
392
+ *default_handler = &dst_ipv6_addr_handler;
393
+ } else if (SYM2ID(v_opts) == rb_intern("sourcev6")) {
394
+ DEBUG_PRINT("yeilding only source ipv6 addresses");
395
+ *default_handler = &src_ipv6_addr_handler;
396
+ } else {
397
+ // unkonw keyword passed, use default capture handler
398
+ DEBUG_PRINT("unknown option, using default capture handler");
399
+ *default_handler = &handler;
400
+ }
401
+ }
402
+ }
403
+
321
404
  static VALUE
322
405
  capture_dispatch(argc, argv, self)
323
406
  int argc;
324
407
  VALUE *argv;
325
408
  VALUE self;
326
409
  {
327
- VALUE v_cnt;
328
- int cnt;
410
+ VALUE v_cnt, v_opts;
411
+ int ret = 0, cnt = 0;
412
+ unsigned int cap_cnt = 0;
329
413
  struct capture_object *cap;
330
- int ret;
414
+ void *default_handler;
331
415
 
332
416
  DEBUG_PRINT("capture_dispatch");
333
417
  GetCapture(self, cap);
334
418
 
335
419
  /* scan arg */
336
- if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
337
- FIXNUM_P(v_cnt);
338
- cnt = FIX2INT(v_cnt);
420
+ rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
421
+ if (NIL_P(v_cnt)) {
422
+ cnt = -1;
339
423
  } else {
340
- cnt = -1;
424
+ FIXNUM_P(v_cnt);
425
+ cnt = FIX2INT(v_cnt);
341
426
  }
342
-
343
- MAYBE_TRAP_BEG;
344
- ret = pcap_dispatch(cap->pcap, cnt, handler, (u_char *)cap);
345
- MAYBE_TRAP_END;
346
- if (ret == -1) {
427
+ parse_opts(v_opts, &default_handler);
428
+ // call dispatch with 10,000 and break if we have reached desired amount
429
+ // if dispatch is called with -1/0 sometimes it dispatches millions of packets
430
+ for (cap_cnt = 0; cap_cnt < cnt; cap_cnt += ret ) {
431
+ MAYBE_TRAP_BEG;
432
+ ret = pcap_dispatch(cap->pcap, 10000, default_handler, (u_char *)cap);
433
+ MAYBE_TRAP_END;
434
+ if (ret < 0) {
347
435
  rb_raise(ePcapError, "dispatch: %s", pcap_geterr(cap->pcap));
436
+ }
348
437
  }
349
-
350
- return INT2FIX(ret);
438
+ return UINT2NUM(cap_cnt);
351
439
  }
352
440
 
353
441
  static VALUE
@@ -367,31 +455,45 @@ capture_fh(argc, argv, self)
367
455
  return rb_funcall(rb_path2class("IO"), rb_intern("new"), 1, INT2FIX(pcap_fileno(cap->pcap)));
368
456
  }
369
457
 
458
+ static VALUE
459
+ capture_breakloop(self)
460
+ VALUE self;
461
+ {
462
+ struct capture_object *cap;
463
+
464
+ DEBUG_PRINT("capture_breakloop");
465
+ GetCapture(self, cap);
466
+ pcap_breakloop(cap->pcap);
467
+ return Qnil;
468
+ }
469
+
370
470
  static VALUE
371
471
  capture_loop(argc, argv, self)
372
472
  int argc;
373
473
  VALUE *argv;
374
474
  VALUE self;
375
475
  {
376
- VALUE v_cnt;
476
+ VALUE v_cnt, v_opts;
377
477
  int cnt;
378
478
  struct capture_object *cap;
379
479
  int ret;
480
+ void *default_handler;
380
481
 
381
482
  DEBUG_PRINT("capture_loop");
382
483
  GetCapture(self, cap);
383
484
 
384
485
  /* scan arg */
385
- if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
386
- FIXNUM_P(v_cnt);
387
- cnt = FIX2INT(v_cnt);
486
+ rb_scan_args(argc, argv, "02", &v_cnt, &v_opts);
487
+ if (NIL_P(v_cnt)) {
488
+ cnt = -1;
388
489
  } else {
389
- cnt = -1;
490
+ FIXNUM_P(v_cnt);
491
+ cnt = FIX2INT(v_cnt);
390
492
  }
391
-
493
+ parse_opts(v_opts, &default_handler);
392
494
  if (pcap_file(cap->pcap) != NULL) {
393
495
  MAYBE_TRAP_BEG;
394
- ret = pcap_loop(cap->pcap, cnt, handler, (u_char *)cap);
496
+ ret = pcap_loop(cap->pcap, cnt, default_handler, (u_char *)cap);
395
497
  MAYBE_TRAP_END;
396
498
  }
397
499
  else {
@@ -409,7 +511,7 @@ capture_loop(argc, argv, self)
409
511
  rb_thread_wait_fd(fd);
410
512
  }
411
513
  MAYBE_TRAP_BEG;
412
- ret = pcap_dispatch(cap->pcap, 1, handler, (u_char *)cap);
514
+ ret = pcap_dispatch(cap->pcap, 1, default_handler, (u_char *)cap);
413
515
  MAYBE_TRAP_END;
414
516
  } while (ret == 0);
415
517
 
@@ -540,6 +642,30 @@ capture_inject(self, v_buf)
540
642
  return Qnil;
541
643
  }
542
644
 
645
+ // configure capture direction: IN/OUT packets
646
+ static VALUE
647
+ capture_direction(self, direction)
648
+ VALUE direction;
649
+ VALUE self;
650
+ {
651
+ struct capture_object *cap;
652
+ // default value is in and out packets
653
+ int v_direction = PCAP_D_INOUT;
654
+
655
+ DEBUG_PRINT("capture_direction");
656
+ GetCapture(self, cap);
657
+ Check_Type(direction, T_SYMBOL);
658
+ // set desired direction: :in,:out or both
659
+ if (SYM2ID(direction) == rb_intern("in")) {
660
+ DEBUG_PRINT("setting capture direction IN");
661
+ v_direction = PCAP_D_IN;
662
+ } else if (SYM2ID(direction) == rb_intern("out")) {
663
+ DEBUG_PRINT("setting capture direction OUT");
664
+ v_direction = PCAP_D_OUT;
665
+ }
666
+ return INT2NUM(pcap_setdirection(cap->pcap, v_direction));
667
+ }
668
+
543
669
  /*
544
670
  * Dumper object
545
671
  */
@@ -905,6 +1031,9 @@ Init_pcap(void)
905
1031
  rb_define_method(cCapture, "snaplen", capture_snapshot, 0);
906
1032
  rb_define_method(cCapture, "stats", capture_stats, 0);
907
1033
  rb_define_method(cCapture, "inject", capture_inject, 1);
1034
+ rb_define_method(cCapture, "direction", capture_direction, 1);
1035
+ rb_define_method(cCapture, "breakloop", capture_breakloop, 0);
1036
+ rb_define_method(cCapture, "closed?", is_capture_closed, 0);
908
1037
 
909
1038
  /* define class Dumper */
910
1039
  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
  }