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.
- data/.gitignore +2 -1
- data/.pkg_ignore +25 -0
- data/.rspec +1 -0
- data/.specopts +1 -0
- data/.yardopts +1 -0
- data/{ChangeLog.rdoc → ChangeLog.md} +15 -5
- data/LICENSE.txt +1 -4
- data/README.md +92 -0
- data/Rakefile +30 -20
- data/examples/em_selectable_pcap.rb +38 -0
- data/examples/em_timer.rb +26 -0
- data/examples/ipfw_divert.rb +28 -8
- data/examples/print_bytes.rb +5 -1
- data/examples/replay.rb +11 -0
- data/examples/selectable_pcap.rb +29 -0
- data/ffi-pcap.gemspec +60 -0
- data/gemspec.yml +23 -0
- data/lib/ffi/pcap.rb +7 -13
- data/lib/ffi/pcap/addr.rb +16 -15
- data/lib/ffi/pcap/bpf_instruction.rb +25 -0
- data/lib/ffi/pcap/bpf_program.rb +85 -0
- data/lib/ffi/pcap/bsd.rb +9 -98
- data/lib/ffi/pcap/bsd/af.rb +18 -0
- data/lib/ffi/pcap/bsd/in6_addr.rb +16 -0
- data/lib/ffi/pcap/bsd/in_addr.rb +18 -0
- data/lib/ffi/pcap/bsd/sock_addr.rb +19 -0
- data/lib/ffi/pcap/bsd/sock_addr_dl.rb +24 -0
- data/lib/ffi/pcap/bsd/sock_addr_family.rb +19 -0
- data/lib/ffi/pcap/bsd/sock_addr_in.rb +21 -0
- data/lib/ffi/pcap/bsd/sock_addr_in6.rb +20 -0
- data/lib/ffi/pcap/bsd/typedefs.rb +7 -0
- data/lib/ffi/pcap/capture_wrapper.rb +296 -256
- data/lib/ffi/pcap/common_wrapper.rb +152 -127
- data/lib/ffi/pcap/copy_handler.rb +32 -32
- data/lib/ffi/pcap/crt.rb +7 -10
- data/lib/ffi/pcap/data_link.rb +178 -153
- data/lib/ffi/pcap/dead.rb +42 -29
- data/lib/ffi/pcap/dumper.rb +39 -41
- data/lib/ffi/pcap/error_buffer.rb +21 -36
- data/lib/ffi/pcap/exceptions.rb +21 -15
- data/lib/ffi/pcap/file_header.rb +24 -18
- data/lib/ffi/pcap/in_addr.rb +4 -4
- data/lib/ffi/pcap/interface.rb +22 -20
- data/lib/ffi/pcap/live.rb +296 -252
- data/lib/ffi/pcap/offline.rb +50 -43
- data/lib/ffi/pcap/packet.rb +186 -143
- data/lib/ffi/pcap/packet_header.rb +20 -18
- data/lib/ffi/pcap/pcap.rb +269 -212
- data/lib/ffi/pcap/stat.rb +19 -49
- data/lib/ffi/pcap/stat_ex.rb +42 -0
- data/lib/ffi/pcap/time_val.rb +52 -38
- data/lib/ffi/pcap/typedefs.rb +16 -20
- data/spec/data_link_spec.rb +39 -35
- data/spec/dead_spec.rb +0 -4
- data/spec/error_buffer_spec.rb +7 -9
- data/spec/file_header_spec.rb +17 -14
- data/spec/live_spec.rb +12 -5
- data/spec/offline_spec.rb +10 -11
- data/spec/packet_behaviors.rb +20 -6
- data/spec/packet_injection_spec.rb +9 -8
- data/spec/packet_spec.rb +22 -26
- data/spec/pcap_spec.rb +52 -40
- data/spec/spec_helper.rb +16 -5
- data/spec/wrapper_behaviors.rb +0 -3
- data/tasks/doc.rake +69 -0
- data/tasks/gem.rake +200 -0
- data/tasks/git.rake +40 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +286 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +142 -92
- data/README.rdoc +0 -30
- data/VERSION +0 -1
- data/lib/ffi/pcap/bpf.rb +0 -106
- data/lib/ffi/pcap/version.rb +0 -6
- data/tasks/rcov.rb +0 -6
- data/tasks/rdoc.rb +0 -17
- data/tasks/spec.rb +0 -9
- data/tasks/yard.rb +0 -21
data/lib/ffi/pcap/stat.rb
CHANGED
@@ -1,57 +1,27 @@
|
|
1
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
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
|
data/lib/ffi/pcap/time_val.rb
CHANGED
@@ -1,48 +1,62 @@
|
|
1
1
|
module FFI
|
2
|
-
module PCap
|
3
|
-
|
4
|
-
include FFI::DRY::StructHelper
|
2
|
+
module PCap
|
3
|
+
class TimeVal < FFI::Struct
|
5
4
|
|
6
|
-
|
7
|
-
field :tv_sec, :time_t
|
8
|
-
field :tv_usec, :suseconds_t
|
9
|
-
end
|
5
|
+
include FFI::DRY::StructHelper
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
data/lib/ffi/pcap/typedefs.rb
CHANGED
@@ -1,27 +1,23 @@
|
|
1
1
|
module FFI
|
2
|
-
module PCap
|
3
|
-
|
2
|
+
module PCap
|
3
|
+
extend FFI::Library
|
4
4
|
|
5
|
-
|
6
|
-
typedef :uint, :bpf_uint32
|
5
|
+
typedef :pointer, :FILE
|
7
6
|
|
8
|
-
|
9
|
-
:
|
10
|
-
:pcap_d_in,
|
11
|
-
:pcap_d_out
|
12
|
-
]
|
7
|
+
typedef :int, :bpf_int32
|
8
|
+
typedef :uint, :bpf_uint32
|
13
9
|
|
14
|
-
|
15
|
-
|
10
|
+
enum :pcap_direction_t, [
|
11
|
+
:pcap_d_inout,
|
12
|
+
:pcap_d_in,
|
13
|
+
:pcap_d_out
|
14
|
+
]
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
typedef :pointer, :pcap_addr_t
|
16
|
+
# For Win32-only pcap_setmode()
|
17
|
+
enum :pcap_w32_modes_enum, [ :capt, :stat, :mon ]
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
data/spec/data_link_spec.rb
CHANGED
@@ -1,65 +1,69 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe DataLink do
|
4
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
15
|
+
subject.name.should == 'NULL'
|
18
16
|
end
|
19
17
|
|
20
|
-
it "should
|
21
|
-
|
22
|
-
DataLink.should === @datalink
|
18
|
+
it "should have a description" do
|
19
|
+
subject.description.should_not be_empty
|
23
20
|
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
31
|
-
|
32
|
-
(@datalink == 1).should == false
|
33
|
-
end
|
26
|
+
link.name.should == 'NULL'
|
27
|
+
end
|
34
28
|
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
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
|
-
|
67
|
+
subject.to_s.should == 'NULL'
|
64
68
|
end
|
65
69
|
end
|
data/spec/dead_spec.rb
CHANGED
data/spec/error_buffer_spec.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ErrorBuffer do
|
4
|
-
|
5
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
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
|
data/spec/file_header_spec.rb
CHANGED
@@ -1,28 +1,31 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FileHeader do
|
4
|
-
|
5
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
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
|