ffi-pcap 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/.gitignore +2 -1
  2. data/.pkg_ignore +25 -0
  3. data/.rspec +1 -0
  4. data/.specopts +1 -0
  5. data/.yardopts +1 -0
  6. data/{ChangeLog.rdoc → ChangeLog.md} +15 -5
  7. data/LICENSE.txt +1 -4
  8. data/README.md +92 -0
  9. data/Rakefile +30 -20
  10. data/examples/em_selectable_pcap.rb +38 -0
  11. data/examples/em_timer.rb +26 -0
  12. data/examples/ipfw_divert.rb +28 -8
  13. data/examples/print_bytes.rb +5 -1
  14. data/examples/replay.rb +11 -0
  15. data/examples/selectable_pcap.rb +29 -0
  16. data/ffi-pcap.gemspec +60 -0
  17. data/gemspec.yml +23 -0
  18. data/lib/ffi/pcap.rb +7 -13
  19. data/lib/ffi/pcap/addr.rb +16 -15
  20. data/lib/ffi/pcap/bpf_instruction.rb +25 -0
  21. data/lib/ffi/pcap/bpf_program.rb +85 -0
  22. data/lib/ffi/pcap/bsd.rb +9 -98
  23. data/lib/ffi/pcap/bsd/af.rb +18 -0
  24. data/lib/ffi/pcap/bsd/in6_addr.rb +16 -0
  25. data/lib/ffi/pcap/bsd/in_addr.rb +18 -0
  26. data/lib/ffi/pcap/bsd/sock_addr.rb +19 -0
  27. data/lib/ffi/pcap/bsd/sock_addr_dl.rb +24 -0
  28. data/lib/ffi/pcap/bsd/sock_addr_family.rb +19 -0
  29. data/lib/ffi/pcap/bsd/sock_addr_in.rb +21 -0
  30. data/lib/ffi/pcap/bsd/sock_addr_in6.rb +20 -0
  31. data/lib/ffi/pcap/bsd/typedefs.rb +7 -0
  32. data/lib/ffi/pcap/capture_wrapper.rb +296 -256
  33. data/lib/ffi/pcap/common_wrapper.rb +152 -127
  34. data/lib/ffi/pcap/copy_handler.rb +32 -32
  35. data/lib/ffi/pcap/crt.rb +7 -10
  36. data/lib/ffi/pcap/data_link.rb +178 -153
  37. data/lib/ffi/pcap/dead.rb +42 -29
  38. data/lib/ffi/pcap/dumper.rb +39 -41
  39. data/lib/ffi/pcap/error_buffer.rb +21 -36
  40. data/lib/ffi/pcap/exceptions.rb +21 -15
  41. data/lib/ffi/pcap/file_header.rb +24 -18
  42. data/lib/ffi/pcap/in_addr.rb +4 -4
  43. data/lib/ffi/pcap/interface.rb +22 -20
  44. data/lib/ffi/pcap/live.rb +296 -252
  45. data/lib/ffi/pcap/offline.rb +50 -43
  46. data/lib/ffi/pcap/packet.rb +186 -143
  47. data/lib/ffi/pcap/packet_header.rb +20 -18
  48. data/lib/ffi/pcap/pcap.rb +269 -212
  49. data/lib/ffi/pcap/stat.rb +19 -49
  50. data/lib/ffi/pcap/stat_ex.rb +42 -0
  51. data/lib/ffi/pcap/time_val.rb +52 -38
  52. data/lib/ffi/pcap/typedefs.rb +16 -20
  53. data/spec/data_link_spec.rb +39 -35
  54. data/spec/dead_spec.rb +0 -4
  55. data/spec/error_buffer_spec.rb +7 -9
  56. data/spec/file_header_spec.rb +17 -14
  57. data/spec/live_spec.rb +12 -5
  58. data/spec/offline_spec.rb +10 -11
  59. data/spec/packet_behaviors.rb +20 -6
  60. data/spec/packet_injection_spec.rb +9 -8
  61. data/spec/packet_spec.rb +22 -26
  62. data/spec/pcap_spec.rb +52 -40
  63. data/spec/spec_helper.rb +16 -5
  64. data/spec/wrapper_behaviors.rb +0 -3
  65. data/tasks/doc.rake +69 -0
  66. data/tasks/gem.rake +200 -0
  67. data/tasks/git.rake +40 -0
  68. data/tasks/post_load.rake +34 -0
  69. data/tasks/rubyforge.rake +55 -0
  70. data/tasks/setup.rb +286 -0
  71. data/tasks/spec.rake +54 -0
  72. data/tasks/svn.rake +47 -0
  73. data/tasks/test.rake +40 -0
  74. metadata +142 -92
  75. data/README.rdoc +0 -30
  76. data/VERSION +0 -1
  77. data/lib/ffi/pcap/bpf.rb +0 -106
  78. data/lib/ffi/pcap/version.rb +0 -6
  79. data/tasks/rcov.rb +0 -6
  80. data/tasks/rdoc.rb +0 -17
  81. data/tasks/spec.rb +0 -9
  82. data/tasks/yard.rb +0 -21
