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.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/bin/pgconsole +1 -0
  4. data/lib/packetgen.rb +33 -4
  5. data/lib/packetgen/capture.rb +51 -28
  6. data/lib/packetgen/config.rb +17 -11
  7. data/lib/packetgen/deprecation.rb +33 -7
  8. data/lib/packetgen/header.rb +2 -9
  9. data/lib/packetgen/header/arp.rb +2 -2
  10. data/lib/packetgen/header/asn1_base.rb +2 -2
  11. data/lib/packetgen/header/base.rb +70 -74
  12. data/lib/packetgen/header/bootp.rb +3 -3
  13. data/lib/packetgen/header/dhcp.rb +2 -2
  14. data/lib/packetgen/header/dhcp/option.rb +2 -2
  15. data/lib/packetgen/header/dhcp/options.rb +2 -2
  16. data/lib/packetgen/header/dhcpv6.rb +12 -12
  17. data/lib/packetgen/header/dhcpv6/duid.rb +11 -5
  18. data/lib/packetgen/header/dhcpv6/option.rb +8 -16
  19. data/lib/packetgen/header/dhcpv6/options.rb +2 -2
  20. data/lib/packetgen/header/dhcpv6/relay.rb +2 -2
  21. data/lib/packetgen/header/dns.rb +9 -9
  22. data/lib/packetgen/header/dns/name.rb +20 -9
  23. data/lib/packetgen/header/dns/opt.rb +2 -2
  24. data/lib/packetgen/header/dns/option.rb +2 -2
  25. data/lib/packetgen/header/dns/qdsection.rb +3 -3
  26. data/lib/packetgen/header/dns/question.rb +37 -35
  27. data/lib/packetgen/header/dns/rr.rb +3 -3
  28. data/lib/packetgen/header/dns/rrsection.rb +2 -2
  29. data/lib/packetgen/header/dot11.rb +30 -51
  30. data/lib/packetgen/header/dot11/control.rb +5 -5
  31. data/lib/packetgen/header/dot11/data.rb +11 -7
  32. data/lib/packetgen/header/dot11/element.rb +16 -16
  33. data/lib/packetgen/header/dot11/management.rb +2 -2
  34. data/lib/packetgen/header/dot11/sub_mngt.rb +2 -12
  35. data/lib/packetgen/header/dot1q.rb +2 -2
  36. data/lib/packetgen/header/dot1x.rb +7 -20
  37. data/lib/packetgen/header/eap.rb +30 -33
  38. data/lib/packetgen/header/eap/fast.rb +2 -2
  39. data/lib/packetgen/header/eap/md5.rb +2 -2
  40. data/lib/packetgen/header/eap/tls.rb +2 -2
  41. data/lib/packetgen/header/eap/ttls.rb +2 -2
  42. data/lib/packetgen/header/eth.rb +13 -11
  43. data/lib/packetgen/header/gre.rb +2 -2
  44. data/lib/packetgen/header/http.rb +2 -0
  45. data/lib/packetgen/header/http/headers.rb +6 -4
  46. data/lib/packetgen/header/http/request.rb +36 -21
  47. data/lib/packetgen/header/http/response.rb +7 -7
  48. data/lib/packetgen/header/http/verbs.rb +3 -3
  49. data/lib/packetgen/header/icmp.rb +2 -2
  50. data/lib/packetgen/header/icmpv6.rb +2 -2
  51. data/lib/packetgen/header/igmp.rb +4 -4
  52. data/lib/packetgen/header/igmpv3.rb +3 -3
  53. data/lib/packetgen/header/igmpv3/group_record.rb +8 -6
  54. data/lib/packetgen/header/igmpv3/mq.rb +2 -2
  55. data/lib/packetgen/header/igmpv3/mr.rb +2 -2
  56. data/lib/packetgen/header/ip.rb +30 -31
  57. data/lib/packetgen/header/ip/addr.rb +10 -3
  58. data/lib/packetgen/header/ip/option.rb +8 -10
  59. data/lib/packetgen/header/ip/options.rb +3 -5
  60. data/lib/packetgen/header/ipv6.rb +2 -2
  61. data/lib/packetgen/header/ipv6/addr.rb +9 -2
  62. data/lib/packetgen/header/ipv6/extension.rb +2 -2
  63. data/lib/packetgen/header/ipv6/hop_by_hop.rb +3 -3
  64. data/lib/packetgen/header/llc.rb +2 -2
  65. data/lib/packetgen/header/mdns.rb +2 -2
  66. data/lib/packetgen/header/mld.rb +2 -2
  67. data/lib/packetgen/header/mldv2.rb +2 -2
  68. data/lib/packetgen/header/mldv2/mcast_address_record.rb +4 -2
  69. data/lib/packetgen/header/mldv2/mlq.rb +2 -2
  70. data/lib/packetgen/header/mldv2/mlr.rb +2 -2
  71. data/lib/packetgen/header/ospfv2.rb +9 -9
  72. data/lib/packetgen/header/ospfv2/db_description.rb +2 -2
  73. data/lib/packetgen/header/ospfv2/hello.rb +2 -2
  74. data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -2
  75. data/lib/packetgen/header/ospfv2/ls_request.rb +4 -2
  76. data/lib/packetgen/header/ospfv2/ls_update.rb +2 -2
  77. data/lib/packetgen/header/ospfv2/lsa.rb +9 -5
  78. data/lib/packetgen/header/ospfv2/lsa_header.rb +8 -7
  79. data/lib/packetgen/header/ospfv3.rb +2 -2
  80. data/lib/packetgen/header/ospfv3/db_description.rb +2 -2
  81. data/lib/packetgen/header/ospfv3/hello.rb +2 -2
  82. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +4 -2
  83. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
  84. data/lib/packetgen/header/ospfv3/ls_request.rb +4 -2
  85. data/lib/packetgen/header/ospfv3/ls_update.rb +2 -2
  86. data/lib/packetgen/header/ospfv3/lsa.rb +5 -5
  87. data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -8
  88. data/lib/packetgen/header/snmp.rb +33 -29
  89. data/lib/packetgen/header/tcp.rb +4 -23
  90. data/lib/packetgen/header/tcp/option.rb +11 -11
  91. data/lib/packetgen/header/tcp/options.rb +2 -2
  92. data/lib/packetgen/header/tftp.rb +6 -6
  93. data/lib/packetgen/header/udp.rb +3 -3
  94. data/lib/packetgen/headerable.rb +5 -4
  95. data/lib/packetgen/inject.rb +23 -0
  96. data/lib/packetgen/inspect.rb +23 -20
  97. data/lib/packetgen/packet.rb +82 -53
  98. data/lib/packetgen/pcap.rb +29 -0
  99. data/lib/packetgen/pcapng.rb +13 -13
  100. data/lib/packetgen/pcapng/block.rb +26 -13
  101. data/lib/packetgen/pcapng/epb.rb +25 -22
  102. data/lib/packetgen/pcapng/file.rb +260 -138
  103. data/lib/packetgen/pcapng/idb.rb +36 -38
  104. data/lib/packetgen/pcapng/shb.rb +51 -53
  105. data/lib/packetgen/pcapng/spb.rb +19 -19
  106. data/lib/packetgen/pcapng/unknown_block.rb +5 -13
  107. data/lib/packetgen/pcaprub_wrapper.rb +81 -0
  108. data/lib/packetgen/proto.rb +2 -2
  109. data/lib/packetgen/types.rb +3 -0
  110. data/lib/packetgen/types/abstract_tlv.rb +27 -7
  111. data/lib/packetgen/types/array.rb +22 -15
  112. data/lib/packetgen/types/cstring.rb +57 -20
  113. data/lib/packetgen/types/enum.rb +7 -2
  114. data/lib/packetgen/types/fieldable.rb +65 -0
  115. data/lib/packetgen/types/fields.rb +182 -117
  116. data/lib/packetgen/types/int.rb +18 -6
  117. data/lib/packetgen/types/int_string.rb +10 -2
  118. data/lib/packetgen/types/length_from.rb +20 -12
  119. data/lib/packetgen/types/oui.rb +4 -2
  120. data/lib/packetgen/types/string.rb +59 -8
  121. data/lib/packetgen/types/tlv.rb +4 -2
  122. data/lib/packetgen/utils.rb +4 -4
  123. data/lib/packetgen/utils/arp_spoofer.rb +2 -2
  124. data/lib/packetgen/version.rb +3 -3
  125. metadata +39 -61
  126. data/.gitignore +0 -13
  127. data/.rubocop.yml +0 -30
  128. data/.travis.yml +0 -19
  129. data/Gemfile +0 -4
  130. data/Rakefile +0 -21
  131. 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
