packetgen 3.2.0 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/pgconsole +3 -3
  4. data/lib/packetgen/header/arp.rb +24 -13
  5. data/lib/packetgen/header/asn1_base.rb +2 -2
  6. data/lib/packetgen/header/base.rb +1 -1
  7. data/lib/packetgen/header/dhcpv6/duid.rb +6 -0
  8. data/lib/packetgen/header/dhcpv6/option.rb +11 -13
  9. data/lib/packetgen/header/dns/opt.rb +2 -2
  10. data/lib/packetgen/header/dns/rr.rb +61 -28
  11. data/lib/packetgen/header/dns.rb +13 -6
  12. data/lib/packetgen/header/dot11/management.rb +2 -5
  13. data/lib/packetgen/header/dot11.rb +1 -1
  14. data/lib/packetgen/header/eap.rb +1 -1
  15. data/lib/packetgen/header/eth.rb +1 -1
  16. data/lib/packetgen/header/http/headers.rb +16 -1
  17. data/lib/packetgen/header/http/response.rb +43 -23
  18. data/lib/packetgen/header/igmp.rb +1 -1
  19. data/lib/packetgen/header/ip/option.rb +36 -10
  20. data/lib/packetgen/header/ipv6/addr.rb +3 -0
  21. data/lib/packetgen/header/mdns.rb +19 -25
  22. data/lib/packetgen/header/mld.rb +1 -1
  23. data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -4
  24. data/lib/packetgen/header/ospfv2.rb +1 -1
  25. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +14 -5
  26. data/lib/packetgen/header/ospfv3/lsa.rb +1 -1
  27. data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -4
  28. data/lib/packetgen/header/ospfv3.rb +1 -1
  29. data/lib/packetgen/header/snmp.rb +39 -16
  30. data/lib/packetgen/header/tcp/option.rb +1 -1
  31. data/lib/packetgen/header/tcp.rb +12 -5
  32. data/lib/packetgen/header/tftp.rb +15 -9
  33. data/lib/packetgen/inspect.rb +15 -9
  34. data/lib/packetgen/packet.rb +48 -2
  35. data/lib/packetgen/pcapng/file.rb +13 -13
  36. data/lib/packetgen/pcapng.rb +1 -0
  37. data/lib/packetgen/pcaprub_wrapper.rb +0 -4
  38. data/lib/packetgen/types/abstract_tlv.rb +1 -1
  39. data/lib/packetgen/types/array.rb +35 -13
  40. data/lib/packetgen/types/fields.rb +19 -19
  41. data/lib/packetgen/types/int.rb +7 -0
  42. data/lib/packetgen/types/oui.rb +1 -1
  43. data/lib/packetgen/types/tlv.rb +17 -9
  44. data/lib/packetgen/unknown_packet.rb +3 -2
  45. data/lib/packetgen/utils.rb +67 -24
  46. data/lib/packetgen/version.rb +1 -1
  47. data/lib/packetgen.rb +3 -3
  48. metadata +3 -3
@@ -31,32 +31,10 @@ module PacketGen
31
31
  case iph
32
32
  when IP
33
33
  iph.dst = '224.0.0.251'
34
- llh = ll_header(self)
35
- mac = case llh
36
- when Eth
37
- llh[:dst]
38
- when Dot11
39
- if llh.to_ds?
40
- llh[:mac3]
41
- else
42
- llh[:mac1]
43
- end
44
- end
45
- mac.from_human('01:00:5E:00:00:FB')
34
+ dst_mac.from_human('01:00:5E:00:00:FB')
46
35
  when IPv6
47
36
  iph.dst = 'ff02::fb'
48
- llh = ll_header(self)
49
- mac = case llh
50
- when Eth
51
- llh[:dst]
52
- when Dot11
53
- if llh.to_ds?
54
- llh[:mac3]
55
- else
56
- llh[:mac1]
57
- end
58
- end
59
- mac.from_human('33:33:00:00:00:FB')
37
+ dst_mac.from_human('33:33:00:00:00:FB')
60
38
  end