@@ -1,57 +1,27 @@
1
- module FFI
2
- module PCap
3
- # As returned by pcap_stats()
4
- #
5
- # See pcap_stat struct in pcap.h.
6
- class Stat < FFI::Struct
7
- include FFI::DRY::StructHelper
8
-
9
- dsl_layout do
10
- field :ps_recv, :uint, :desc => "number of packets received"
11
- field :ps_drop, :uint, :desc => "numer of packets dropped"
12
- field :ps_ifdrop, :uint, :desc => "drops by interface (not yet supported)"
13
- # bs_capt field intentionally left off (WIN32 only)
14
- end
15
-
16
- alias received ps_recv
17
- alias dropped ps_drop
18
- alias interface_dropped ps_ifdrop
1
+ require 'ffi/pcap/stat_ex'
19
2
 
20
- end
3
+ module FFI
4
+ module PCap
5
+ #
6
+ # As returned by `pcap_stats`.
7
+ #
8
+ # See `pcap_stat` struct in `pcap.h`.
9
+ #
10
+ class Stat < FFI::Struct
21
11
 
22
- # As returned by pcap_stats_ex() (MSDOS only)
23
- #
24
- # See pcap_stat_ex struct in pcap.h
25
- class StatEx < FFI::Struct
26
- include FFI::DRY::StructHelper
12
+ include FFI::DRY::StructHelper
27
13
 
28
- dsl_layout do
29
- field :rx_packets, :ulong, :desc => "total packets received"
30
- field :tx_packets, :ulong, :desc => "total packets transmitted"
31
- field :rx_bytes, :ulong, :desc => "total bytes received"
32
- field :tx_bytes, :ulong, :desc => "total bytes transmitted"
33
- field :rx_errors, :ulong, :desc => "bad packets received"
34
- field :tx_errors, :ulong, :desc => "packet transmit problems"
35
- field :rx_dropped, :ulong, :desc => "no space in Rx buffers"
36
- field :tx_dropped, :ulong, :desc => "no space available for Tx"
37
- field :multicast, :ulong, :desc => "multicast packets received"
38
- field :collisions, :ulong
14
+ dsl_layout do
15
+ field :ps_recv, :uint, :desc => "number of packets received"
16
+ field :ps_drop, :uint, :desc => "numer of packets dropped"
17
+ field :ps_ifdrop, :uint, :desc => "drops by interface (not yet supported)"
18
+ # bs_capt field intentionally left off (WIN32 only)
19
+ end
39
20
 
40
- # detailed rx errors
41
- field :rx_length_errors, :ulong
42
- field :rx_over_errors, :ulong, :desc => "ring buff overflow"
43
- field :rx_crc_errors, :ulong, :desc => "pkt with crc error"
44
- field :rx_frame_errors, :ulong, :desc => "frame alignment errors"
45
- field :rx_fifo_errors, :ulong, :desc => "fifo overrun"
46
- field :rx_missed_errors, :ulong, :desc => "missed packet"
21
+ alias received ps_recv
22
+ alias dropped ps_drop
23
+ alias interface_dropped ps_ifdrop
47
24
 
48
- # detailed tx_errors
49
- field :tx_aborted_errors, :ulong
50
- field :tx_carrier_errors, :ulong
51
- field :tx_fifo_errors, :ulong
52
- field :tx_heartbeat_errors, :ulong
53
- field :tx_window_errors, :ulong
54
25
  end
55
26
  end
56
27
  end