- # frozen_string_literal: true
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 types from {Types} module are supported, and 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 = @bit_fields.clone
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 [Object] type class or instance
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
- define = []
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
- fields << name
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 [Object] type class or instance
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 [Object] type class or instance
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
- raise ArgumentError, "unkown #{field} field for #{self}" unless field_defs.key?(field)
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
- attr_def = field_defs[attr]
295
- raise ArgumentError, "unknown #{attr} field" if attr_def.nil?
280
+ check_existence_of attr
296
281
 
297
- type = attr_def.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
- field = args.shift
306
- while field
288
+ until args.empty?
289
+ field = args.shift
307
290
  next unless field.is_a? Symbol
308
291
 
309
- size = if args.first.is_a? Integer
310
- args.shift
311
- else
312
- 1
313
- end
292
+ size = size_from(args)
293
+
314
294
  unless field == :_
315
- shift = idx - (size - 1)
316
- field_mask = (2**size - 1) << shift
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 = @bit_fields.delete(attr)
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
- type = field_defs[field].type
377
- default = field_defs[field].default
378
- default = default.to_proc.call(self) if default.is_a?(Proc)
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
- self.class.class_eval { @bit_fields }.each do |_, hsh|
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 [Object]
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
- if self[field].respond_to? :sz
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.class_eval { @bit_fields }[field]
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
@@ -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.unpack(@packstr[@endian]).first
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