packetgen 3.1.3 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
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