57
- end
@@ -0,0 +1,42 @@
1
+ module FFI
2
+ module PCap
3
+ #
4
+ # As returned by `pcap_stats_ex()` (MSDOS only).
5
+ #
6
+ # See `pcap_stat_ex` struct in `pcap.h`.
7
+ #
8
+ class StatEx < FFI::Struct
9
+
10
+ include FFI::DRY::StructHelper
11
+
12
+ dsl_layout do
13
+ field :rx_packets, :ulong, :desc => "total packets received"
14
+ field :tx_packets, :ulong, :desc => "total packets transmitted"
15
+ field :rx_bytes, :ulong, :desc => "total bytes received"
16
+ field :tx_bytes, :ulong, :desc => "total bytes transmitted"
17
+ field :rx_errors, :ulong, :desc => "bad packets received"
18
+ field :tx_errors, :ulong, :desc => "packet transmit problems"
19
+ field :rx_dropped, :ulong, :desc => "no space in Rx buffers"
20
+ field :tx_dropped, :ulong, :desc => "no space available for Tx"
21
+ field :multicast, :ulong, :desc => "multicast packets received"
22
+ field :collisions, :ulong
23
+
24
+ # detailed rx errors
25
+ field :rx_length_errors, :ulong
26
+ field :rx_over_errors, :ulong, :desc => "ring buff overflow"
27
+ field :rx_crc_errors, :ulong, :desc => "pkt with crc error"
28
+ field :rx_frame_errors, :ulong, :desc => "frame alignment errors"
29
+ field :rx_fifo_errors, :ulong, :desc => "fifo overrun"
30
+ field :rx_missed_errors, :ulong, :desc => "missed packet"
31
+
32
+ # detailed tx_errors
33
+ field :tx_aborted_errors, :ulong
34
+ field :tx_carrier_errors, :ulong
35
+ field :tx_fifo_errors, :ulong
36
+ field :tx_heartbeat_errors, :ulong
37
+ field :tx_window_errors, :ulong
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -1,48 +1,62 @@
1
1
  module FFI
2
- module PCap
3
- class TimeVal < FFI::Struct
4
- include FFI::DRY::StructHelper
2
+ module PCap
3
+ class TimeVal < FFI::Struct
5
4
 
6
- dsl_layout do
7
- field :tv_sec, :time_t
8
- field :tv_usec, :suseconds_t
9
- end
5
+ include FFI::DRY::StructHelper
10
6
 
11
- def initialize(*args)
12
- if args.size == 1 and (t=args[0]).kind_of?(Time)
13
- self.time = t
14
- else
15
- super(*args)
7
+ dsl_layout do
8
+ field :tv_sec, :time_t
9
+ field :tv_usec, :suseconds_t
16
10
  end
17
- end
18
11
 
19
- alias sec tv_sec
20
- alias usec tv_usec
12
+ #
13
+ # Initializes the new {TimeVal}.
14
+ #
15
+ # @param [Time, FFI::Pointer] timeval
16
+ # A Time object or a pointer to another {TimeVal}.
17
+ #
18
+ def initialize(timeval=nil)
19
+ case timeval
20
+ when Time
21
+ super()
21
22
 
22
- # Returns the time value as a ruby Time object.
23
- #
24
- # @return [Time]
25
- # A ruby time object derived from this TimeVal.
26
- def time
27
- Time.at(self.tv_sec, self.tv_usec)
28
- end
23
+ self.time = timeval
24
+ when Pointer then super(timeval)
25
+ else super()
26
+ end
27
+ end
29
28
 
30
- alias to_time time
31
-
32
- # Sets the time value from a ruby Time object
33
- #
34
- # @param [Time] t
35
- # A ruby time object from which to set the time.
36
- #
37
- # @return [Time]
38
- # Returns the same Time object supplied per convention.
39
- #
40
- def time=(t)
41
- self.tv_sec = t.tv_sec
42
- self.tv_usec = t.tv_usec
43
- return t
44
- end
29
+ alias sec tv_sec
30
+ alias usec tv_usec
31
+
32
+ #
33
+ # Returns the time value as a ruby Time object.
34
+ #
35
+ # @return [Time]
36
+ # A ruby time object derived from this TimeVal.
37
+ #
38
+ def time
39
+ Time.at(self.tv_sec, self.tv_usec)
40
+ end
45
41
 