61
39
  end
62
40
 
@@ -67,12 +45,28 @@ module PacketGen
67
45
  # Needed by new bind API.
68
46
  def added_to_packet(packet)
69
47
  mdns_idx = packet.headers.size
70
- packet.instance_eval "def mdnsize() @headers[#{mdns_idx}].mdnsize; end"
48
+ packet.instance_eval "def mdnsize() @headers[#{mdns_idx}].mdnsize; end" # def mdnsize() @headers[4].mdnsize; end
71
49
  return unless packet.is? 'UDP'
72
50
  return unless packet.udp.sport.zero?
73
51
 
74
52
  packet.udp.sport = UDP_PORT
75
53
  end
54
+
55
+ private
56
+
57
+ def dst_mac
58
+ llh = ll_header(self)
59
+ case llh
60
+ when Eth
61
+ llh[:dst]
62
+ when Dot11
63
+ if llh.to_ds?
64
+ llh[:mac3]
65
+ else
66
+ llh[:mac1]
67
+ end
68
+ end
69
+ end
76
70
  end
77
71
 
78
72
  self.add_class MDNS
@@ -68,7 +68,7 @@ module PacketGen
68
68
  # directly called
69
69
  def added_to_packet(packet)
70
70
  mld_idx = packet.headers.size
71
- packet.instance_eval "def mldize() @headers[#{mld_idx}].mldize; end"
71
+ packet.instance_eval "def mldize() @headers[#{mld_idx}].mldize; end" # def mldize() @headers[3].mldize; end
72
72
  end
73
73
 
74
74
  # Fixup IP header according to RFC 2710:
@@ -77,17 +77,15 @@ module PacketGen
77
77
  # Compute and set Fletcher-16 checksum on LSA
78
78
  # @return [Integer]
79
79
  def calc_checksum
80
- bytes = to_s[2..-1].unpack('C*')
81
-
82
80
  c0 = c1 = 0
83
- bytes.each do |byte|
81
+ to_s[2..-1].unpack('C*').each do |byte|
84
82
  c0 += byte
85
83
  c1 += c0
86
84
  end
87
85
  c0 %= 255
88
86
  c1 %= 255
89
87
 
90
- x = ((sz - 16 - 1) * c0 - c1) % 255
88
+ x = ((sz - 17) * c0 - c1) % 255
91
89
  x += 255 if x <= 0
92
90
  y = 255 * 2 - c0 - x
93
91
  y -= 255 if y > 255
@@ -167,7 +167,7 @@ module PacketGen
167
167
  # directly called
168
168
  def added_to_packet(packet)
169
169
  ospf_idx = packet.headers.size
170
- packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end"
170
+ packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end" # def ospfize(**kwargs) @headers[2].ospfize(**kwargs); end
171
171
  end
172
172
 
173
173
  # Compute checksum and set +checksum+ field
@@ -71,11 +71,8 @@ module PacketGen
71
71
  # @param [String] str
72
72
  # @return [void]
73
73
  def from_human(str)
74
- pfx, len = str.split('/')
75
- len = (len || 128).to_i
76
- addr = IPv6::Addr.new.from_human(pfx)
77
- ary_size = (len + 31) / 32
78
- ary = addr.to_a[0...ary_size * 2]
74
+ ary, len = ary_and_prefix_len_from_str(str)
75
+
79
76
  self.prefix.clear
80
77
  ary.each_with_index do |v, i|
81
78
  if i.even?
@@ -86,6 +83,18 @@ module PacketGen
86
83
  end
87
84
  self.length = len
88
85
  end
