ffi-pcap 0.2.0 → 0.2.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.
- 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
@@ -1,175 +1,200 @@
|
|
1
1
|
module FFI
|
2
|
-
module PCap
|
2
|
+
module PCap
|
3
|
+
#
|
4
|
+
# An abstract base wrapper class with features common to all pcap
|
5
|
+
# wrapper types. Do not use this directly. Instead refer to {Live},
|
6
|
+
# {Dead}, or {Offline} class for {PCap.open_live}, {PCap.open_dead}, or
|
7
|
+
# {PCap.open_file}, respectively.
|
8
|
+
#
|
9
|
+
class CommonWrapper
|
3
10
|
|
4
|
-
|
5
|
-
# wrapper types. Do not use this directly. Instead refer to Live,
|
6
|
-
# Dead, or Offline class for open_live, open_dead, or open_file
|
7
|
-
# respectively.
|
8
|
-
class CommonWrapper
|
9
|
-
attr_accessor :pcap
|
11
|
+
attr_accessor :pcap
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def initialize(pcap, opts={})
|
14
|
+
@pcap = pcap
|
15
|
+
@closed = false
|
16
|
+
@errbuf ||= ErrorBuffer.new
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
+
yield self if block_given?
|
19
|
+
end
|
18
20
|
|
21
|
+
#
|
22
|
+
# Returns the DataLink for the pcap device.
|
23
|
+
#
|
24
|
+
def datalink
|
25
|
+
@datalink ||= DataLink.new(PCap.pcap_datalink(_pcap))
|
26
|
+
end
|
19
27
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
28
|
+
#
|
29
|
+
# Returns an array of supported DataLinks for the pcap device.
|
30
|
+
#
|
31
|
+
def supported_datalinks
|
32
|
+
dlt_lst = MemoryPointer.new(:pointer)
|
24
33
|
|
34
|
+
if (cnt = PCap.pcap_list_datalinks(_pcap, dlt_lst)) < 0
|
35
|
+
raise(LibError, "pcap_list_datalinks(): #{geterr}",caller)
|
36
|
+
end
|
37
|
+
|
38
|
+
# extract datalink values
|
39
|
+
p = dlt_lst.get_pointer(0)
|
40
|
+
ret = p.get_array_of_int(0, cnt).map {|dlt| DataLink.new(dlt) }
|
25
41
|
|
26
|
-
|
27
|
-
|
28
|
-
dlt_lst = FFI::MemoryPointer.new(:pointer)
|
29
|
-
if (cnt=FFI::PCap.pcap_list_datalinks(_pcap, dlt_lst)) < 0
|
30
|
-
raise(LibError, "pcap_list_datalinks(): #{geterr()}")
|
42
|
+
CRT.free(p)
|
43
|
+
return ret
|
31
44
|
end
|
32
|
-
# extract datalink values
|
33
|
-
p = dlt_lst.get_pointer(0)
|
34
|
-
ret = p.get_array_of_int(0, cnt).map {|dlt| DataLink.new(dlt) }
|
35
|
-
CRT.free(p)
|
36
|
-
return ret
|
37
|
-
end
|
38
45
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
#
|
47
|
+
# Indicates whether the pcap interface is already closed.
|
48
|
+
#
|
49
|
+
def closed?
|
50
|
+
@closed == true
|
51
|
+
end
|
43
52
|
|
44
|
-
|
45
|
-
|
46
|
-
|
53
|
+
def ready?
|
54
|
+
(@closed == false && !(@pcap.nil?) && !(@pcap.null?))
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Closes the pcap interface using libpcap.
|
59
|
+
#
|
60
|
+
def close
|
61
|
+
unless @closed
|
62
|
+
PCap.pcap_close(_pcap)
|
47
63
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
FFI::PCap.pcap_close(_pcap)
|
52
|
-
@closed = true
|
53
|
-
@pcap = nil
|
64
|
+
@closed = true
|
65
|
+
@pcap = nil
|
66
|
+
end
|
54
67
|
end
|
55
|
-
end
|
56
68
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# Gets the snapshot length.
|
67
|
-
#
|
68
|
-
# @return [Integer]
|
69
|
-
# Snapshot length for the pcap interface.
|
70
|
-
def snaplen
|
71
|
-
FFI::PCap.pcap_snapshot(_pcap)
|
72
|
-
end
|
69
|
+
#
|
70
|
+
# Returns the pcap interface pointer.
|
71
|
+
#
|
72
|
+
# @return [FFI::Pointer]
|
73
|
+
# Internal pointer to a pcap_t handle.
|
74
|
+
#
|
75
|
+
def to_ptr
|
76
|
+
_check_pcap()
|
77
|
+
end
|
73
78
|
|
79
|
+
#
|
80
|
+
# Gets the snapshot length.
|
81
|
+
#
|
82
|
+
# @return [Integer]
|
83
|
+
# Snapshot length for the pcap interface.
|
84
|
+
def snaplen
|
85
|
+
PCap.pcap_snapshot(_pcap)
|
86
|
+
end
|
74
87
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
88
|
+
#
|
89
|
+
# Compiles a pcap filter but does not apply it to the pcap interface.
|
90
|
+
#
|
91
|
+
# @param [String] expression
|
92
|
+
# A pcap filter expression. See `pcap-filter(7)` manpage for syntax.
|
93
|
+
#
|
94
|
+
# @param [Hash] opts
|
95
|
+
# Additional options for compile
|
96
|
+
#
|
97
|
+
# @option opts [optional, Integer] :optimize
|
98
|
+
# Optimization flag. 0 means don't optimize. Defaults to 1.
|
99
|
+
#
|
100
|
+
# @option opts [optional, Integer] :netmask
|
101
|
+
# A 32-bit number representing the IPv4 netmask of the network on
|
102
|
+
# which packets are being captured. It is only used when checking
|
103
|
+
# for IPv4 broadcast addresses in the filter program.
|
104
|
+
# Default: 0 (unspecified netmask)
|
105
|
+
#
|
106
|
+
# @return [BPF::Program]
|
107
|
+
# A BPF program structure for the compiled filter.
|
108
|
+
#
|
109
|
+
# @raise [LibError]
|
110
|
+
# On failure, an exception is raised with the relevant error
|
111
|
+
# message from libpcap.
|
112
|
+
#
|
113
|
+
def compile(expression, opts={})
|
114
|
+
optimize = opts[:optimize] || 1
|
115
|
+
netmask = opts[:netmask] || 0
|
116
|
+
code = BPFProgram.new
|
117
|
+
|
118
|
+
if PCap.pcap_compile(_pcap, code, expression, optimize, netmask) != 0
|
119
|
+
raise(LibError,"pcap_compile(): #{geterr()}",caller)
|
120
|
+
end
|
121
|
+
|
122
|
+
return code
|
105
123
|
end
|
106
|
-
return code
|
107
|
-
end
|
108
124
|
|
125
|
+
#
|
126
|
+
# @return [Dumper]
|
127
|
+
#
|
128
|
+
# @raise [LibError]
|
129
|
+
# On failure, an exception is raised with the relevant error
|
130
|
+
# message from libpcap.
|
131
|
+
#
|
132
|
+
def open_dump(path)
|
133
|
+
dp = PCap.pcap_dump_open(_pcap, File.expand_path(path))
|
109
134
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
# On failure, an exception is raised with the relevant error
|
114
|
-
# message from libpcap.
|
115
|
-
#
|
116
|
-
def open_dump(path)
|
117
|
-
dp = FFI::PCap.pcap_dump_open(_pcap, File.expand_path(path))
|
118
|
-
raise(LibError, "pcap_dump_open(): #{geterr()}") if dp.null?
|
119
|
-
return Dumper.new(dp)
|
120
|
-
end
|
135
|
+
if dp.null?
|
136
|
+
raise(LibError,"pcap_dump_open(): #{geterr}",caller)
|
137
|
+
end
|
121
138
|
|
139
|
+
return Dumper.new(dp)
|
140
|
+
end
|
122
141
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
142
|
+
#
|
143
|
+
# @return [String]
|
144
|
+
# The error text pertaining to the last pcap library error.
|
145
|
+
#
|
146
|
+
def geterr
|
147
|
+
PCap.pcap_geterr(_pcap)
|
148
|
+
end
|
129
149
|
|
130
|
-
|
150
|
+
alias error geterr
|
131
151
|
|
152
|
+
private
|
132
153
|
|
133
|
-
|
134
|
-
# Raises an exception if
|
154
|
+
#
|
155
|
+
# Raises an exception if `@pcap` is not set.
|
135
156
|
#
|
136
157
|
# Internal sanity check to confirm the pcap instance
|
137
158
|
# variable has been set. Otherwise very bad things can
|
138
159
|
# ensue by passing a null pointer to various libpcap
|
139
160
|
# functions.
|
161
|
+
#
|
140
162
|
def _check_pcap
|
141
163
|
if @pcap.nil?
|
142
|
-
raise(StandardError,
|
164
|
+
raise(StandardError,"nil pcap device",caller)
|
143
165
|
else
|
144
|
-
|
166
|
+
@pcap
|
145
167
|
end
|
146
168
|
end
|
147
169
|
|
170
|
+
#
|
148
171
|
# Raises an exception if @pcap is not set or is a null pointer.
|
149
172
|
#
|
150
173
|
# Internal sanity check to confirm the pcap pointer
|
151
174
|
# variable has been set and is not a null pointer.
|
152
175
|
# Otherwise very bad things can ensue by passing a null
|
153
176
|
# pointer to various libpcap functions.
|
177
|
+
#
|
154
178
|
def _pcap
|
155
|
-
|
156
|
-
|
179
|
+
ptr = _check_pcap
|
180
|
+
|
181
|
+
if ptr.null?
|
182
|
+
raise(StandardError,"null pointer to pcap device",caller)
|
183
|
+
else
|
184
|
+
ptr
|
157
185
|
end
|
158
|
-
p
|
159
186
|
end
|
160
187
|
|
188
|
+
end
|
161
189
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
attach_function :pcap_set_datalink, [:pcap_t, :int], :int
|
171
|
-
attach_function :pcap_snapshot, [:pcap_t], :int
|
172
|
-
attach_function :pcap_dump_open, [:pcap_t, :string], :pcap_dumper_t
|
190
|
+
attach_function :pcap_close, [:pcap_t], :void
|
191
|
+
attach_function :pcap_geterr, [:pcap_t], :string
|
192
|
+
attach_function :pcap_compile, [:pcap_t, BPFProgram, :string, :int, :bpf_uint32], :int
|
193
|
+
attach_function :pcap_datalink, [:pcap_t], :int
|
194
|
+
attach_function :pcap_list_datalinks, [:pcap_t, :pointer], :int
|
195
|
+
attach_function :pcap_set_datalink, [:pcap_t, :int], :int
|
196
|
+
attach_function :pcap_snapshot, [:pcap_t], :int
|
197
|
+
attach_function :pcap_dump_open, [:pcap_t, :string], :pcap_dumper_t
|
173
198
|
|
174
|
-
end
|
199
|
+
end
|
175
200
|
end
|
@@ -1,38 +1,38 @@
|
|
1
|
-
|
2
1
|
module FFI
|
3
|
-
module PCap
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
2
|
+
module PCap
|
3
|
+
#
|
4
|
+
# {CopyHandler} is a callback handler for use with {CaptureWrapper#loop}
|
5
|
+
# and {CaptureWrapper#dispatch}. When used, it works exactly as normal,
|
6
|
+
# passing a reference to a pcap wrapper and {Packet} except for one
|
7
|
+
# important difference. A copy of the {Packet} is yielded to the callback
|
8
|
+
# instead of the volatile one received in the pcap_loop() and
|
9
|
+
# `pcap_dispatch()` callbacks.
|
10
|
+
#
|
11
|
+
# The {CopyHandler} implements receive_callback to return a _copy_
|
12
|
+
# of the {Packet} object. It is necessary to make a copy to keep
|
13
|
+
# allocated references to packets supplied by `pcap_loop()` and
|
14
|
+
# `pcap_dispatch()` callbacks outside of the scope of a single callback
|
15
|
+
# firing on one packet.
|
16
|
+
#
|
17
|
+
# This handler interface is used by default by {CaptureWrapper}, so it is
|
18
|
+
# generally always safe to keep references to received packets after new
|
19
|
+
# packets have been received or even after a pcap interface has been
|
20
|
+
# closed. See {CaptureWrapper} for more information.
|
21
|
+
#
|
22
|
+
class CopyHandler
|
23
|
+
def receive_pcap(pcap, pkt)
|
24
|
+
[pcap, pkt.copy]
|
25
|
+
end
|
25
26
|
end
|
26
|
-
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
#
|
29
|
+
# This class only exists for backward compatibility. Setting
|
30
|
+
# pcap handler to nil has the same effect now.
|
31
|
+
#
|
32
|
+
class Handler
|
33
|
+
def receive_pcap(*args)
|
34
|
+
args
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
37
|
-
end
|
38
|
-
|
data/lib/ffi/pcap/crt.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
|
-
|
2
1
|
module FFI
|
3
|
-
module PCap
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
ffi_lib FFI::Library::LIBC
|
2
|
+
module PCap
|
3
|
+
module CRT
|
4
|
+
extend FFI::Library
|
8
5
|
|
9
|
-
|
6
|
+
ffi_lib FFI::Library::LIBC
|
10
7
|
|
11
|
-
|
12
|
-
|
8
|
+
attach_function :free, [:pointer], :void
|
9
|
+
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
10
|
+
end
|
13
11
|
end
|
14
12
|
end
|
15
|
-
end
|
data/lib/ffi/pcap/data_link.rb
CHANGED
@@ -1,173 +1,198 @@
|
|
1
1
|
module FFI
|
2
|
-
module PCap
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
2
|
+
module PCap
|
3
|
+
class DataLink
|
4
|
+
|
5
|
+
#
|
6
|
+
# Several DLT names harvested out of the pcap-bpf.h header file. These
|
7
|
+
# are in alphabetical order. Their Array index _does_ _not_ match
|
8
|
+
# their pcap DLT value.
|
9
|
+
#
|
10
|
+
# Don't use this Array for anything except quick reference. Use the
|
11
|
+
# {lookup} class methods for actually resolving name to value
|
12
|
+
# mappings or such.
|
13
|
+
#
|
14
|
+
SOME_DLTS = %w[
|
15
|
+
A429 A653_ICM AIRONET_HEADER APPLE_IP_OVER_IEEE1394
|
16
|
+
ARCNET ARCNET_LINUX ATM_CLIP ATM_RFC1483 AURORA AX25 BACNET_MS_TP
|
17
|
+
BLUETOOTH_HCI_H4 BLUETOOTH_HCI_H4_WITH_PHDR CAN20B CHAOS CHDLC
|
18
|
+
CISCO_IOS C_HDLC DOCSIS ECONET EN10MB EN3MB ENC ERF ERF_ETH ERF_POS
|
19
|
+
FDDI FRELAY GCOM_SERIAL GCOM_T1E1 GPF_F GPF_T GPRS_LLC HHDLC IBM_SN
|
20
|
+
IBM_SP IEEE802 IEEE802_11 IEEE802_11_RADIO IEEE802_11_RADIO_AVS
|
21
|
+
IEEE802_15_4 IEEE802_15_4_LINUX IEEE802_16_MAC_CPS
|
22
|
+
IEEE802_16_MAC_CPS_RADIO IPFILTER IPMB IP_OVER_FC JUNIPER_ATM1
|
23
|
+
JUNIPER_ATM2 JUNIPER_CHDLC JUNIPER_ES JUNIPER_ETHER JUNIPER_FRELAY
|
24
|
+
JUNIPER_GGSN JUNIPER_ISM JUNIPER_MFR JUNIPER_MLFR JUNIPER_MLPPP
|
25
|
+
JUNIPER_MONITOR JUNIPER_PIC_PEER JUNIPER_PPP JUNIPER_PPPOE
|
26
|
+
JUNIPER_PPPOE_ATM JUNIPER_SERVICES JUNIPER_ST JUNIPER_VP LINUX_IRDA
|
27
|
+
LINUX_LAPD LINUX_PPP_WITHDIRECTION LINUX_SLL LOOP LTALK MFR MTP2
|
28
|
+
MTP2_WITH_PHDR MTP3 NULL OLD_PFLOG PCI_EXP PFLOG PFSYNC PPI PPP
|
29
|
+
PPP_BSDOS PPP_ETHER PPP_PPPD PPP_SERIAL PPP_WITH_DIRECTION
|
30
|
+
PRISM_HEADER PRONET RAIF1 RAW REDBACK_SMARTEDGE RIO SCCP SITA SLIP
|
31
|
+
SLIP_BSDOS SUNATM SYMANTEC_FIREWALL TZSP USB USB_LINUX USER0 USER1
|
32
|
+
USER10 USER11 USER12 USER13 USER14 USER15 USER2 USER3 USER4 USER5
|
33
|
+
USER6 USER7 USER8 USER9
|
34
|
+
]
|
35
|
+
|
36
|
+
#
|
37
|
+
# Uses the `pcap_datalnk_*` functions to lookup a datalink name and
|
38
|
+
# value pair.
|
39
|
+
#
|
40
|
+
# @param [String, Symbol or Integer] l
|
41
|
+
# The name or value to lookup. A Symbol is converted to String.
|
42
|
+
# Names are case-insensitive.
|
43
|
+
#
|
44
|
+
# @return [Array]
|
45
|
+
# A 2-element array containing [value, name]. Both elements are
|
46
|
+
# `nil` if the lookup failed.
|
47
|
+
#
|
48
|
+
def self.lookup(l)
|
49
|
+
val, name = nil
|
50
|
+
l = l.to_s if l.kind_of?(Symbol)
|
51
|
+
|
52
|
+
case l
|
53
|
+
when String
|
54
|
+
if (v = name_to_val(l))
|
55
|
+
name = val_to_name(v) # get the canonical name
|
56
|
+
val = v
|
57
|
+
end
|
58
|
+
when Integer
|
59
|
+
name = val_to_name(l)
|
60
|
+
val = l
|
61
|
+
else
|
62
|
+
raise(ArgumentError,"lookup takes either a String or Integer",caller)
|
51
63
|
end
|
52
|
-
|
53
|
-
name = val_to_name(l)
|
54
|
-
val = l
|
55
|
-
else
|
56
|
-
raise(ArgumentError, "lookup takes either a String or Integer")
|
64
|
+
return [val, name]
|
57
65
|
end
|
58
|
-
return [val, name]
|
59
|
-
end
|
60
66
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
#
|
68
|
+
# Translates a data link type name, which is a `DLT_` name with the
|
69
|
+
# `DLT_` removed, to the corresponding data link type numeric value.
|
70
|
+
#
|
71
|
+
# @param [String or Symbol] n
|
72
|
+
# The name to lookup. Names are case-insensitive.
|
73
|
+
#
|
74
|
+
# @return [Integer or nil]
|
75
|
+
# The numeric value for the datalink name or `nil` on failure.
|
76
|
+
#
|
77
|
+
def self.name_to_val(n)
|
78
|
+
n = n.to_s if n.kind_of?(Symbol)
|
79
|
+
v = PCap.pcap_datalink_name_to_val(n)
|
80
|
+
|
81
|
+
return v if v >= 0
|
73
82
|
end
|
74
|
-
end
|
75
83
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
#
|
85
|
+
# Translates a data link type value to the corresponding data link
|
86
|
+
# type name.
|
87
|
+
#
|
88
|
+
# @return [String or nil]
|
89
|
+
# The string name of the data-link or `nil` on failure.
|
90
|
+
#
|
91
|
+
def self.val_to_name(v)
|
92
|
+
PCap.pcap_datalink_val_to_name(v)
|
93
|
+
end
|
85
94
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if
|
112
|
-
|
113
|
-
|
95
|
+
#
|
96
|
+
# @param [String, Symbol or Integer] l
|
97
|
+
# The name or value to lookup. A Symbol is converted to String.
|
98
|
+
# Names are case-insensitive.
|
99
|
+
#
|
100
|
+
def self.describe(l)
|
101
|
+
l = l.to_s if l.kind_of?(Symbol)
|
102
|
+
l = PCap.pcap_datalink_name_to_val(l) if l.kind_of?(String)
|
103
|
+
|
104
|
+
PCap.pcap_datalink_val_to_description(l)
|
105
|
+
end
|
106
|
+
|
107
|
+
# FFI::PCap datalink numeric value
|
108
|
+
attr_reader :value
|
109
|
+
|
110
|
+
#
|
111
|
+
# Creates a new DataLink object with the specified value or name.
|
112
|
+
# The canonical name, value, and description are can be looked up on
|
113
|
+
# demand.
|
114
|
+
#
|
115
|
+
# @param [String or Integer] arg
|
116
|
+
# Arg can be a string or number which will be used to look up the
|
117
|
+
# datalink.
|
118
|
+
#
|
119
|
+
# @raise [UnsupportedDataLinkError]
|
120
|
+
# An exception is raised if a name is supplied and a lookup for its
|
121
|
+
# value fails or if the arg parameter is an invalid type.
|
122
|
+
#
|
123
|
+
def initialize(arg)
|
124
|
+
case arg
|
125
|
+
when String, Symbol
|
126
|
+
unless (@value = self.class.name_to_val(arg.to_s))
|
127
|
+
raise(UnsupportedDataLinkError, "Invalid DataLink: #{arg.to_s}")
|
128
|
+
end
|
129
|
+
when Numeric
|
130
|
+
@value = arg
|
131
|
+
else
|
132
|
+
raise(UnsupportedDataLinkError,"Invalid DataLink: #{arg.inspect}",caller)
|
114
133
|
end
|
115
|
-
|
116
|
-
@
|
117
|
-
else
|
118
|
-
raise(UnsupportedDataLinkError, "Invalid DataLink: #{arg.inspect}")
|
134
|
+
|
135
|
+
@name = self.class.val_to_name(@value)
|
119
136
|
end
|
120
|
-
@name = self.class.val_to_name(@value)
|
121
|
-
end
|
122
137
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
138
|
+
#
|
139
|
+
# Overrides the equality operator so that quick comparisons can be
|
140
|
+
# made against other DataLinks, name by String, or value by Integer.
|
141
|
+
#
|
142
|
+
def ==(other)
|
143
|
+
case other
|
144
|
+
when DataLink
|
145
|
+
self.value == other.value
|
146
|
+
when Numeric
|
147
|
+
self.value == other
|
148
|
+
when Symbol
|
149
|
+
@value == self.class.name_to_val(other.to_s)
|
150
|
+
when String
|
151
|
+
@value == self.class.name_to_val(other)
|
152
|
+
else
|
153
|
+
false
|
154
|
+
end
|
137
155
|
end
|
138
|
-
end
|
139
156
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
157
|
+
#
|
158
|
+
# Overrides the sort comparison operator to sort by DLT value.
|
159
|
+
#
|
160
|
+
def <=>(other)
|
161
|
+
self.value <=> other.value
|
162
|
+
end
|
144
163
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
164
|
+
#
|
165
|
+
# Returns the description of the datalink.
|
166
|
+
#
|
167
|
+
def description
|
168
|
+
@desc ||= self.class.describe(@value)
|
169
|
+
end
|
149
170
|
|
150
|
-
|
151
|
-
|
171
|
+
alias desc description
|
172
|
+
alias describe description
|
152
173
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
174
|
+
#
|
175
|
+
# Returns the canonical String name of the DataLink object
|
176
|
+
#
|
177
|
+
def name
|
178
|
+
@name
|
179
|
+
end
|
157
180
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
181
|
+
#
|
182
|
+
# Override `inspect` to always provide the name for irb,
|
183
|
+
# pretty_print, etc.
|
184
|
+
#
|
185
|
+
def inspect
|
186
|
+
"<#{self.class}:#{"0x%0.8x" % self.object_id} @value=#{@value}, @name=#{name().inspect}>"
|
187
|
+
end
|
163
188
|
|
164
|
-
|
165
|
-
|
166
|
-
end
|
189
|
+
alias to_s name
|
190
|
+
alias to_i value
|
167
191
|
|
168
|
-
|
169
|
-
attach_function :pcap_datalink_val_to_name, [:int], :string
|
170
|
-
attach_function :pcap_datalink_val_to_description, [:int], :string
|
192
|
+
end
|
171
193
|
|
172
|
-
|
194
|
+
attach_function :pcap_datalink_name_to_val, [:string], :int
|
195
|
+
attach_function :pcap_datalink_val_to_name, [:int], :string
|
196
|
+
attach_function :pcap_datalink_val_to_description, [:int], :string
|
197
|
+
end
|
173
198
|
end
|