42
+ alias to_time time
43
+
44
+ #
45
+ # Sets the time value from a ruby Time object
46
+ #
47
+ # @param [Time] new_time
48
+ # A ruby time object from which to set the time.
49
+ #
50
+ # @return [Time]
51
+ # Returns the same Time object supplied per convention.
52
+ #
53
+ def time=(new_time)
54
+ self.tv_sec = new_time.tv_sec
55
+ self.tv_usec = new_time.tv_usec
56
+
57
+ return new_time
58
+ end
59
+
60
+ end
46
61
  end
47
62
  end
48
- end
@@ -1,27 +1,23 @@
1
1
  module FFI
2
- module PCap
3
- typedef :pointer, :FILE
2
+ module PCap
3
+ extend FFI::Library
4
4
 
5
- typedef :int, :bpf_int32
6
- typedef :uint, :bpf_uint32
5
+ typedef :pointer, :FILE
7
6
 
8
- enum :pcap_direction_t, [
9
- :pcap_d_inout,
10
- :pcap_d_in,
11
- :pcap_d_out
12
- ]
7
+ typedef :int, :bpf_int32
8
+ typedef :uint, :bpf_uint32
13
9
 
14
- # For Win32-only pcap_setmode()
15
- enum :pcap_w32_modes_enum, [ :capt, :stat, :mon ]
10
+ enum :pcap_direction_t, [
11
+ :pcap_d_inout,
12
+ :pcap_d_in,
13
+ :pcap_d_out
14
+ ]
16
15
 
17
- typedef :pointer, :pcap_t
18
- typedef :pointer, :pcap_dumper_t
19
- typedef :pointer, :pcap_addr_t
16
+ # For Win32-only pcap_setmode()
17
+ enum :pcap_w32_modes_enum, [ :capt, :stat, :mon ]
20
18
 
21
- # add some of the more temperamental FFI types if needed
22
- [ [:long, :time_t],
23
- [:uint32, :suseconds_t],
24
- ].each {|t, d| begin; find_type(d); rescue TypeError; typedef t,d; end }
25
-
26
- end
19
+ typedef :pointer, :pcap_t
20
+ typedef :pointer, :pcap_dumper_t
21
+ typedef :pointer, :pcap_addr_t
22
+ end
27
23
  end
@@ -1,65 +1,69 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe DataLink do
4
- before(:all) do
5
- @datalink = DataLink.new(0)
6
- end
4
+ subject { described_class.new(0) }
7
5
 
8
6
  it "should map datalink names to datalink layer type values" do
9
- DataLink.name_to_val(:en10mb).should == 1
7
+ described_class.name_to_val(:en10mb).should == 1
10
8
  end
11
9
 
12
10
  it "should map datalink layer type values to datalink names" do
13
- DataLink.val_to_name(1).should == "EN10MB"
11
+ described_class.val_to_name(1).should == "EN10MB"
14
12
  end
15
13
 
16
14
  it "should be initialized from a pcap datalink value" do
17
- @datalink.name.should == 'NULL'
15
+ subject.name.should == 'NULL'
18
16
  end
19
17
 
20
- it "should support initialization from a pcap datalink name symbol" do
21
- @datalink = DataLink.new(:null)
22
- DataLink.should === @datalink
18
+ it "should have a description" do
19
+ subject.description.should_not be_empty
23
20
  end
24
21
 
25
- it "should support initialization from a pcap datalink name string" do
26
- dl = DataLink.new('en10mb')
27
- DataLink.should === dl
28
- end
22
+ describe "#initialize" do
23
+ it "should support initialization from a pcap datalink name Symbol" do
24
+ link = described_class.new(:null)
29
25
 
30
- it "should allow equality comparison against numeric values" do
31
- (@datalink == 0).should == true
32
- (@datalink == 1).should == false
33
- end
26
+ link.name.should == 'NULL'
27
+ end
34
28
 
35
- it "should allow equality comparison against String names" do
36
- (@datalink == "null").should == true
37
- (@datalink == "en10mb").should == false
29
+ it "should support initialization from a pcap datalink name String" do
30
+ link = described_class.new('en10mb')
31
+
32
+ link.name.should == 'EN10MB'
33
+ end
38
34
  end
39
35
 
