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
@@ -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
|