86
+
87
+ private
88
+
89
+ def ary_and_prefix_len_from_str(str)
90
+ pfx, len = str.split('/')
91
+ len = (len || 128).to_i
92
+ addr = IPv6::Addr.new.from_human(pfx)
93
+ ary_size = (len + 31) / 32
94
+ ary = addr.to_a[0...ary_size * 2]
95
+
96
+ [ary, len]
97
+ end
89
98
  end
90
99
 
91
100
  # Array of {IPv6Prefix}
@@ -35,7 +35,7 @@ module PacketGen
35
35
  # @return [String]
36
36
  def to_human
37
37
  "Link<type:#{type},metric:#{metric},id:#{interface_id}," \
38
- "neighbor_id:#{neighbor_interface_id},neighbor_router:#{neighbor_router_id}>"
38
+ "neighbor_id:#{neighbor_interface_id},neighbor_router:#{neighbor_router_id}>"
39
39
  end
40
40
  end
41
41
 
@@ -78,17 +78,15 @@ module PacketGen
78
78
  # Compute and set Fletcher-16 checksum on LSA
79
79
  # @return [Integer]
80
80
  def calc_checksum
81
- bytes = to_s[2..-1].unpack('C*')
82
-
83
81
  c0 = c1 = 0
84
- bytes.each do |byte|
82
+ to_s[2..-1].unpack('C*').each do |byte|
85
83
  c0 += byte
86
84
  c1 += c0
87
85
  end
88
86
  c0 %= 255
89
87
  c1 %= 255
90
88
 
91
- x = ((sz - 16 - 1) * c0 - c1) % 255
89
+ x = ((sz - 17) * c0 - c1) % 255
92
90
  x += 255 if x <= 0
93
91
  y = 255 * 2 - c0 - x
94
92
  y -= 255 if y > 255
@@ -145,7 +145,7 @@ module PacketGen
145
145
  # directly called
146
146
  def added_to_packet(packet)
147
147
  ospf_idx = packet.headers.size
148
- packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end"
148
+ packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end" # def ospfize(**kwargs) @headers[2].ospfize(**kwargs); end
149
149
  end
150
150
 
151
151
  # Compute checksum and set +checksum+ field
@@ -74,6 +74,18 @@ module PacketGen
74
74
  # @author Sylvain Daubert
75
75
  class VariableBindings < RASN1::Model
76
76
  sequence_of :bindings, VarBind
77
+
78
+ # Get 'idx'th element from the list
79
+ # @return [VarBind,nil]
80
+ def [](idx)
81
+ value[idx]
82
+ end
83
+
84
+ # Get element counts in list
85
+ # @return [Integer]
86
+ def size
87
+ value.size
88
+ end
77
89
  end
78
90
 
79
91
  # Class to handle GetRequest PDU
@@ -119,6 +131,10 @@ module PacketGen
119
131
  integer(:error, value: 0, enum: ERRORS),
120
132
  integer(:error_index, value: 0),
121
133
  model(:varbindlist, VariableBindings)]
134
+
135
+ def initialize(args={})
136
+ super
137
+ end
122
138
  end
123
139
 
124
140
  # Class to handle GetNextRequest PDU
@@ -264,11 +280,12 @@ module PacketGen
264
280
  data.chosen = options[:chosen_pdu] if options[:chosen_pdu]
265
281
  return unless options[:pdu]
266
282
 
267
- data.root.value[data.chosen] = data.root.chosen_value.class.new(options[:pdu])
283
+ klass = data.root.chosen_value.class
284
+ data.root.value[data.chosen] = klass.new(options[:pdu])
268
285
  end
269
286
 
270
287
  # accessor to data payload
271
- # @return [GetRequest]
288
+ # @return [ASN1::Types::Choice]
272
289
  def data
273
290
  @elements[:data]
274
291
  end
@@ -286,20 +303,11 @@ module PacketGen
286
303
  def inspect
287
304
  str = super
288
305
  str << Inspect.shift_level
