packetgen 3.1.3 → 3.1.8
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 +33 -4
- data/lib/packetgen/capture.rb +51 -28
- data/lib/packetgen/config.rb +17 -11
- data/lib/packetgen/deprecation.rb +33 -7
- data/lib/packetgen/header.rb +2 -9
- data/lib/packetgen/header/arp.rb +2 -2
- data/lib/packetgen/header/asn1_base.rb +2 -2
- data/lib/packetgen/header/base.rb +70 -74
- data/lib/packetgen/header/bootp.rb +3 -3
- data/lib/packetgen/header/dhcp.rb +2 -2
- data/lib/packetgen/header/dhcp/option.rb +2 -2
- data/lib/packetgen/header/dhcp/options.rb +2 -2
- data/lib/packetgen/header/dhcpv6.rb +12 -12
- data/lib/packetgen/header/dhcpv6/duid.rb +11 -5
- data/lib/packetgen/header/dhcpv6/option.rb +8 -16
- data/lib/packetgen/header/dhcpv6/options.rb +2 -2
- data/lib/packetgen/header/dhcpv6/relay.rb +2 -2
- data/lib/packetgen/header/dns.rb +9 -9
- data/lib/packetgen/header/dns/name.rb +20 -9
- data/lib/packetgen/header/dns/opt.rb +2 -2
- data/lib/packetgen/header/dns/option.rb +2 -2
- data/lib/packetgen/header/dns/qdsection.rb +3 -3
- data/lib/packetgen/header/dns/question.rb +37 -35
- data/lib/packetgen/header/dns/rr.rb +3 -3
- data/lib/packetgen/header/dns/rrsection.rb +2 -2
- data/lib/packetgen/header/dot11.rb +30 -51
- data/lib/packetgen/header/dot11/control.rb +5 -5
- data/lib/packetgen/header/dot11/data.rb +11 -7
- data/lib/packetgen/header/dot11/element.rb +16 -16
- data/lib/packetgen/header/dot11/management.rb +2 -2
- data/lib/packetgen/header/dot11/sub_mngt.rb +2 -12
- data/lib/packetgen/header/dot1q.rb +2 -2
- data/lib/packetgen/header/dot1x.rb +7 -20
- data/lib/packetgen/header/eap.rb +30 -33
- data/lib/packetgen/header/eap/fast.rb +2 -2
- data/lib/packetgen/header/eap/md5.rb +2 -2
- data/lib/packetgen/header/eap/tls.rb +2 -2
- data/lib/packetgen/header/eap/ttls.rb +2 -2
- data/lib/packetgen/header/eth.rb +13 -11
- data/lib/packetgen/header/gre.rb +2 -2
- data/lib/packetgen/header/http.rb +2 -0
- data/lib/packetgen/header/http/headers.rb +6 -4
- data/lib/packetgen/header/http/request.rb +36 -21
- data/lib/packetgen/header/http/response.rb +7 -7
- data/lib/packetgen/header/http/verbs.rb +3 -3
- data/lib/packetgen/header/icmp.rb +2 -2
- data/lib/packetgen/header/icmpv6.rb +2 -2
- data/lib/packetgen/header/igmp.rb +4 -4
- data/lib/packetgen/header/igmpv3.rb +3 -3
- data/lib/packetgen/header/igmpv3/group_record.rb +8 -6
- data/lib/packetgen/header/igmpv3/mq.rb +2 -2
- data/lib/packetgen/header/igmpv3/mr.rb +2 -2
- data/lib/packetgen/header/ip.rb +30 -31
- data/lib/packetgen/header/ip/addr.rb +10 -3
- data/lib/packetgen/header/ip/option.rb +8 -10
- data/lib/packetgen/header/ip/options.rb +3 -5
- data/lib/packetgen/header/ipv6.rb +2 -2
- data/lib/packetgen/header/ipv6/addr.rb +9 -2
- data/lib/packetgen/header/ipv6/extension.rb +2 -2
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +3 -3
- data/lib/packetgen/header/llc.rb +2 -2
- data/lib/packetgen/header/mdns.rb +2 -2
- data/lib/packetgen/header/mld.rb +2 -2
- data/lib/packetgen/header/mldv2.rb +2 -2
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +4 -2
- data/lib/packetgen/header/mldv2/mlq.rb +2 -2
- data/lib/packetgen/header/mldv2/mlr.rb +2 -2
- data/lib/packetgen/header/ospfv2.rb +9 -9
- data/lib/packetgen/header/ospfv2/db_description.rb +2 -2
- data/lib/packetgen/header/ospfv2/hello.rb +2 -2
- data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -2
- data/lib/packetgen/header/ospfv2/ls_request.rb +4 -2
- data/lib/packetgen/header/ospfv2/ls_update.rb +2 -2
- data/lib/packetgen/header/ospfv2/lsa.rb +9 -5
- data/lib/packetgen/header/ospfv2/lsa_header.rb +8 -7
- data/lib/packetgen/header/ospfv3.rb +2 -2
- data/lib/packetgen/header/ospfv3/db_description.rb +2 -2
- data/lib/packetgen/header/ospfv3/hello.rb +2 -2
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +4 -2
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
- data/lib/packetgen/header/ospfv3/ls_request.rb +4 -2
- data/lib/packetgen/header/ospfv3/ls_update.rb +2 -2
- data/lib/packetgen/header/ospfv3/lsa.rb +5 -5
- data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -8
- data/lib/packetgen/header/snmp.rb +33 -29
- data/lib/packetgen/header/tcp.rb +4 -23
- data/lib/packetgen/header/tcp/option.rb +11 -11
- data/lib/packetgen/header/tcp/options.rb +2 -2
- data/lib/packetgen/header/tftp.rb +6 -6
- data/lib/packetgen/header/udp.rb +3 -3
- data/lib/packetgen/headerable.rb +5 -4
- data/lib/packetgen/inject.rb +23 -0
- data/lib/packetgen/inspect.rb +23 -20
- data/lib/packetgen/packet.rb +82 -53
- data/lib/packetgen/pcap.rb +29 -0
- data/lib/packetgen/pcapng.rb +13 -13
- data/lib/packetgen/pcapng/block.rb +26 -13
- data/lib/packetgen/pcapng/epb.rb +25 -22
- data/lib/packetgen/pcapng/file.rb +260 -138
- data/lib/packetgen/pcapng/idb.rb +36 -38
- data/lib/packetgen/pcapng/shb.rb +51 -53
- data/lib/packetgen/pcapng/spb.rb +19 -19
- data/lib/packetgen/pcapng/unknown_block.rb +5 -13
- data/lib/packetgen/pcaprub_wrapper.rb +81 -0
- data/lib/packetgen/proto.rb +2 -2
- data/lib/packetgen/types.rb +3 -0
- data/lib/packetgen/types/abstract_tlv.rb +27 -7
- data/lib/packetgen/types/array.rb +22 -15
- data/lib/packetgen/types/cstring.rb +57 -20
- data/lib/packetgen/types/enum.rb +7 -2
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +182 -117
- data/lib/packetgen/types/int.rb +18 -6
- data/lib/packetgen/types/int_string.rb +10 -2
- data/lib/packetgen/types/length_from.rb +20 -12
- data/lib/packetgen/types/oui.rb +4 -2
- data/lib/packetgen/types/string.rb +59 -8
- data/lib/packetgen/types/tlv.rb +4 -2
- data/lib/packetgen/utils.rb +4 -4
- data/lib/packetgen/utils/arp_spoofer.rb +2 -2
- data/lib/packetgen/version.rb +3 -3
- metadata +39 -61
- data/.gitignore +0 -13
- data/.rubocop.yml +0 -30
- data/.travis.yml +0 -19
- data/Gemfile +0 -4
- data/Rakefile +0 -21
- data/packetgen.gemspec +0 -36
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of PacketGen
|
2
4
|
# See https://github.com/sdaubert/packetgen for more informations
|
3
5
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
6
|
# This program is published under MIT license.
|
5
7
|
|
6
|
-
#
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
7
9
|
|
8
10
|
module PacketGen
|
9
11
|
module Types
|
@@ -13,8 +15,7 @@ module PacketGen
|
|
13
15
|
#
|
14
16
|
# == Basics
|
15
17
|
# A {Fields} subclass is generaly composed of multiple binary fields. These fields
|
16
|
-
# have each a given type. All
|
17
|
-
# {Fields} subclasses may also be used as field type.
|
18
|
+
# have each a given type. All {Fieldable} types are supported.
|
18
19
|
#
|
19
20
|
# To define a new subclass, it has to inherit from {Fields}. And some class
|
20
21
|
# methods have to be used to declare attributes/fields:
|
@@ -119,17 +120,23 @@ module PacketGen
|
|
119
120
|
# @return [Hash]
|
120
121
|
# @since 3.1.0
|
121
122
|
attr_reader :field_defs
|
123
|
+
# Get bit fields defintions for this class
|
124
|
+
# @return [Hash]
|
125
|
+
# @since 3.1.5
|
126
|
+
attr_reader :bit_fields
|
122
127
|
|
123
128
|
# On inheritage, create +@field_defs+ class variable
|
124
129
|
# @param [Class] klass
|
125
130
|
# @return [void]
|
126
131
|
def inherited(klass)
|
132
|
+
super
|
133
|
+
|
127
134
|
field_defs = {}
|
128
135
|
@field_defs.each do |k, v|
|
129
136
|
field_defs[k] = v.clone
|
130
137
|
end
|
131
138
|
ordered = @ordered_fields.clone
|
132
|
-
bf =
|
139
|
+
bf = bit_fields.clone
|
133
140
|
|
134
141
|
klass.class_eval do
|
135
142
|
@ordered_fields = ordered
|
@@ -158,7 +165,7 @@ module PacketGen
|
|
158
165
|
# bs[value1] # => Types::Int8
|
159
166
|
# bs.value1 # => Integer
|
160
167
|
# @param [Symbol] name field name
|
161
|
-
# @param [
|
168
|
+
# @param [Fieldable] type class or instance
|
162
169
|
# @param [Hash] options Unrecognized options are passed to object builder if
|
163
170
|
# +:builder+ option is not set.
|
164
171
|
# @option options [Object] :default default value. May be a proc. This lambda
|
@@ -172,44 +179,22 @@ module PacketGen
|
|
172
179
|
# Define enumeration: hash's keys are +String+, and values are +Integer+.
|
173
180
|
# @return [void]
|
174
181
|
def define_field(name, type, options={})
|
175
|
-
|
176
|
-
if type < Types::Enum
|
177
|
-
define << "def #{name}; self[:#{name}].to_i; end"
|
178
|
-
define << "def #{name}=(val) self[:#{name}].value = val; end"
|
179
|
-
else
|
180
|
-
define << "def #{name}\n" \
|
181
|
-
" if self[:#{name}].respond_to?(:to_human) && self[:#{name}].respond_to?(:from_human)\n" \
|
182
|
-
" self[:#{name}].to_human\n" \
|
183
|
-
" else\n" \
|
184
|
-
" self[:#{name}]\n" \
|
185
|
-
" end\n" \
|
186
|
-
"end"
|
187
|
-
define << "def #{name}=(val)\n" \
|
188
|
-
" if self[:#{name}].respond_to?(:to_human) && self[:#{name}].respond_to?(:from_human)\n" \
|
189
|
-
" self[:#{name}].from_human val\n" \
|
190
|
-
" else\n" \
|
191
|
-
" self[:#{name}].read val\n" \
|
192
|
-
" end\n" \
|
193
|
-
"end"
|
194
|
-
end
|
195
|
-
|
196
|
-
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
197
|
-
define.delete_at(0) if instance_methods.include? name
|
198
|
-
class_eval define.join("\n")
|
182
|
+
fields << name
|
199
183
|
field_defs[name] = FieldDef.new(type,
|
200
184
|
options.delete(:default),
|
201
185
|
options.delete(:builder),
|
202
186
|
options.delete(:optional),
|
203
187
|
options.delete(:enum),
|
204
188
|
options)
|
205
|
-
|
189
|
+
|
190
|
+
add_methods(name, type)
|
206
191
|
end
|
207
192
|
|
208
193
|
# Define a field, before another one
|
209
194
|
# @param [Symbol,nil] other field name to create a new one before. If +nil+,
|
210
195
|
# new field is appended.
|
211
196
|
# @param [Symbol] name field name to create
|
212
|
-
# @param [
|
197
|
+
# @param [Fieldable] type class or instance
|
213
198
|
# @param [Hash] options See {.define_field}.
|
214
199
|
# @return [void]
|
215
200
|
# @see .define_field
|
@@ -228,7 +213,7 @@ module PacketGen
|
|
228
213
|
# @param [Symbol,nil] other field name to create a new one after. If +nil+,
|
229
214
|
# new field is appended.
|
230
215
|
# @param [Symbol] name field name to create
|
231
|
-
# @param [
|
216
|
+
# @param [Fieldable] type class or instance
|
232
217
|
# @param [Hash] options See {.define_field}.
|
233
218
|
# @return [void]
|
234
219
|
# @see .define_field
|
@@ -262,12 +247,12 @@ module PacketGen
|
|
262
247
|
# @raise [ArgumentError] unknown +field+
|
263
248
|
# @since 2.8.4
|
264
249
|
def update_field(field, options)
|
265
|
-
|
250
|
+
check_existence_of field
|
251
|
+
|
252
|
+
%i[default builder optional enum].each do |property|
|
253
|
+
field_defs_property_from(field, property, options)
|
254
|
+
end
|
266
255
|
|
267
|
-
field_defs[field].default = options.delete(:default) if options.key?(:default)
|
268
|
-
field_defs[field].builder = options.delete(:builder) if options.key?(:builder)
|
269
|
-
field_defs[field].optional = options.delete(:optional) if options.key?(:optional)
|
270
|
-
field_defs[field].enum = options.delete(:enum) if options.key?(:enum)
|
271
256
|
field_defs[field].options.merge!(options)
|
272
257
|
end
|
273
258
|
|
@@ -289,63 +274,29 @@ module PacketGen
|
|
289
274
|
# subclass)
|
290
275
|
# @param [Array] args list of bitfield names. Name may be followed
|
291
276
|
# by bitfield size. If no size is given, 1 bit is assumed.
|
277
|
+
# @raise [ArgumentError] unknown +attr+
|
292
278
|
# @return [void]
|
293
279
|
def define_bit_fields_on(attr, *args)
|
294
|
-
|
295
|
-
raise ArgumentError, "unknown #{attr} field" if attr_def.nil?
|
280
|
+
check_existence_of attr
|
296
281
|
|
297
|
-
type =
|
298
|
-
unless type < Types::Int
|
299
|
-
raise TypeError, "#{attr} is not a PacketGen::Types::Int"
|
300
|
-
end
|
282
|
+
type = field_defs[attr].type
|
283
|
+
raise TypeError, "#{attr} is not a PacketGen::Types::Int" unless type < Types::Int
|
301
284
|
|
302
285
|
total_size = type.new.width * 8
|
303
286
|
idx = total_size - 1
|
304
287
|
|
305
|
-
|
306
|
-
|
288
|
+
until args.empty?
|
289
|
+
field = args.shift
|
307
290
|
next unless field.is_a? Symbol
|
308
291
|
|
309
|
-
size =
|
310
|
-
|
311
|
-
else
|
312
|
-
1
|
313
|
-
end
|
292
|
+
size = size_from(args)
|
293
|
+
|
314
294
|
unless field == :_
|
315
|
-
|
316
|
-
|
317
|
-
clear_mask = (2**total_size - 1) & (~field_mask & (2**total_size - 1))
|
318
|
-
|
319
|
-
if size == 1
|
320
|
-
class_eval <<-METHODS
|
321
|
-
def #{field}?
|
322
|
-
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
323
|
-
val != 0
|
324
|
-
end
|
325
|
-
def #{field}=(v)
|
326
|
-
val = v ? 1 : 0
|
327
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
328
|
-
self[:#{attr}].value |= val << #{shift}
|
329
|
-
end
|
330
|
-
METHODS
|
331
|
-
else
|
332
|
-
class_eval <<-METHODS
|
333
|
-
def #{field}
|
334
|
-
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
335
|
-
end
|
336
|
-
def #{field}=(v)
|
337
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
338
|
-
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
339
|
-
end
|
340
|
-
METHODS
|
341
|
-
end
|
342
|
-
|
343
|
-
@bit_fields[attr] = {} if @bit_fields[attr].nil?
|
344
|
-
@bit_fields[attr][field] = size
|
295
|
+
add_bit_methods(attr, field, size, total_size, idx)
|
296
|
+
register_bit_field_size(attr, field, size)
|
345
297
|
end
|
346
298
|
|
347
299
|
idx -= size
|
348
|
-
field = args.shift
|
349
300
|
end
|
350
301
|
end
|
351
302
|
|
@@ -354,7 +305,7 @@ module PacketGen
|
|
354
305
|
# @return [void]
|
355
306
|
# @since 2.8.4
|
356
307
|
def remove_bit_fields_on(attr)
|
357
|
-
fields =
|
308
|
+
fields = bit_fields.delete(attr)
|
358
309
|
return if fields.nil?
|
359
310
|
|
360
311
|
fields.each do |field, size|
|
@@ -362,6 +313,98 @@ module PacketGen
|
|
362
313
|
undef_method(size == 1 ? "#{field}?" : field)
|
363
314
|
end
|
364
315
|
end
|
316
|
+
|
317
|
+
private
|
318
|
+
|
319
|
+
def add_methods(name, type)
|
320
|
+
define = []
|
321
|
+
if type < Types::Enum
|
322
|
+
define << "def #{name}; self[:#{name}].to_i; end"
|
323
|
+
define << "def #{name}=(val) self[:#{name}].value = val; end"
|
324
|
+
else
|
325
|
+
define << "def #{name}\n" \
|
326
|
+
" to_and_from_human?(:#{name}) ? self[:#{name}].to_human : self[:#{name}]\n" \
|
327
|
+
'end'
|
328
|
+
define << "def #{name}=(val)\n" \
|
329
|
+
" to_and_from_human?(:#{name}) ? self[:#{name}].from_human(val) : self[:#{name}].read(val)\n" \
|
330
|
+
'end'
|
331
|
+
end
|
332
|
+
|
333
|
+
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
334
|
+
define.delete_at(0) if instance_methods.include? name
|
335
|
+
class_eval define.join("\n")
|
336
|
+
end
|
337
|
+
|
338
|
+
def add_bit_methods(attr, name, size, total_size, idx)
|
339
|
+
shift = idx - (size - 1)
|
340
|
+
|
341
|
+
if size == 1
|
342
|
+
add_single_bit_methods(attr, name, size, total_size, shift)
|
343
|
+
else
|
344
|
+
add_multibit_methods(attr, name, size, total_size, shift)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def compute_field_mask(size, shift)
|
349
|
+
(2**size - 1) << shift
|
350
|
+
end
|
351
|
+
|
352
|
+
def compute_clear_mask(total_size, field_mask)
|
353
|
+
(2**total_size - 1) & (~field_mask & (2**total_size - 1))
|
354
|
+
end
|
355
|
+
|
356
|
+
def add_single_bit_methods(attr, name, size, total_size, shift)
|
357
|
+
field_mask = compute_field_mask(size, shift)
|
358
|
+
clear_mask = compute_clear_mask(total_size, field_mask)
|
359
|
+
|
360
|
+
class_eval <<-METHODS
|
361
|
+
def #{name}?
|
362
|
+
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
363
|
+
val != 0
|
364
|
+
end
|
365
|
+
def #{name}=(v)
|
366
|
+
val = v ? 1 : 0
|
367
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
368
|
+
self[:#{attr}].value |= val << #{shift}
|
369
|
+
end
|
370
|
+
METHODS
|
371
|
+
end
|
372
|
+
|
373
|
+
def add_multibit_methods(attr, name, size, total_size, shift)
|
374
|
+
field_mask = compute_field_mask(size, shift)
|
375
|
+
clear_mask = compute_clear_mask(total_size, field_mask)
|
376
|
+
|
377
|
+
class_eval <<-METHODS
|
378
|
+
def #{name}
|
379
|
+
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
380
|
+
end
|
381
|
+
def #{name}=(v)
|
382
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
383
|
+
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
384
|
+
end
|
385
|
+
METHODS
|
386
|
+
end
|
387
|
+
|
388
|
+
def register_bit_field_size(attr, field, size)
|
389
|
+
bit_fields[attr] = {} if bit_fields[attr].nil?
|
390
|
+
bit_fields[attr][field] = size
|
391
|
+
end
|
392
|
+
|
393
|
+
def field_defs_property_from(field, property, options)
|
394
|
+
field_defs[field].send("#{property}=", options.delete(property)) if options.key?(property)
|
395
|
+
end
|
396
|
+
|
397
|
+
def size_from(args)
|
398
|
+
if args.first.is_a? Integer
|
399
|
+
args.shift
|
400
|
+
else
|
401
|
+
1
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def check_existence_of(field)
|
406
|
+
raise ArgumentError, "unknown #{field} field for #{self}" unless field_defs.key?(field)
|
407
|
+
end
|
365
408
|
end
|
366
409
|
|
367
410
|
# Create a new fields object
|
@@ -371,36 +414,13 @@ module PacketGen
|
|
371
414
|
@fields = {}
|
372
415
|
@optional_fields = {}
|
373
416
|
|
374
|
-
field_defs = self.class.field_defs
|
375
417
|
self.class.fields.each do |field|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
builder = field_defs[field].builder
|
380
|
-
optional = field_defs[field].optional
|
381
|
-
enum = field_defs[field].enum
|
382
|
-
field_options = field_defs[field].options
|
383
|
-
|
384
|
-
@fields[field] = if builder
|
385
|
-
builder.call(self, type)
|
386
|
-
elsif enum
|
387
|
-
type.new(enum)
|
388
|
-
elsif !field_options.empty?
|
389
|
-
type.new(field_options)
|
390
|
-
else
|
391
|
-
type.new
|
392
|
-
end
|
393
|
-
|
394
|
-
value = options[field] || default
|
395
|
-
if value.class <= type
|
396
|
-
@fields[field] = value
|
397
|
-
elsif @fields[field].respond_to? :from_human
|
398
|
-
@fields[field].from_human(value)
|
399
|
-
end
|
400
|
-
|
401
|
-
@optional_fields[field] = optional if optional
|
418
|
+
build_field field
|
419
|
+
initialize_value field, options[field]
|
420
|
+
initialize_optional field
|
402
421
|
end
|
403
|
-
|
422
|
+
|
423
|
+
self.class.bit_fields.each do |_, hsh|
|
404
424
|
hsh.each_key do |bit_field|
|
405
425
|
self.send "#{bit_field}=", options[bit_field] if options[bit_field]
|
406
426
|
end
|
@@ -409,7 +429,7 @@ module PacketGen
|
|
409
429
|
|
410
430
|
# Get field object
|
411
431
|
# @param [Symbol] field
|
412
|
-
# @return [
|
432
|
+
# @return [Fieldable]
|
413
433
|
def [](field)
|
414
434
|
@fields[field]
|
415
435
|
end
|
@@ -429,6 +449,7 @@ module PacketGen
|
|
429
449
|
end
|
430
450
|
|
431
451
|
# Get all optional field name
|
452
|
+
# @return[Array<Symbol>,nil]
|
432
453
|
def optional_fields
|
433
454
|
@optional_fields.keys
|
434
455
|
end
|
@@ -459,11 +480,7 @@ module PacketGen
|
|
459
480
|
next unless present?(field)
|
460
481
|
|
461
482
|
obj = self[field].read str[start..-1]
|
462
|
-
|
463
|
-
start += self[field].sz
|
464
|
-
else
|
465
|
-
start = str.size
|
466
|
-
end
|
483
|
+
start += self[field].sz
|
467
484
|
self[field] = obj unless obj == self[field]
|
468
485
|
end
|
469
486
|
|
@@ -530,7 +547,7 @@ module PacketGen
|
|
530
547
|
# @return [Hash,nil] keys: bit fields, values: their size in bits
|
531
548
|
# @since 2.8.3
|
532
549
|
def bits_on(field)
|
533
|
-
self.class.
|
550
|
+
self.class.bit_fields[field]
|
534
551
|
end
|
535
552
|
|
536
553
|
private
|
@@ -549,6 +566,54 @@ module PacketGen
|
|
549
566
|
def force_binary(str)
|
550
567
|
PacketGen.force_binary(str)
|
551
568
|
end
|
569
|
+
|
570
|
+
# @param [Symbol] attr attribute
|
571
|
+
# @return [Boolean] +tru+e if #from_human and #to_human are both defined for given attribute
|
572
|
+
def to_and_from_human?(attr)
|
573
|
+
self[attr].respond_to?(:to_human) && self[attr].respond_to?(:from_human)
|
574
|
+
end
|
575
|
+
|
576
|
+
def field_defs
|
577
|
+
self.class.field_defs
|
578
|
+
end
|
579
|
+
|
580
|
+
# rubocop:disable Metrics/AbcSize
|
581
|
+
def build_field(field)
|
582
|
+
type = field_defs[field].type
|
583
|
+
|
584
|
+
@fields[field] = if field_defs[field].builder
|
585
|
+
field_defs[field].builder.call(self, type)
|
586
|
+
elsif field_defs[field].enum
|
587
|
+
type.new(field_defs[field].enum)
|
588
|
+
elsif !field_defs[field].options.empty?
|
589
|
+
type.new(field_defs[field].options)
|
590
|
+
else
|
591
|
+
type.new
|
592
|
+
end
|
593
|
+
end
|
594
|
+
# rubocop:enable Metrics/AbcSize
|
595
|
+
|
596
|
+
def initialize_value(field, val)
|
597
|
+
type = field_defs[field].type
|
598
|
+
default = field_defs[field].default
|
599
|
+
default = default.to_proc.call(self) if default.is_a?(Proc)
|
600
|
+
|
601
|
+
value = val || default
|
602
|
+
if value.class <= type
|
603
|
+
@fields[field] = value
|
604
|
+
elsif @fields[field].respond_to? :from_human
|
605
|
+
@fields[field].from_human(value)
|
606
|
+
else
|
607
|
+
@fields[field].read(value)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
def initialize_optional(field)
|
612
|
+
optional = field_defs[field].optional
|
613
|
+
@optional_fields[field] = optional if optional
|
614
|
+
end
|
552
615
|
end
|
553
616
|
end
|
554
617
|
end
|
618
|
+
|
619
|
+
# rubocop:enable Metrics/ClassLength
|
data/lib/packetgen/types/int.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
# This file is part of PacketGen
|
3
5
|
# See https://github.com/sdaubert/packetgen for more informations
|
4
6
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
5
7
|
# This program is published under MIT license.
|
6
8
|
|
7
|
-
# frozen_string_literal: true
|
8
|
-
|
9
9
|
module PacketGen
|
10
10
|
module Types
|
11
11
|
# Base integer class to handle binary integers
|
12
12
|
# @abstract
|
13
13
|
# @author Sylvain Daubert
|
14
14
|
class Int
|
15
|
+
include Fieldable
|
16
|
+
|
15
17
|
# Integer value
|
16
18
|
# @return [Integer]
|
17
19
|
attr_accessor :value
|
@@ -45,7 +47,7 @@ module PacketGen
|
|
45
47
|
@value = if value.is_a?(Integer)
|
46
48
|
value.to_i
|
47
49
|
elsif defined? @packstr
|
48
|
-
value.to_s.
|
50
|
+
value.to_s.unpack1(@packstr[@endian])
|
49
51
|
else
|
50
52
|
raise ParseError, 'Int#read is abstract and cannot read'
|
51
53
|
end
|
@@ -56,9 +58,7 @@ module PacketGen
|
|
56
58
|
# @return [::String]
|
57
59
|
# @raise [ParseError] This is an abstrat method and must be redefined
|
58
60
|
def to_s
|
59
|
-
unless defined? @packstr
|
60
|
-
raise ParseError, 'PacketGen::Types::Int#to_s is an abstract method'
|
61
|
-
end
|
61
|
+
raise ParseError, 'PacketGen::Types::Int#to_s is an abstract method' unless defined? @packstr
|
62
62
|
|
63
63
|
[to_i].pack(@packstr[@endian])
|
64
64
|
end
|
@@ -82,6 +82,18 @@ module PacketGen
|
|
82
82
|
def sz
|
83
83
|
width
|
84
84
|
end
|
85
|
+
|
86
|
+
# Format Int type when inspecting header or packet
|
87
|
+
# @return [String]
|
88
|
+
def format_inspect
|
89
|
+
format_str % [to_i.to_s, to_i]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def format_str
|
95
|
+
"%-16s (0x%0#{width * 2}x)"
|
96
|
+
end
|
85
97
|
end
|
86
98
|
|
87
99
|
# One byte unsigned integer
|