40
- it "should allow equality comparison against Symbol names" do
41
- (@datalink == :null).should == true
42
- (@datalink == :en10mb).should == false
43
- end
36
+ describe "#==" do
37
+ it "should allow equality comparison against numeric values" do
38
+ (subject == 0).should == true
39
+ (subject == 1).should == false
40
+ end
44
41
 
45
- it "should allow comparison against another DataLink" do
46
- (@datalink == DataLink.new(0)).should == true
47
- (@datalink == DataLink.new(1)).should == false
48
- end
42
+ it "should allow equality comparison against String names" do
43
+ (subject == "null").should == true
44
+ (subject == "en10mb").should == false
45
+ end
49
46
 
50
- it "should still compare correctly against any other object" do
51
- (@datalink == Object.new).should == false
52
- end
47
+ it "should allow equality comparison against Symbol names" do
48
+ (subject == :null).should == true
49
+ (subject == :en10mb).should == false
50
+ end
53
51
 
54
- it "should have a description" do
55
- @datalink.description.should_not be_empty
52
+ it "should allow comparison against another described_class" do
53
+ (subject == described_class.new(0)).should == true
54
+ (subject == described_class.new(1)).should == false
55
+ end
56
+
57
+ it "should still compare correctly against any other object" do
58
+ (subject == Object.new).should == false
59
+ end
56
60
  end
57
61
 
58
62
  it "should convert to an Integer for the DLT value" do
59
- @datalink.to_i.should == 0
63
+ subject.to_i.should == 0
60
64
  end
61
65
 
62
66
  it "should convert to a String for the DLT name" do
63
- @datalink.to_s.should == 'NULL'
67
+ subject.to_s.should == 'NULL'
64
68
  end
65
69
  end
@@ -26,9 +26,5 @@ describe Dead do
26
26
 
27
27
  @pcap.close
28
28
  end
29
-
30
-
31
29
  end
32
-
33
30
  end
34
-
@@ -1,17 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ErrorBuffer do
4
- before(:all) do
5
- @errbuf = ErrorBuffer.create
6
- end
7
-
8
- it "should have a size of 256" do
9
- @errbuf.size.should == 256
4
+ it "should have a default size of 256" do
5
+ subject.size.should == 256
10
6
  end
11
7
 
12
8
  it "should return an error message with to_s" do
13
- @errbuf.to_s.should be_empty
14
- FFI::PCap.pcap_open_offline("/this/file/wont/exist/#{rand(0xFFFF)}", @errbuf )
15
- @errbuf.to_s.should_not be_empty
9
+ subject.to_s.should be_empty
10
+
11
+ PCap.pcap_open_offline("/this/file/wont/exist",subject)
12
+
13
+ subject.to_s.should_not be_empty
16
14
  end
17
15
  end
@@ -1,28 +1,31 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FileHeader do
4
- before(:all) do
5
- @file_header = FileHeader.new( :raw => File.read(PCAP_TESTFILE) )
4
+ let(:pcap_file) do
5
+ File.open(PCAP_TESTFILE,'rb') do |file|
6
+ file.read
7
+ end
6
8
  end
7
9
 
10
+ subject { described_class.new(:raw => pcap_file) }
11
+
8
12
  it "should parse a pcap file correctly" do
9
- @file_header.magic.should == 0xa1b2c3d4
10
- @file_header.version_major.should == 2
11
- @file_header.version_minor.should == 4
12
- @file_header.thiszone.should == 0
13
- @file_header.sigfigs.should == 0
14
- @file_header.snaplen.should == 96
15
- @file_header.linktype.should == 1
13
+ subject.magic.should == 0xa1b2c3d4
14
+ subject.version_major.should == 2
15
+ subject.version_minor.should == 4
16
+ subject.thiszone.should == 0
17
+ subject.sigfigs.should == 0
18
+ subject.snaplen.should == 96
19
+ subject.linktype.should == 1
16
20
  end
17
21
 
18
22
  it "should return a file format version string" do
19
- String.should === @file_header.version
20
- @file_header.version.should == "2.4"
23
+ subject.version.should == "2.4"
21
24
  end
22
25
 
23
26
  it "should return a DataLink for the linktype using datalink()" do
24
- DataLink.should === @file_header.datalink
25
- (@file_header.datalink == :en10mb).should == true
26
- end
27
+ subject.datalink.should be_kind_of(DataLink)
27
28
 
29
+ (subject.datalink == :en10mb).should == true
30
+ end
28
31
  end