packetgen 3.1.4 → 3.2.0
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.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/bin/pgconsole +1 -0
- data/lib/packetgen.rb +19 -3
- data/lib/packetgen/capture.rb +30 -9
- data/lib/packetgen/config.rb +15 -9
- data/lib/packetgen/deprecation.rb +1 -1
- data/lib/packetgen/header/asn1_base.rb +19 -9
- data/lib/packetgen/header/base.rb +68 -70
- data/lib/packetgen/header/dhcpv6/duid.rb +3 -1
- data/lib/packetgen/header/dhcpv6/option.rb +4 -12
- data/lib/packetgen/header/dns/name.rb +18 -7
- data/lib/packetgen/header/dns/qdsection.rb +1 -1
- data/lib/packetgen/header/dns/question.rb +2 -0
- data/lib/packetgen/header/dot11.rb +25 -38
- data/lib/packetgen/header/dot11/data.rb +28 -34
- data/lib/packetgen/header/dot1x.rb +1 -14
- data/lib/packetgen/header/eap.rb +14 -17
- data/lib/packetgen/header/eth.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +4 -2
- data/lib/packetgen/header/http/request.rb +37 -18
- data/lib/packetgen/header/http/response.rb +11 -5
- data/lib/packetgen/header/http/verbs.rb +1 -1
- data/lib/packetgen/header/igmpv3/group_record.rb +2 -0
- data/lib/packetgen/header/ip.rb +27 -26
- data/lib/packetgen/header/ip/addr.rb +3 -1
- data/lib/packetgen/header/ip/option.rb +4 -4
- data/lib/packetgen/header/ipv6/addr.rb +2 -0
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -0
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -3
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -0
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv3/lsa.rb +9 -3
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
- data/lib/packetgen/header/snmp.rb +3 -2
- data/lib/packetgen/header/tcp.rb +1 -20
- data/lib/packetgen/header/tcp/option.rb +8 -6
- data/lib/packetgen/inspect.rb +1 -17
- data/lib/packetgen/packet.rb +10 -6
- data/lib/packetgen/pcapng.rb +11 -11
- data/lib/packetgen/pcapng/block.rb +15 -2
- data/lib/packetgen/pcapng/epb.rb +22 -15
- data/lib/packetgen/pcapng/file.rb +166 -81
- data/lib/packetgen/pcapng/idb.rb +7 -9
- data/lib/packetgen/pcapng/shb.rb +35 -28
- data/lib/packetgen/pcapng/spb.rb +16 -12
- data/lib/packetgen/pcapng/unknown_block.rb +3 -11
- data/lib/packetgen/pcaprub_wrapper.rb +25 -11
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/abstract_tlv.rb +3 -1
- data/lib/packetgen/types/array.rb +17 -10
- data/lib/packetgen/types/cstring.rb +56 -19
- data/lib/packetgen/types/enum.rb +4 -0
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +180 -113
- data/lib/packetgen/types/int.rb +15 -1
- data/lib/packetgen/types/int_string.rb +8 -0
- data/lib/packetgen/types/length_from.rb +18 -10
- data/lib/packetgen/types/oui.rb +2 -0
- data/lib/packetgen/types/string.rb +58 -7
- data/lib/packetgen/types/tlv.rb +2 -0
- data/lib/packetgen/unknown_packet.rb +84 -0
- data/lib/packetgen/utils.rb +6 -7
- data/lib/packetgen/version.rb +1 -1
- metadata +18 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f3faa715cd36e918df79355267c50690bdde15f1566e23947d26890e7b89a82
|
4
|
+
data.tar.gz: d374447f230500b0c5be84b225d3a5576f019afc4870dc6512c659bc2e069d67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de7911facea630eaa2d3d4afd2ae15e1cbd927241ebf0c63ec096c64eac31c58e519d379476763c50fc1b4290029cec4b14dbf9e96ae9aa05dc06701cf45af32
|
7
|
+
data.tar.gz: 69881fc66b4af80177bdad4b5b2daa4bd28259596bbf8a36112998aa9a8c117c7c9898180372635fcc1b47376e2fab4fb5cece88be5c000277cdce825fb03168
|
data/README.md
CHANGED
data/bin/pgconsole
CHANGED
data/lib/packetgen.rb
CHANGED
@@ -32,6 +32,7 @@ module PacketGen
|
|
32
32
|
attr_reader :hdr
|
33
33
|
|
34
34
|
def initialize(prev_hdr, hdr)
|
35
|
+
super()
|
35
36
|
@prev_hdr = prev_hdr
|
36
37
|
@hdr = hdr
|
37
38
|
end
|
@@ -66,7 +67,7 @@ module PacketGen
|
|
66
67
|
# @yieldparam [Packet] packet
|
67
68
|
# @return [Array<Packet>]
|
68
69
|
def self.capture(**kwargs)
|
69
|
-
Packet.capture(kwargs) { |packet| yield packet if block_given? }
|
70
|
+
Packet.capture(**kwargs) { |packet| yield packet if block_given? }
|
70
71
|
end
|
71
72
|
|
72
73
|
# Shortcut for {Packet.read}
|
@@ -94,7 +95,21 @@ module PacketGen
|
|
94
95
|
# Get default network interface (ie. first non-loopback declared interface)
|
95
96
|
# @return [String]
|
96
97
|
def self.default_iface
|
97
|
-
|
98
|
+
return @default_iface if defined? @default_iface
|
99
|
+
|
100
|
+
@default_iface = Interfacez.raw_interface_addresses.each do |iface|
|
101
|
+
next unless iface.broadaddr
|
102
|
+
next unless Interfacez.ipv4_address_of(iface.name)
|
103
|
+
next unless Interfacez.ipv6_address_of(iface.name)
|
104
|
+
|
105
|
+
break iface.name
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Get loopback network interface
|
110
|
+
# @return [String]
|
111
|
+
def self.loopback_iface
|
112
|
+
Interfacez.loopback
|
98
113
|
end
|
99
114
|
|
100
115
|
# Shortcut to get a header class
|
@@ -114,11 +129,12 @@ module PacketGen
|
|
114
129
|
end
|
115
130
|
|
116
131
|
require 'packetgen/deprecation'
|
117
|
-
require 'packetgen/types'
|
118
132
|
require 'packetgen/inspect'
|
133
|
+
require 'packetgen/types'
|
119
134
|
require 'packetgen/pcapng'
|
120
135
|
require 'packetgen/pcap'
|
121
136
|
require 'packetgen/packet'
|
137
|
+
require 'packetgen/unknown_packet'
|
122
138
|
require 'packetgen/capture'
|
123
139
|
require 'packetgen/inject'
|
124
140
|
require 'packetgen/proto'
|
data/lib/packetgen/capture.rb
CHANGED
@@ -13,7 +13,9 @@ module PacketGen
|
|
13
13
|
class Capture
|
14
14
|
private
|
15
15
|
|
16
|
-
attr_reader :filter, :cap_thread, :snaplen, :promisc
|
16
|
+
attr_reader :filter, :cap_thread, :snaplen, :promisc, :monitor
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/ParameterLists
|
17
19
|
|
18
20
|
public
|
19
21
|
|
@@ -41,14 +43,18 @@ module PacketGen
|
|
41
43
|
# yielding. Default: +true+
|
42
44
|
# @param [Integer] snaplen maximum number of bytes to capture for
|
43
45
|
# each packet.
|
46
|
+
# @param [Boolean] monitor enable or disable monitor mode on interface (if supported by +iface+).
|
44
47
|
# @since 2.0.0 remove old 1.x API
|
45
48
|
# @since 3.0.0 arguments are kwargs and no more a hash
|
46
|
-
|
47
|
-
|
49
|
+
# @since 3.1.5 add monitor argument
|
50
|
+
# @author Sylvain Daubert
|
51
|
+
# @author optix2000 - add monitor argument
|
52
|
+
def initialize(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: nil, monitor: nil)
|
53
|
+
@iface = iface || PacketGen.default_iface || PacketGen.loopback_iface
|
48
54
|
|
49
55
|
@packets = []
|
50
56
|
@raw_packets = []
|
51
|
-
set_options iface, max, timeout, filter, promisc, parse, snaplen
|
57
|
+
set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
|
52
58
|
end
|
53
59
|
|
54
60
|
# Start capture
|
@@ -56,8 +62,11 @@ module PacketGen
|
|
56
62
|
# @yieldparam [Packet,String] packet if a block is given, yield each
|
57
63
|
# captured packet (Packet or raw data String, depending on +:parse+ option)
|
58
64
|
# @since 3.0.0 arguments are kwargs and no more a hash
|
59
|
-
|
60
|
-
|
65
|
+
# @since 3.1.5 add monitor argument
|
66
|
+
# @author Sylvain Daubert
|
67
|
+
# @author optix2000 - add monitor argument
|
68
|
+
def start(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: nil, monitor: nil, &block)
|
69
|
+
set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
|
61
70
|
|
62
71
|
@cap_thread = Thread.new do
|
63
72
|
PCAPRUBWrapper.capture(**capture_args) do |packet_data|
|
@@ -79,7 +88,10 @@ module PacketGen
|
|
79
88
|
|
80
89
|
private
|
81
90
|
|
82
|
-
|
91
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
92
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
93
|
+
|
94
|
+
def set_options(iface, max, timeout, filter, promisc, parse, snaplen, monitor)
|
83
95
|
@max = max if max
|
84
96
|
@filter = filter unless filter.nil?
|
85
97
|
@timeout = timeout unless timeout.nil?
|
@@ -87,10 +99,15 @@ module PacketGen
|
|
87
99
|
@snaplen = snaplen unless snaplen.nil?
|
88
100
|
@parse = parse unless parse.nil?
|
89
101
|
@iface = iface unless iface.nil?
|
102
|
+
@monitor = monitor unless monitor.nil?
|
90
103
|
end
|
91
104
|
|
105
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
106
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
107
|
+
# rubocop:enable Metrics/ParameterLists
|
108
|
+
|
92
109
|
def capture_args
|
93
|
-
h = { iface: iface, filter: filter }
|
110
|
+
h = { iface: iface, filter: filter, monitor: monitor }
|
94
111
|
h[:snaplen] = snaplen unless snaplen.nil?
|
95
112
|
h[:promisc] = promisc unless promisc.nil?
|
96
113
|
h
|
@@ -105,7 +122,11 @@ module PacketGen
|
|
105
122
|
def add_packet(data, &block)
|
106
123
|
raw_packets << data
|
107
124
|
if @parse
|
108
|
-
|
125
|
+
begin
|
126
|
+
packet = Packet.parse(data)
|
127
|
+
rescue ParseError
|
128
|
+
packet = UnknownPacket.new.parse(data)
|
129
|
+
end
|
109
130
|
packets << packet
|
110
131
|
block&.call(packet)
|
111
132
|
elsif block
|
data/lib/packetgen/config.rb
CHANGED
@@ -22,37 +22,43 @@ module PacketGen
|
|
22
22
|
attr_reader :default_iface
|
23
23
|
|
24
24
|
def initialize
|
25
|
-
@default_iface =
|
25
|
+
@default_iface = PacketGen.default_iface || PacketGen.loopback_iface
|
26
26
|
@hwaddr = {}
|
27
27
|
@ipaddr = {}
|
28
28
|
@ip6addr = {}
|
29
29
|
|
30
|
-
|
31
|
-
@hwaddr[iface_name] = Interfacez.mac_address_of(iface_name)
|
32
|
-
@ipaddr[iface_name] = Interfacez.ipv4_address_of(iface_name)
|
33
|
-
@ip6addr[iface_name] = Interfacez.ipv6_addresses_of(iface_name)
|
34
|
-
end
|
30
|
+
initialize_local_addresses
|
35
31
|
end
|
36
32
|
|
37
33
|
# Get MAC address for given network interface
|
38
34
|
# @param [String,nil] iface network interface. If +nil+, use default one.
|
39
35
|
# @return [String]
|
40
36
|
def hwaddr(iface=nil)
|
41
|
-
@hwaddr[iface ||
|
37
|
+
@hwaddr[iface || default_iface]
|
42
38
|
end
|
43
39
|
|
44
40
|
# Get IP address for given network interface
|
45
41
|
# @param [String,nil] iface network interface. If +nil+, use default one.
|
46
42
|
# @return [String]
|
47
43
|
def ipaddr(iface=nil)
|
48
|
-
@ipaddr[iface ||
|
44
|
+
@ipaddr[iface || default_iface]
|
49
45
|
end
|
50
46
|
|
51
47
|
# Get IPv6 addresses for given network interface
|
52
48
|
# @param [String,nil] iface network interface. If +nil+, use default one.
|
53
49
|
# @return [Array<String>]
|
54
50
|
def ip6addr(iface=nil)
|
55
|
-
@ip6addr[iface ||
|
51
|
+
@ip6addr[iface || default_iface]
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def initialize_local_addresses
|
57
|
+
Interfacez.all do |iface_name|
|
58
|
+
@hwaddr[iface_name] = Interfacez.mac_address_of(iface_name)
|
59
|
+
@ipaddr[iface_name] = Interfacez.ipv4_address_of(iface_name)
|
60
|
+
@ip6addr[iface_name] = Interfacez.ipv6_addresses_of(iface_name)
|
61
|
+
end
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
@@ -31,7 +31,7 @@ module PacketGen
|
|
31
31
|
complete_deprecated_method_name = "#{base_name}#{deprecated_method}"
|
32
32
|
complete_new_method_name = "#{base_name}#{new_method}" unless new_method.nil?
|
33
33
|
|
34
|
-
file, line = caller(2..2).split(':')[0, 2]
|
34
|
+
file, line = caller(2..2).first.split(':')[0, 2]
|
35
35
|
message = +"#{file}:#{line}: #{complete_deprecated_method_name} is deprecated"
|
36
36
|
message << " in favor of #{complete_new_method_name}" unless new_method.nil?
|
37
37
|
message << '. ' << self.removed(remove_version)
|
@@ -19,14 +19,20 @@ module PacketGen
|
|
19
19
|
class ASN1Base < RASN1::Model
|
20
20
|
include Headerable
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
class <<self
|
23
|
+
# Define some methods from given ASN.1 fields to mimic {Base} attributes
|
24
|
+
# @param [Array<Symbol>] attributes
|
25
|
+
# @return [void]
|
26
|
+
def define_attributes(*attributes)
|
27
|
+
@attributes = attributes
|
28
|
+
attributes.each do |attr|
|
29
|
+
class_eval "def #{attr}; @elements[:#{attr}].value; end\n" \
|
30
|
+
"def #{attr}=(v); @elements[:#{attr}].value = v; end"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def known_headers
|
35
|
+
@known_headers ||= {}.freeze
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
@@ -37,7 +43,11 @@ module PacketGen
|
|
37
43
|
# @param [String] str
|
38
44
|
# @return [ASN1Base] self
|
39
45
|
def read(str)
|
40
|
-
|
46
|
+
begin
|
47
|
+
parse(str, ber: true)
|
48
|
+
rescue RASN1::ASN1Error
|
49
|
+
# suppress exception to allow guessing
|
50
|
+
end
|
41
51
|
self
|
42
52
|
end
|
43
53
|
|
@@ -99,10 +99,8 @@ module PacketGen
|
|
99
99
|
|
100
100
|
# each iterator
|
101
101
|
# @return [void]
|
102
|
-
def each
|
103
|
-
@bindings.each
|
104
|
-
yield b
|
105
|
-
end
|
102
|
+
def each(&block)
|
103
|
+
@bindings.each(&block)
|
106
104
|
end
|
107
105
|
|
108
106
|
# @return [Boolean]
|
@@ -144,74 +142,74 @@ module PacketGen
|
|
144
142
|
klass.class_eval { @known_headers = {} }
|
145
143
|
end
|
146
144
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
# Given value may be a lambda, whose alone argument is the value extracted
|
153
|
-
# from header field (or +nil+ when lambda is used to set field while adding
|
154
|
-
# a header).
|
155
|
-
#
|
156
|
-
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
157
|
-
# fields, the latter to check bindings. This may be used when multiple and
|
158
|
-
# non-trivial checks should be made.
|
159
|
-
# @return [void]
|
160
|
-
# @example Basic examples
|
161
|
-
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
162
|
-
# Header1.bind Header2, field1: 42
|
163
|
-
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
164
|
-
# # and field2 has value 43 or 44
|
165
|
-
# Header1.bind Header3, field1: 43, field2: 43
|
166
|
-
# Header1.bind Header3, field1: 43, field2: 44
|
167
|
-
# @example Defining a binding on a field using a lambda.
|
168
|
-
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
169
|
-
# # greater or equal to 44. When adding a Header2 to a Header1
|
170
|
-
# # with Packet#add, force value to 44.
|
171
|
-
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
172
|
-
# @example Defining a binding using procs key
|
173
|
-
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
174
|
-
# # and first two bytes of header1's body are null.
|
175
|
-
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
176
|
-
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
177
|
-
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
178
|
-
# @since 2.7.0
|
179
|
-
def self.bind(header_klass, args={})
|
180
|
-
if @known_headers[header_klass].nil?
|
181
|
-
bindings = Bindings.new
|
182
|
-
@known_headers[header_klass] = bindings
|
183
|
-
else
|
184
|
-
bindings = @known_headers[header_klass]
|
185
|
-
end
|
186
|
-
bindings.new_set
|
187
|
-
args.each do |key, value|
|
188
|
-
bindings << if key == :procs
|
189
|
-
ProcBinding.new(value)
|
190
|
-
else
|
191
|
-
Binding.new(key, value)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
145
|
+
class <<self
|
146
|
+
# @api private
|
147
|
+
# Get known headers
|
148
|
+
# @return [Hash] keys: header classes, values: hashes
|
149
|
+
attr_reader :known_headers
|
195
150
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
151
|
+
# Bind a upper header to current one.
|
152
|
+
# @param [Class] header_klass header class to bind to current class
|
153
|
+
# @param [Hash] args current class fields and their value when +header_klass+
|
154
|
+
# is embedded in current class.
|
155
|
+
#
|
156
|
+
# Given value may be a lambda, whose alone argument is the value extracted
|
157
|
+
# from header field (or +nil+ when lambda is used to set field while adding
|
158
|
+
# a header).
|
159
|
+
#
|
160
|
+
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
161
|
+
# fields, the latter to check bindings. This may be used when multiple and
|
162
|
+
# non-trivial checks should be made.
|
163
|
+
# @return [void]
|
164
|
+
# @example Basic examples
|
165
|
+
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
166
|
+
# Header1.bind Header2, field1: 42
|
167
|
+
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
168
|
+
# # and field2 has value 43 or 44
|
169
|
+
# Header1.bind Header3, field1: 43, field2: 43
|
170
|
+
# Header1.bind Header3, field1: 43, field2: 44
|
171
|
+
# @example Defining a binding on a field using a lambda.
|
172
|
+
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
173
|
+
# # greater or equal to 44. When adding a Header2 to a Header1
|
174
|
+
# # with Packet#add, force value to 44.
|
175
|
+
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
176
|
+
# @example Defining a binding using procs key
|
177
|
+
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
178
|
+
# # and first two bytes of header1's body are null.
|
179
|
+
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
180
|
+
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
181
|
+
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
182
|
+
# @since 2.7.0
|
183
|
+
def bind(header_klass, args={})
|
184
|
+
if @known_headers[header_klass].nil?
|
185
|
+
bindings = Bindings.new
|
186
|
+
@known_headers[header_klass] = bindings
|
187
|
+
else
|
188
|
+
bindings = @known_headers[header_klass]
|
189
|
+
end
|
190
|
+
bindings.new_set
|
191
|
+
args.each do |key, value|
|
192
|
+
bindings << if key == :procs
|
193
|
+
ProcBinding.new(value)
|
194
|
+
else
|
195
|
+
Binding.new(key, value)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
209
199
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
200
|
+
# Helper method to calculate length of +hdr+ and set its +length+ field.
|
201
|
+
# To be used by +#calc_length+ in Base subclasses.
|
202
|
+
# @param [Base] hdr
|
203
|
+
# @param [Boolean] header_in_size if +true+ header is included in length,
|
204
|
+
# if +false+, only +body+ is taken into account
|
205
|
+
def calculate_and_set_length(hdr, header_in_size: true)
|
206
|
+
length = if header_in_size
|
207
|
+
hdr.sz
|
208
|
+
else
|
209
|
+
hdr[:body].sz
|
210
|
+
end
|
211
|
+
hdr.length = length
|
212
|
+
end
|
215
213
|
end
|
216
214
|
|
217
215
|
# @see Types::Fields#initialize
|
@@ -11,6 +11,8 @@ module PacketGen
|
|
11
11
|
# @abstract Base class for DUID (DHCP Unique ID)
|
12
12
|
# @author Sylvain Daubert
|
13
13
|
class DUID < Types::Fields
|
14
|
+
include Types::Fieldable
|
15
|
+
|
14
16
|
TYPES = {
|
15
17
|
'DUID-LLT' => 1,
|
16
18
|
'DUID-EN' => 2,
|
@@ -34,7 +36,7 @@ module PacketGen
|
|
34
36
|
# @param [String] str
|
35
37
|
# @return [DUID]
|
36
38
|
def read(str)
|
37
|
-
if self.
|
39
|
+
if self.instance_of?(DUID)
|
38
40
|
super
|
39
41
|
case type
|
40
42
|
when 1
|
@@ -17,6 +17,8 @@ module PacketGen
|
|
17
17
|
# field to replace it by specific option field(s).
|
18
18
|
# @author Sylvain Daubert
|
19
19
|
class Option < Types::Fields
|
20
|
+
include Types::Fieldable
|
21
|
+
|
20
22
|
# @!attribute type
|
21
23
|
# 16-bit option type
|
22
24
|
# @return [Integer]
|
@@ -85,7 +87,7 @@ module PacketGen
|
|
85
87
|
# Get human-readable {#type}
|
86
88
|
# @return [String]
|
87
89
|
def human_type
|
88
|
-
if self.
|
90
|
+
if self.instance_of?(Option)
|
89
91
|
"option#{type}"
|
90
92
|
else
|
91
93
|
self.class.to_s.sub(/.*::/, '')
|
@@ -230,17 +232,7 @@ module PacketGen
|
|
230
232
|
|
231
233
|
# @!attribute options
|
232
234
|
# @return [RequestedOptions]
|
233
|
-
define_field :options, RequestedOptions
|
234
|
-
|
235
|
-
# Populate object from +str+
|
236
|
-
# @param [String] str
|
237
|
-
# @return [self]
|
238
|
-
def read(str)
|
239
|
-
self[:type].read str[0, 2]
|
240
|
-
self[:length].read str[2, 2]
|
241
|
-
self[:options].read str[4, self.length]
|
242
|
-
self
|
243
|
-
end
|
235
|
+
define_field :options, RequestedOptions, builder: ->(h, t) { t.new(length_from: h[:length]) }
|
244
236
|
|
245
237
|
# Get human-readable data
|
246
238
|
# @return [String]
|