ruby-pcap 0.7.9 → 0.8.1

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