packetgen 2.6.0 → 2.7.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/.gitignore +1 -0
- data/.rubocop.yml +28 -0
- data/Rakefile +6 -6
- data/bin/pgconsole +6 -6
- data/lib/packetgen.rb +4 -3
- data/lib/packetgen/capture.rb +5 -7
- data/lib/packetgen/config.rb +3 -3
- data/lib/packetgen/deprecation.rb +17 -0
- data/lib/packetgen/header.rb +40 -38
- data/lib/packetgen/header/arp.rb +46 -31
- data/lib/packetgen/header/asn1_base.rb +8 -8
- data/lib/packetgen/header/base.rb +108 -36
- data/lib/packetgen/header/bootp.rb +28 -19
- data/lib/packetgen/header/crypto.rb +6 -8
- data/lib/packetgen/header/dhcp.rb +4 -5
- data/lib/packetgen/header/dhcp/option.rb +46 -34
- data/lib/packetgen/header/dhcp/options.rb +0 -1
- data/lib/packetgen/header/dhcpv6.rb +10 -10
- data/lib/packetgen/header/dhcpv6/duid.rb +2 -3
- data/lib/packetgen/header/dhcpv6/option.rb +16 -21
- data/lib/packetgen/header/dhcpv6/relay.rb +6 -4
- data/lib/packetgen/header/dns.rb +13 -11
- data/lib/packetgen/header/dns/name.rb +4 -6
- data/lib/packetgen/header/dns/opt.rb +31 -31
- data/lib/packetgen/header/dns/option.rb +0 -2
- data/lib/packetgen/header/dns/qdsection.rb +1 -2
- data/lib/packetgen/header/dns/question.rb +19 -13
- data/lib/packetgen/header/dns/rr.rb +11 -14
- data/lib/packetgen/header/dns/rrsection.rb +5 -7
- data/lib/packetgen/header/dot11.rb +45 -29
- data/lib/packetgen/header/dot11/control.rb +3 -5
- data/lib/packetgen/header/dot11/data.rb +34 -6
- data/lib/packetgen/header/dot11/element.rb +0 -1
- data/lib/packetgen/header/dot11/management.rb +9 -5
- data/lib/packetgen/header/dot11/sub_mngt.rb +13 -14
- data/lib/packetgen/header/dot1q.rb +2 -2
- data/lib/packetgen/header/dot1x.rb +3 -4
- data/lib/packetgen/header/eap.rb +62 -53
- data/lib/packetgen/header/eap/fast.rb +0 -1
- data/lib/packetgen/header/eap/md5.rb +1 -2
- data/lib/packetgen/header/eap/tls.rb +9 -10
- data/lib/packetgen/header/eap/ttls.rb +9 -10
- data/lib/packetgen/header/esp.rb +33 -33
- data/lib/packetgen/header/eth.rb +11 -8
- data/lib/packetgen/header/gre.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +11 -14
- data/lib/packetgen/header/http/request.rb +20 -20
- data/lib/packetgen/header/http/response.rb +16 -18
- data/lib/packetgen/header/http/verbs.rb +5 -5
- data/lib/packetgen/header/icmp.rb +1 -3
- data/lib/packetgen/header/icmpv6.rb +1 -3
- data/lib/packetgen/header/igmp.rb +5 -6
- data/lib/packetgen/header/igmpv3.rb +5 -9
- data/lib/packetgen/header/igmpv3/group_record.rb +4 -5
- data/lib/packetgen/header/igmpv3/mq.rb +2 -2
- data/lib/packetgen/header/igmpv3/mr.rb +4 -3
- data/lib/packetgen/header/ike.rb +33 -8
- data/lib/packetgen/header/ike/auth.rb +4 -6
- data/lib/packetgen/header/ike/cert.rb +0 -2
- data/lib/packetgen/header/ike/certreq.rb +1 -3
- data/lib/packetgen/header/ike/id.rb +1 -3
- data/lib/packetgen/header/ike/ke.rb +0 -2
- data/lib/packetgen/header/ike/nonce.rb +0 -2
- data/lib/packetgen/header/ike/notify.rb +22 -24
- data/lib/packetgen/header/ike/payload.rb +198 -199
- data/lib/packetgen/header/ike/sa.rb +21 -30
- data/lib/packetgen/header/ike/sk.rb +16 -17
- data/lib/packetgen/header/ike/ts.rb +22 -24
- data/lib/packetgen/header/ike/vendor_id.rb +0 -2
- data/lib/packetgen/header/ip.rb +30 -23
- data/lib/packetgen/header/ip/addr.rb +5 -6
- data/lib/packetgen/header/ip/option.rb +11 -15
- data/lib/packetgen/header/ip/options.rb +1 -2
- data/lib/packetgen/header/ipv6.rb +27 -12
- data/lib/packetgen/header/ipv6/addr.rb +2 -2
- data/lib/packetgen/header/ipv6/extension.rb +1 -1
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +11 -11
- data/lib/packetgen/header/llc.rb +4 -3
- data/lib/packetgen/header/mdns.rb +11 -5
- data/lib/packetgen/header/mld.rb +4 -4
- data/lib/packetgen/header/mldv2.rb +4 -3
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +3 -4
- data/lib/packetgen/header/mldv2/mlq.rb +3 -4
- data/lib/packetgen/header/mldv2/mlr.rb +4 -3
- data/lib/packetgen/header/netbios.rb +18 -5
- data/lib/packetgen/header/ospfv2.rb +6 -7
- data/lib/packetgen/header/ospfv2/db_description.rb +3 -4
- data/lib/packetgen/header/ospfv2/hello.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -14
- data/lib/packetgen/header/ospfv2/lsa_header.rb +4 -5
- data/lib/packetgen/header/ospfv3.rb +3 -4
- data/lib/packetgen/header/ospfv3/db_description.rb +3 -5
- data/lib/packetgen/header/ospfv3/hello.rb +2 -3
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +7 -8
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv3/lsa.rb +10 -11
- data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -4
- data/lib/packetgen/header/snmp.rb +45 -32
- data/lib/packetgen/header/tcp.rb +13 -9
- data/lib/packetgen/header/tcp/option.rb +16 -11
- data/lib/packetgen/header/tcp/options.rb +3 -4
- data/lib/packetgen/header/tftp.rb +15 -17
- data/lib/packetgen/header/udp.rb +10 -4
- data/lib/packetgen/inspect.rb +7 -9
- data/lib/packetgen/packet.rb +44 -22
- data/lib/packetgen/pcapng.rb +1 -5
- data/lib/packetgen/pcapng/block.rb +17 -11
- data/lib/packetgen/pcapng/epb.rb +6 -11
- data/lib/packetgen/pcapng/file.rb +37 -44
- data/lib/packetgen/pcapng/idb.rb +17 -22
- data/lib/packetgen/pcapng/shb.rb +7 -10
- data/lib/packetgen/pcapng/spb.rb +21 -17
- data/lib/packetgen/pcapng/unknown_block.rb +17 -13
- data/lib/packetgen/proto.rb +1 -2
- data/lib/packetgen/types/array.rb +119 -34
- data/lib/packetgen/types/cstring.rb +1 -5
- data/lib/packetgen/types/enum.rb +8 -10
- data/lib/packetgen/types/fields.rb +34 -28
- data/lib/packetgen/types/int.rb +11 -13
- data/lib/packetgen/types/int_string.rb +6 -8
- data/lib/packetgen/types/oui.rb +3 -6
- data/lib/packetgen/types/string.rb +4 -6
- data/lib/packetgen/types/tlv.rb +11 -14
- data/lib/packetgen/utils.rb +15 -23
- data/lib/packetgen/utils/arp_spoofer.rb +12 -18
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +9 -8
- metadata +19 -17
@@ -7,15 +7,17 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# @abstract Base class for all header types.
|
12
11
|
# Subclasses may define magic methods:
|
13
|
-
# * {#
|
12
|
+
# * {#calc_checksum}, which computes header checksum,
|
13
|
+
# * {#calc_length}, which computes header length,
|
14
|
+
# * {#parse?},
|
15
|
+
# * {#reply!}, which inverts needed fields to forge a response.
|
14
16
|
# @author Sylvain Daubert
|
15
17
|
class Base < Types::Fields
|
16
|
-
|
17
18
|
# @api private
|
18
19
|
# Simple class to handle a header association
|
20
|
+
# @deprecated Will be remove with {Base.bind_header}
|
19
21
|
class Binding < Struct.new(:key, :value)
|
20
22
|
# Check +fields+ responds to binding
|
21
23
|
# @param [Types::Fields] fields
|
@@ -49,8 +51,8 @@ module PacketGen
|
|
49
51
|
|
50
52
|
# @api private
|
51
53
|
# Class to handle a header association from procs
|
54
|
+
# @deprecated Will be remove with {Base.bind_header}
|
52
55
|
class ProcBinding
|
53
|
-
|
54
56
|
# @param [Array<Proc>] procs first proc is used to set fields, second proc is
|
55
57
|
# used to check binding
|
56
58
|
def initialize(procs)
|
@@ -84,22 +86,32 @@ module PacketGen
|
|
84
86
|
# @return [Array<Binding>]
|
85
87
|
attr_accessor :bindings
|
86
88
|
|
87
|
-
# @param [:or, :and]
|
88
|
-
def initialize(
|
89
|
-
@op =
|
89
|
+
# @param [:or, :and, :newstyle] operator
|
90
|
+
def initialize(operator)
|
91
|
+
@op = operator
|
90
92
|
@bindings = []
|
91
93
|
end
|
92
94
|
|
95
|
+
def new_set
|
96
|
+
@bindings << [] if @op == :newstyle
|
97
|
+
end
|
98
|
+
|
93
99
|
# @param [Object] arg
|
94
|
-
# @return [
|
100
|
+
# @return [OldBindings] self
|
95
101
|
def <<(arg)
|
96
|
-
|
102
|
+
if op == :newstyle
|
103
|
+
@bindings.last << arg
|
104
|
+
else
|
105
|
+
@bindings << arg
|
106
|
+
end
|
97
107
|
end
|
98
108
|
|
99
109
|
# each iterator
|
100
110
|
# @return [void]
|
101
111
|
def each
|
102
|
-
@bindings.each
|
112
|
+
@bindings.each do |b|
|
113
|
+
yield b
|
114
|
+
end
|
103
115
|
end
|
104
116
|
|
105
117
|
# @return [Boolean]
|
@@ -110,7 +122,13 @@ module PacketGen
|
|
110
122
|
# @return [Hash]
|
111
123
|
def to_h
|
112
124
|
hsh = {}
|
113
|
-
each
|
125
|
+
each do |b|
|
126
|
+
if b.is_a? Array
|
127
|
+
b.each { |sb| hsh[sb.key] = sb.value }
|
128
|
+
else
|
129
|
+
hsh[b.key] = b.value
|
130
|
+
end
|
131
|
+
end
|
114
132
|
hsh
|
115
133
|
end
|
116
134
|
|
@@ -123,6 +141,8 @@ module PacketGen
|
|
123
141
|
empty? || @bindings.any? { |binding| binding.check?(fields) }
|
124
142
|
when :and
|
125
143
|
@bindings.all? { |binding| binding.check?(fields) }
|
144
|
+
when :newstyle
|
145
|
+
@bindings.any? { |group| group.all? { |binding| binding.check?(fields) } }
|
126
146
|
end
|
127
147
|
end
|
128
148
|
|
@@ -130,7 +150,12 @@ module PacketGen
|
|
130
150
|
# @param [Types::Fields] fields
|
131
151
|
# @return [void]
|
132
152
|
def set(fields)
|
133
|
-
@bindings.
|
153
|
+
case @bindings.first
|
154
|
+
when Array
|
155
|
+
@bindings.first.each { |b| b.set fields }
|
156
|
+
else
|
157
|
+
@bindings.each { |b| b.set fields }
|
158
|
+
end
|
134
159
|
end
|
135
160
|
end
|
136
161
|
|
@@ -138,7 +163,7 @@ module PacketGen
|
|
138
163
|
# @return [Packet,nil]
|
139
164
|
attr_reader :packet
|
140
165
|
|
141
|
-
# On inheritage, create +@
|
166
|
+
# On inheritage, create +@old_known_header+ class variable
|
142
167
|
# @param [Class] klass
|
143
168
|
# @return [void]
|
144
169
|
def self.inherited(klass)
|
@@ -155,20 +180,22 @@ module PacketGen
|
|
155
180
|
# ->(hdr) { hdr.field1 == 1 && hdr.body[0..1] == "\x00\x00" }]
|
156
181
|
# @param [Class] header_klass header class to bind to current class
|
157
182
|
# @param [Hash] args current class fields and their value when +header_klass+
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
183
|
+
# is embedded in current class. Given value may be a lambda, whose alone argument
|
184
|
+
# is the value extracted from header field (or +nil+ when lambda is used to set
|
185
|
+
# field while adding a header).
|
186
|
+
#
|
187
|
+
# If multiple fields are given, a special key +:op+ may be given to set parse
|
188
|
+
# operation on this binding. By default, +:op+ is +:or+ (at least one binding
|
189
|
+
# must match to parse it). It also may be set to +:and+ (all bindings must match
|
190
|
+
# to parse it).
|
161
191
|
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
# to parse it).
|
166
|
-
#
|
167
|
-
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
168
|
-
# fields, the former to check bindings. This may be used when multiple and
|
169
|
-
# non-trivial checks should be made.
|
192
|
+
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
193
|
+
# fields, the latter to check bindings. This may be used when multiple and
|
194
|
+
# non-trivial checks should be made.
|
170
195
|
# @return [void]
|
196
|
+
# @deprecated Use {.bind} instead.
|
171
197
|
def self.bind_header(header_klass, args={})
|
198
|
+
Deprecation.deprecated(self, __method__, 'bind', klass_method: true)
|
172
199
|
op = args.delete(:op) || :or
|
173
200
|
if @known_headers[header_klass].nil? || @known_headers[header_klass].op != op
|
174
201
|
bindings = Bindings.new(op)
|
@@ -177,11 +204,57 @@ module PacketGen
|
|
177
204
|
bindings = @known_headers[header_klass]
|
178
205
|
end
|
179
206
|
args.each do |key, value|
|
180
|
-
if key == :procs
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
207
|
+
bindings << if key == :procs
|
208
|
+
ProcBinding.new(value)
|
209
|
+
else
|
210
|
+
Binding.new(key, value)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Bind a upper header to current one.
|
216
|
+
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
217
|
+
# Header1.bind Header2, field1: 42
|
218
|
+
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
219
|
+
# # and field2 has value 43 or 44
|
220
|
+
# Header1.bind Header3, field1: 43, field2: 43
|
221
|
+
# Header1.bind Header3, field1: 43, field2: 44
|
222
|
+
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
223
|
+
# # greater or equal to 44. When adding a Header2 to a Header1
|
224
|
+
# # with Packet#add, force value to 44.
|
225
|
+
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
226
|
+
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
227
|
+
# # and first two bytes of header1's body are null.
|
228
|
+
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
229
|
+
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
230
|
+
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
231
|
+
# @param [Class] header_klass header class to bind to current class
|
232
|
+
# @param [Hash] args current class fields and their value when +header_klass+
|
233
|
+
# is embedded in current class.
|
234
|
+
#
|
235
|
+
# Given value may be a lambda, whose alone argument is the value extracted
|
236
|
+
# from header field (or +nil+ when lambda is used to set field while adding
|
237
|
+
# a header).
|
238
|
+
#
|
239
|
+
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
240
|
+
# fields, the latter to check bindings. This may be used when multiple and
|
241
|
+
# non-trivial checks should be made.
|
242
|
+
# @return [void]
|
243
|
+
# @since 2.7.0
|
244
|
+
def self.bind(header_klass, args={})
|
245
|
+
if @known_headers[header_klass].nil?
|
246
|
+
bindings = Bindings.new(:newstyle)
|
247
|
+
@known_headers[header_klass] = bindings
|
248
|
+
else
|
249
|
+
bindings = @known_headers[header_klass]
|
250
|
+
end
|
251
|
+
bindings.new_set
|
252
|
+
args.each do |key, value|
|
253
|
+
bindings << if key == :procs
|
254
|
+
ProcBinding.new(value)
|
255
|
+
else
|
256
|
+
Binding.new(key, value)
|
257
|
+
end
|
185
258
|
end
|
186
259
|
end
|
187
260
|
|
@@ -189,7 +262,7 @@ module PacketGen
|
|
189
262
|
# @return [String]
|
190
263
|
# @since 2.0.0
|
191
264
|
def self.protocol_name
|
192
|
-
|
265
|
+
new.protocol_name
|
193
266
|
end
|
194
267
|
|
195
268
|
# Helper method to calculate length of +hdr+ and set its +length+ field.
|
@@ -207,7 +280,7 @@ module PacketGen
|
|
207
280
|
end
|
208
281
|
|
209
282
|
# @api private
|
210
|
-
# Get
|
283
|
+
# Get known headers
|
211
284
|
# @return [Hash] keys: header classes, values: hashes
|
212
285
|
def self.known_headers
|
213
286
|
@known_headers
|
@@ -253,14 +326,13 @@ module PacketGen
|
|
253
326
|
added_to_packet(packet)
|
254
327
|
@packet
|
255
328
|
end
|
256
|
-
|
329
|
+
|
257
330
|
# @abstract This method is called when a header is added to a packet.
|
258
331
|
# This base method does nothing but may be overriden by subclasses.
|
259
332
|
# @param [Packet] packet packet to which self is added
|
260
333
|
# @return [void]
|
261
334
|
# @since 2.1.4
|
262
|
-
def added_to_packet(packet)
|
263
|
-
end
|
335
|
+
def added_to_packet(packet) end
|
264
336
|
|
265
337
|
# @api private
|
266
338
|
# Get +header+ id in packet headers array
|
@@ -284,7 +356,7 @@ module PacketGen
|
|
284
356
|
# @raise FormatError +header+ not in a packet
|
285
357
|
def ip_header(header)
|
286
358
|
hid = header_id(header)
|
287
|
-
iph = packet.headers[0...hid].reverse.find { |h| h.is_a?
|
359
|
+
iph = packet.headers[0...hid].reverse.find { |h| h.is_a?(IP) || h.is_a?(IPv6) }
|
288
360
|
raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
|
289
361
|
iph
|
290
362
|
end
|
@@ -297,7 +369,7 @@ module PacketGen
|
|
297
369
|
# @raise FormatError +header+ not in a packet
|
298
370
|
def ll_header(header)
|
299
371
|
hid = header_id(header)
|
300
|
-
llh = packet.headers[0...hid].reverse.find { |h| h.is_a?
|
372
|
+
llh = packet.headers[0...hid].reverse.find { |h| h.is_a?(Eth) || h.is_a?(Dot11) }
|
301
373
|
raise FormatError, 'no link layer header in packet' if llh.nil?
|
302
374
|
llh
|
303
375
|
end
|
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# Bootstrap Protocol, {https://tools.ietf.org/html/rfc951
|
12
11
|
# RFC 951}
|
13
12
|
#
|
@@ -40,15 +39,14 @@ module PacketGen
|
|
40
39
|
# @author Sylvain Daubert
|
41
40
|
# @since 2.2.0
|
42
41
|
class BOOTP < Base
|
43
|
-
|
44
42
|
UDP_SERVER_PORT = 67
|
45
43
|
UDP_CLIENT_PORT = 68
|
46
|
-
|
44
|
+
|
47
45
|
# DHCP opcodes
|
48
46
|
OPCODES = {
|
49
47
|
'BOOTREQUEST' => 1,
|
50
48
|
'BOOTREPLY' => 2
|
51
|
-
}
|
49
|
+
}.freeze
|
52
50
|
|
53
51
|
# @!attribute op
|
54
52
|
# 8-bit opcode
|
@@ -73,13 +71,13 @@ module PacketGen
|
|
73
71
|
# 32-bit Transaction ID
|
74
72
|
# @return [Integer]
|
75
73
|
define_field :xid, Types::Int32
|
76
|
-
|
74
|
+
|
77
75
|
# @!attribute secs
|
78
76
|
# 16-bit integer: number of seconds elapsed since client began address
|
79
77
|
# acquisition or renewal process
|
80
78
|
# @return [Integer]
|
81
79
|
define_field :secs, Types::Int16
|
82
|
-
|
80
|
+
|
83
81
|
# @!attribute flags
|
84
82
|
# 16-bit flag field
|
85
83
|
# @return [Integer]
|
@@ -94,17 +92,17 @@ module PacketGen
|
|
94
92
|
# 'your' (client) IP address
|
95
93
|
# @return [String]
|
96
94
|
define_field :yiaddr, IP::Addr
|
97
|
-
|
95
|
+
|
98
96
|
# @!attribute siaddr
|
99
97
|
# IP address of next server to use in bootstrap
|
100
98
|
# @return [String]
|
101
99
|
define_field :siaddr, IP::Addr
|
102
|
-
|
100
|
+
|
103
101
|
# @!attribute giaddr
|
104
102
|
# Relay agent IP address, used in booting via a relay agent
|
105
103
|
# @return [String]
|
106
104
|
define_field :giaddr, IP::Addr
|
107
|
-
|
105
|
+
|
108
106
|
# @!attribute chaddr
|
109
107
|
# client hardware address
|
110
108
|
# @return [String]
|
@@ -123,7 +121,7 @@ module PacketGen
|
|
123
121
|
# @!attribute body
|
124
122
|
# @return [String]
|
125
123
|
define_field :body, Types::String
|
126
|
-
|
124
|
+
|
127
125
|
# @!attribute b
|
128
126
|
# Broadcast flag, from {#flags}
|
129
127
|
# @return [Boolean]
|
@@ -131,23 +129,34 @@ module PacketGen
|
|
131
129
|
# 15-bit Must Be Zero bits, from {#flags}
|
132
130
|
# @return [Boolean]
|
133
131
|
define_bit_fields_on :flags, :b, :mbz, 15
|
134
|
-
|
132
|
+
|
133
|
+
# @return [String]
|
135
134
|
def inspect
|
136
135
|
str = Inspect.dashed_line(self.class, 2)
|
137
136
|
fields.each do |attr|
|
138
137
|
next if attr == :body
|
139
138
|
next unless is_present?(attr)
|
140
|
-
if attr == :chaddr
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
139
|
+
str << if (attr == :chaddr) && (self.hlen == 6)
|
140
|
+
Inspect.inspect_attribute(attr, Eth::MacAddr.new.read(self[:chaddr][0, 6]), 2)
|
141
|
+
else
|
142
|
+
Inspect.inspect_attribute(attr, self[attr], 2)
|
143
|
+
end
|
145
144
|
end
|
146
145
|
str
|
147
146
|
end
|
147
|
+
|
148
|
+
# Invert opcode, if known
|
149
|
+
# @return [self]
|
150
|
+
def reply!
|
151
|
+
case self.op
|
152
|
+
when 1 then self.op = 2
|
153
|
+
when 2 then self.op = 1
|
154
|
+
end
|
155
|
+
self
|
156
|
+
end
|
148
157
|
end
|
149
|
-
|
150
|
-
UDP.
|
151
|
-
UDP.
|
158
|
+
|
159
|
+
UDP.bind BOOTP, sport: 67, dport: 68
|
160
|
+
UDP.bind BOOTP, sport: 68, dport: 67
|
152
161
|
end
|
153
162
|
end
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
module PacketGen
|
4
4
|
module Header
|
5
|
-
|
6
5
|
# Mixin for cryptographic classes
|
7
6
|
# @api private
|
8
7
|
# @author Sylvain Daubert
|
9
8
|
module Crypto
|
10
|
-
|
11
9
|
# Cryptographic error
|
12
10
|
class Error < PacketGen::Error; end
|
13
11
|
|
@@ -16,11 +14,11 @@ module PacketGen
|
|
16
14
|
# @param [OpenSSL::HMAC] intg
|
17
15
|
# @return [void]
|
18
16
|
def set_crypto(conf, intg)
|
19
|
-
@conf
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
@conf = conf
|
18
|
+
@intg = intg
|
19
|
+
return unless conf.authenticated?
|
20
|
+
# #auth_tag_len only supported from ruby 2.4.0
|
21
|
+
@conf.auth_tag_len = @trunc if @conf.respond_to? :auth_tag_len
|
24
22
|
end
|
25
23
|
|
26
24
|
# Get confidentiality mode name
|
@@ -34,7 +32,7 @@ module PacketGen
|
|
34
32
|
# Say if crypto modes permit authentication
|
35
33
|
# @return [Boolean]
|
36
34
|
def authenticated?
|
37
|
-
@conf.authenticated?
|
35
|
+
@conf.authenticated? || !@intg.nil?
|
38
36
|
end
|
39
37
|
|
40
38
|
def authenticate!
|
@@ -7,8 +7,7 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
|
-
# Dynamic Host Configuration Protocol, {https://tools.ietf.org/html/rfc2131
|
10
|
+
# Dynamic Host Configuration Protocol, {https://tools.ietf.org/html/rfc2131
|
12
11
|
# RFC 2131}
|
13
12
|
#
|
14
13
|
# A DHCP header is quite simple. It is composed of:
|
@@ -54,14 +53,14 @@ module PacketGen
|
|
54
53
|
# @!attribute options
|
55
54
|
# @return [DHCP::Options]
|
56
55
|
define_field :options, DHCP::Options
|
57
|
-
|
56
|
+
|
58
57
|
# differentiate from BOOTP by checking presence of DHCP magic
|
59
58
|
# @return [Boolean]
|
60
59
|
def parse?
|
61
60
|
self.magic == DHCP_MAGIC
|
62
61
|
end
|
63
62
|
end
|
64
|
-
|
65
|
-
BOOTP.
|
63
|
+
|
64
|
+
BOOTP.bind DHCP
|
66
65
|
end
|
67
66
|
end
|
@@ -5,15 +5,14 @@
|
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
7
7
|
|
8
|
-
|
9
8
|
module PacketGen
|
10
9
|
module Header
|
11
10
|
class DHCP
|
12
|
-
|
13
11
|
# define DHCP Options.
|
14
12
|
# keys are option type, value are arrays containing option names
|
15
13
|
# as strings, and a hash passed to {Option#initialize}.
|
16
|
-
|
14
|
+
# @since 2.7.0
|
15
|
+
DHCP_OPTIONS = {
|
17
16
|
1 => ['subnet_mask', length: 4, v: IP::Addr],
|
18
17
|
2 => ['time_zone'],
|
19
18
|
3 => ['router', length: 4, v: IP::Addr],
|
@@ -37,14 +36,14 @@ module PacketGen
|
|
37
36
|
44 => ['NetBIOS_server', length: 4, v: IP::Addr],
|
38
37
|
45 => ['NetBIOS_dist_server', length: 4, v: IP::Addr],
|
39
38
|
50 => ['requested_addr', length: 4, v: IP::Addr],
|
40
|
-
51 => ['lease_time', length: 4, v: Types::Int32, value:
|
39
|
+
51 => ['lease_time', length: 4, v: Types::Int32, value: 43_200],
|
41
40
|
53 => ['message-type', length: 1, v: Types::Int8],
|
42
41
|
54 => ['server_id', length: 4, v: IP::Addr],
|
43
42
|
55 => ['param_req_list'],
|
44
43
|
56 => ['error_message'],
|
45
|
-
57 => ['max_dhcp_size', length: 2, v: Types::Int16, value:
|
46
|
-
58 => ['renewal_time', length: 4, v: Types::Int32, value:
|
47
|
-
59 => ['rebinding_time', length: 4, v: Types::Int32, value:
|
44
|
+
57 => ['max_dhcp_size', length: 2, v: Types::Int16, value: 1_500],
|
45
|
+
58 => ['renewal_time', length: 4, v: Types::Int32, value: 21_600],
|
46
|
+
59 => ['rebinding_time', length: 4, v: Types::Int32, value: 37_800],
|
48
47
|
60 => ['vendor_class_id'],
|
49
48
|
61 => ['client_id'],
|
50
49
|
64 => ['NISplus_domain'],
|
@@ -55,14 +54,20 @@ module PacketGen
|
|
55
54
|
72 => ['WWW_server', length: 4, v: IP::Addr],
|
56
55
|
73 => ['finger_server', length: 4, v: IP::Addr],
|
57
56
|
74 => ['IRC_server', length: 4, v: IP::Addr]
|
58
|
-
}
|
57
|
+
}.freeze
|
58
|
+
|
59
|
+
# @deprecated Use {DHCP_OPTIONS} instead.
|
60
|
+
DCHPOptions = DHCP_OPTIONS
|
59
61
|
|
60
62
|
# Class to indicate DHCP options end
|
61
63
|
class End < Types::Int8
|
62
64
|
def initialize(value=255)
|
63
65
|
super
|
64
66
|
end
|
65
|
-
|
67
|
+
|
68
|
+
def to_human
|
69
|
+
self.class.to_s.sub(/.*::/, '').downcase
|
70
|
+
end
|
66
71
|
alias human_type to_human
|
67
72
|
end
|
68
73
|
|
@@ -83,9 +88,8 @@ module PacketGen
|
|
83
88
|
# option).
|
84
89
|
# @author Sylvain Daubert
|
85
90
|
class Option < Types::TLV
|
86
|
-
|
87
91
|
# Option types
|
88
|
-
TYPES = Hash[
|
92
|
+
TYPES = Hash[DHCP_OPTIONS.to_a.map { |type, ary| [type, ary[0]] }]
|
89
93
|
|
90
94
|
# @param [Hash] options
|
91
95
|
# @option options [Integer] :type
|
@@ -93,16 +97,15 @@ module PacketGen
|
|
93
97
|
# @option options [String] :value
|
94
98
|
def initialize(options={})
|
95
99
|
super
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
return unless DHCP_OPTIONS.key?(self.type)
|
101
|
+
h = DHCP_OPTIONS[self.type].last
|
102
|
+
|
103
|
+
return unless h.is_a? Hash
|
104
|
+
h.each do |k, v|
|
105
|
+
self.length = v if k == :length
|
106
|
+
if k == :v
|
107
|
+
self[:value] = v.new
|
108
|
+
self.value = options[:value] if options[:value]
|
106
109
|
end
|
107
110
|
end
|
108
111
|
end
|
@@ -115,24 +118,33 @@ module PacketGen
|
|
115
118
|
# @return [Option,End,Pad] may return another object than itself
|
116
119
|
def read(str)
|
117
120
|
read_type = str[0].unpack('C').first
|
118
|
-
if read_type
|
121
|
+
if read_type.zero?
|
119
122
|
Pad.new.read(str)
|
120
123
|
elsif read_type == 255
|
121
124
|
End.new.read(str)
|
122
|
-
elsif
|
123
|
-
Option.new(
|
125
|
+
elsif DHCP_OPTIONS.key?(read_type)
|
126
|
+
Option.new(DHCP_OPTIONS[read_type][1] || {}).private_read(str)
|
124
127
|
else
|
125
128
|
super
|
126
129
|
end
|
127
130
|
end
|
128
131
|
|
129
|
-
|
132
|
+
# @since 2.7.0
|
133
|
+
# @return [true]
|
134
|
+
def human_types?
|
130
135
|
true
|
131
136
|
end
|
132
137
|
|
138
|
+
# @deprecated Use {#human_types?} instead
|
139
|
+
# @return [true]
|
140
|
+
def has_human_types?
|
141
|
+
Deprecation.deprecated(self.class, __method__, 'human_types?')
|
142
|
+
human_types?
|
143
|
+
end
|
144
|
+
|
133
145
|
def human_type
|
134
|
-
if
|
135
|
-
|
146
|
+
if DHCP_OPTIONS.key?(type)
|
147
|
+
DHCP_OPTIONS[type].first.dup
|
136
148
|
else
|
137
149
|
type.to_s
|
138
150
|
end
|
@@ -141,13 +153,13 @@ module PacketGen
|
|
141
153
|
def to_human
|
142
154
|
s = human_type
|
143
155
|
if length > 0
|
144
|
-
if value.respond_to? :to_human
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
156
|
+
s << if value.respond_to? :to_human
|
157
|
+
":#{value.to_human}"
|
158
|
+
elsif self[:value].is_a? Types::Int
|
159
|
+
":#{self.value.to_i}"
|
160
|
+
else
|
161
|
+
":#{value.inspect}"
|
162
|
+
end
|
151
163
|
end
|
152
164
|
s
|
153
165
|
end
|