289
- if self[:data].chosen.nil?
290
- str << Inspect::FMT_ATTR % [self[:data].type, :data, '']
291
- else
292
- data = self[:data]
293
- str << Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
294
- str << Inspect.dashed_line('ASN.1 content')
295
- str << data.chosen_value.inspect(1)
296
- begin
297
- str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
298
- rescue StandardError => e
299
- raise unless e.message.match?(/TAG.*not handled/)
300
- end
301
- str
302
- end
306
+ str << if self[:data].chosen.nil?
307
+ Inspect::FMT_ATTR % [self[:data].type, :data, '']
308
+ else
309
+ inspect_data
310
+ end
303
311
  end
304
312
 
305
313
  # @api private
@@ -315,6 +323,21 @@ module PacketGen
315
323
 
316
324
  packet.udp.sport = packet.udp.dport
317
325
  end
326
+
327
+ private
328
+
329
+ def inspect_data
330
+ data = self[:data]
331
+ str = Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
332
+ str << Inspect.dashed_line('ASN.1 content')
333
+ str << data.chosen_value.inspect(1)
334
+ begin
335
+ str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
336
+ rescue StandardError => e
337
+ raise unless e.message.match?(/TAG.*not handled/)
338
+ end
339
+ str
340
+ end
318
341
  end
319
342
 
320
343
  self.add_class SNMP
@@ -43,7 +43,7 @@ module PacketGen
43
43
  # @!attribute value
44
44
  # @return [Integer,String] option value
45
45
  define_field :value, Types::String, optional: ->(h) { h.length? && h.length > 2 },
46
- builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
46
+ builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
47
47
 
48
48
  # @param [hash] options
49
49
  # @option options [Integer] :kind
@@ -216,11 +216,7 @@ module PacketGen
216
216
  doff = Inspect.int_dec_hex(data_offset, 1)
217
217
  str << shift << Inspect::FMT_ATTR % ['', 'data_offset', doff]
218
218
  str << shift << Inspect::FMT_ATTR % ['', 'reserved', reserved]
219
- flags = +''
220
- %w[ns cwr ece urg ack psh rst syn fin].each do |fl|
221
- flags << (send("flag_#{fl}?") ? fl[0].upcase : '.')
222
- end
223
- str << shift << Inspect::FMT_ATTR % ['', 'flags', flags]
219
+ str << shift << Inspect::FMT_ATTR % ['', 'flags', flags2string]
224
220
  end
225
221
  end
226
222
 
@@ -231,6 +227,17 @@ module PacketGen
231
227
  self[:sport], self[:dport] = self[:dport], self[:sport]
232
228
  self
233
229
  end
230
+
231
+ private
232
+
233
+ def flags2string
234
+ flags = +''
235
+ %w[ns cwr ece urg ack psh rst syn fin].each do |fl|
236
+ flags << (send("flag_#{fl}?") ? fl[0].upcase : '.')
237
+ end
238
+
239
+ flags
240
+ end
234
241
  end
235
242
 
236
243
  self.add_class TCP
@@ -102,22 +102,18 @@ module PacketGen
102
102
  client_tid = packet.udp.sport
103
103
  server_tid = nil
104
104
  ary.each do |pkt|
105
+ next unless pkt.is?('UDP')
106
+
105
107
  if server_tid.nil?
106
- next unless pkt.is?('UDP') && (pkt.udp.dport == client_tid)
108
+ next unless pkt.udp.dport == client_tid
107
109
 
108
110
  server_tid = pkt.udp.sport
109
111
  else
110
- next unless pkt.is?('UDP')
111
-
112
112
  tids = [server_tid, client_tid]
113
113
  ports = [pkt.udp.sport, pkt.udp.dport]
114
114
  next unless (tids - ports).empty?
115
115
  end
116
- tftp = Packet.parse(pkt.body, first_header: 'TFTP')
117
- udp_dport = pkt.udp.dport
118
- pkt.encapsulate tftp
119
- # need to fix it as #encapsulate force it to 69
120
- pkt.udp.dport = udp_dport
116
+ decode_tftp_packet(pkt)
121
117
  end
122
118
  end
123
119
 
@@ -135,7 +131,17 @@ module PacketGen
135
131
  def added_to_packet(packet)
136
132
  return if packet.respond_to? :tftp
137
133
 
138
- packet.instance_eval("def tftp(arg=nil); header(#{self.class}, arg); end")
134
+ packet.instance_eval("def tftp(arg=nil); header(#{self.class}, arg); end") # def tftp(arg=nil); header(TFTP, arg); end
135
+ end
136
+
137
+ private
138
+
139
+ def decode_tftp_packet(pkt)
140
+ tftp = Packet.parse(pkt.body, first_header: 'TFTP')
141
+ udp_dport = pkt.udp.dport
142
+ pkt.encapsulate tftp
143
+ # need to fix it as #encapsulate force it to 69
144
+ pkt.udp.dport = udp_dport
139
145
  end
140
146
 
141
147
  # TFTP Read Request header
@@ -12,6 +12,8 @@ module PacketGen
12
12
  module Inspect
13
13
  # Maximum number of characters on a line for INSPECT
14
14
  MAX_WIDTH = 70
15
+ # @private
16
+ SEPARATOR = ('-' * MAX_WIDTH << "\n").freeze
15
17
 
16
18
  # Format to inspect attribute
17
19
  FMT_ATTR = "%14s %16s: %s\n"
@@ -105,19 +107,23 @@ module PacketGen
105
107
  return '' if body.nil? || body.empty?
106
108
 
107
109
  str = dashed_line(name, 2)
108
- str << (0..15).to_a.map { |v| ' %02d' % v }.join << "\n"
109
- str << '-' * MAX_WIDTH << "\n"
110
+ 0.upto(15) { |v| str << ' %02d' % v }
111
+ str << "\n" << SEPARATOR
110
112
  unless body.empty?
111
113
  (body.size / 16 + 1).times do |i|
112
- octets = body.to_s[i * 16, 16].unpack('C*')
113
- o_str = octets.map { |v| ' %02x' % v }.join
114
- str << o_str
115
- str << ' ' * (3 * 16 - o_str.size) unless o_str.size >= 3 * 16
116
- str << ' ' << octets.map { |v| v < 128 && v > 31 ? v.chr : '.' }.join
117
- str << "\n"
114
+ str << self.convert_body_slice(body.to_s[i * 16, 16])
118
115
  end
119
116
  end
120
- str << '-' * MAX_WIDTH << "\n"
117
+ str << SEPARATOR
118
+ end
119
+
120
+ # @private
121
+ def self.convert_body_slice(bslice)
122
+ octets = bslice.unpack('C*')
123
+ str = octets.map { |v| ' %02x' % v }.join
124
+ str << ' ' * (48 - str.size) unless str.size >= 48
125
+ str << ' ' << octets.map { |v| (32..127).cover?(v) ? v.chr : '.' }.join
126
+ str << "\n"
121
127
  end
122
128
  end
123
129
  end
@@ -51,6 +51,9 @@ module PacketGen
51
51
  # Get packet headers, ordered as they appear in the packet.
52
52
  # @return [Array<Header::Base>]
53
53
  attr_reader :headers
54
+ # Activaye or deactivate header cache (activated by default)
55
+ # @return [Boolean]
56
+ attr_accessor :cache_headers
54
57
 
55
58
  # Create a new Packet
56
59
  # @param [String] protocol base protocol for packet
@@ -121,6 +124,8 @@ module PacketGen
121
124
  # @private
122
125
  def initialize
123
126
  @headers = []
127
+ @header_cache = {}
128
+ @cache_headers = true
124
129
  end
125
130
 
126
131
  # Add a protocol header in packet.
@@ -166,7 +171,7 @@ module PacketGen
166
171
  # @raise [ArgumentError] unknown protocol
167
172
  def is?(protocol)
168
173
  klass = check_protocol protocol
169
- headers.any? { |h| h.is_a? klass }
174
+ headers.any?(klass)
170
175
  end
171
176
 
172
177
  # Recalculate all packet checksums
@@ -271,6 +276,7 @@ module PacketGen
271
276
  headers.delete(hdr)
272
277
  add_header(next_hdr, previous_header: prev_hdr) if prev_hdr && next_hdr
273
278
  end
279
+ invalidate_header_cache
274
280
  rescue ArgumentError => e
275
281
  raise FormatError, e.message
276
282
  end
@@ -356,6 +362,7 @@ module PacketGen
356
362
  headers.each do |header|
357
363
  add_magic_header_method header
358
364
  end
365
+ invalidate_header_cache
359
366
  end
360
367
 
361
368
  # Give first header of packet
@@ -409,7 +416,7 @@ module PacketGen
409
416
  # @return [Header::Base]
410
417
  def header(klass, arg)
411
418
  layer = arg.is_a?(Integer) ? arg : 1
412
- header = headers.select { |h| h.is_a? klass }[layer - 1]
419
+ header = find_header(klass, layer)
413
420
  return header unless arg.is_a? Hash
414
421
 
415
422
  arg.each do |key, value|
@@ -421,6 +428,19 @@ module PacketGen
421
428
  header
422
429
  end
423
430
 
431
+ # Get header from cache, or find it in packet
432
+ # @param [Class] klass
433
+ # @param [Integer] layer
434
+ # @return [Header::Base]
435
+ def find_header(klass, layer)
436
+ header = fetch_header_from_cache(klass, layer)
437
+ return header if header
438
+
439
+ header = headers.select { |h| h.is_a? klass }[layer - 1]
440
+ add_header_to_cache(header, klass, layer)
441
+ header
442
+ end
443
+
424
444
  # check if protocol is known
425
445
  # @param [String] protocol
426
446
  # @raise [ArgumentError] unknown protocol
@@ -438,6 +458,7 @@ module PacketGen
438
458
  # @return [void]
439
459
  # @raise [BindingError]
440
460
  def add_header(header, previous_header: nil, parsing: false)
461
+ invalidate_header_cache
441
462
  prev_header = previous_header || last_header
442
463
  add_to_previous_header(prev_header, header, parsing) if prev_header
443
464
 
@@ -521,6 +542,31 @@ module PacketGen
521
542
 
522
543
  nil
523
544
  end
545
+
546
+ def invalidate_header_cache
547
+ return unless cache_headers
548
+
549
+ @header_cache = {}
550
+ end
551
+
552
+ # Fetch header from cache if authorized
553
+ # @param [Class] klass
554
+ # @param [Integer] layer
555
+ # @return [Header::Base,nil]
556
+ def fetch_header_from_cache(klass, layer)
557
+ @header_cache.fetch(klass, []).fetch(layer - 1, nil) if cache_headers
558
+ end
559
+
560
+ # Add header to cache if authorized
561
+ # @param [Class] klass
562
+ # @param [Integer] layer
563
+ # @return [Header::Base,nil]
564
+ def add_header_to_cache(header, klass, layer)
565
+ return unless cache_headers
566
+
567
+ @header_cache[klass] ||= []
568
+ @header_cache[klass][layer - 1] = header
569
+ end
524
570
  end
525
571
  end
526
572
 
@@ -9,7 +9,7 @@ module PacketGen
9
9
  module PcapNG
10
10
  # PcapNG::File is a complete Pcap-NG file handler.
11
11
  # @author Sylvain Daubert
12
- class File
12
+ class File # rubocop:disable Metrics/ClassLength
13
13
  # Known link types
14
14
  KNOWN_LINK_TYPES = {
15
15
  LINKTYPE_ETHERNET => 'Eth',
@@ -21,13 +21,11 @@ module PacketGen
21
21
  }.freeze
22
22
 
23
23
  # @private
24
- BLOCK_TYPES = Hash[
25
- PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.map do |c|
26
- type_value = PcapNG.const_get(c).to_i
27
- klass = PcapNG.const_get(c.to_s[0..-6]) # @todo use delete_suffix('_TYPE') when support for Ruby 2.4 will stop
28
- [type_value, klass]
29
- end
30
- ].freeze
24
+ BLOCK_TYPES = PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.map do |c|
25
+ type_value = PcapNG.const_get(c).to_i
26
+ klass = PcapNG.const_get(c.to_s.delete_suffix('_TYPE'))
27
+ [type_value, klass]
28
+ end.to_h.freeze
31
29
 
32
30
  # Get file sections
33
31
  # @return [Array]
@@ -204,7 +202,7 @@ module PacketGen
204
202
  # @return [Array] array of 2 elements: filename and size written
205
203
  # @todo for 4.0, replace +options+ by +append+ kwarg
206
204
  def to_file(filename, options={})
207
- mode = (options[:append] && ::File.exist?(filename)) ? 'ab' : 'wb'
205
+ mode = options[:append] && ::File.exist?(filename) ? 'ab' : 'wb'
208
206
  ::File.open(filename, mode) { |f| f.write(self.to_s) }
209
207
  [filename, self.to_s.size]
210
208
  end
@@ -317,12 +315,12 @@ module PacketGen
317
315
  shb = parse_shb(SHB.new, io)
318
316
  raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
319
317
 
320
- to_parse = if shb.section_len.to_i != 0xffffffffffffffff
321
- # Section length is defined
322
- StringIO.new(io.read(shb.section_len.to_i))
323
- else
318
+ to_parse = if shb.section_len.to_i == 0xffffffffffffffff
324
319
  # section length is undefined
325
320
  io
321
+ else
322
+ # Section length is defined
323
+ StringIO.new(io.read(shb.section_len.to_i))
326
324
  end
327
325
 
328
326
  until to_parse.eof?
@@ -388,6 +386,7 @@ module PacketGen
388
386
  end
389
387
  end
390
388
 
389
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
391
390
  # Extract and check options for #array_to_file
392
391
  def array_to_file_options_from_hash(options)
393
392
  %i[filename arr ts].each do |deprecated_opt|
@@ -404,6 +403,7 @@ module PacketGen
404
403
 
405
404
  [filename, ary, ts, ts_inc, append]
406
405
  end
406
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
407
407
 
408
408
  def create_new_shb_section
409
409
  section = SHB.new
@@ -41,6 +41,7 @@ module PacketGen
41
41
 
42
42
  # Base error class for PcapNG
43
43
  class Error < PacketGen::Error; end
44
+
44
45
  # Invalid PcapNG file error
45
46
  class InvalidFileError < Error; end
46
47
  end
@@ -38,8 +38,6 @@ module PacketGen
38
38
  pcap.activate
39
39
  end
40
40
 
41
- # rubocop:disable Metrics/ParameterLists
42
-
43
41
  # Capture packets from a network interface
44
42
  # @param [String] iface interface name
45
43
  # @param [Integer] snaplen
@@ -57,8 +55,6 @@ module PacketGen
57
55
  pcap.each(&block)
58
56
  end
59
57
 
60
- # rubocop:enable Metrics/ParameterLists
61
-
62
58
  # Inject given data onto wire
63
59
  # @param [String] iface interface name
64
60
  # @param [String] data to inject
@@ -60,7 +60,7 @@ module PacketGen
60
60
  class AbstractTLV < Types::Fields
61
61
  include Fieldable
62
62
 
63
- class <<self
63
+ class << self
64
64
  # @return [Hash]
65
65
  attr_accessor :aliases
66
66
  attr_accessor :header_in_length