packetgen 3.1.6 → 3.2.1

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/bin/pgconsole +3 -3
  4. data/lib/packetgen/capture.rb +5 -1
  5. data/lib/packetgen/header/arp.rb +24 -13
  6. data/lib/packetgen/header/asn1_base.rb +19 -9
  7. data/lib/packetgen/header/base.rb +1 -1
  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/data.rb +19 -29
  13. data/lib/packetgen/header/dot11/management.rb +2 -5
  14. data/lib/packetgen/header/dot11.rb +1 -1
  15. data/lib/packetgen/header/eap.rb +1 -1
  16. data/lib/packetgen/header/eth.rb +1 -1
  17. data/lib/packetgen/header/http/request.rb +5 -1
  18. data/lib/packetgen/header/http/response.rb +46 -20
  19. data/lib/packetgen/header/http/verbs.rb +1 -1
  20. data/lib/packetgen/header/igmp.rb +1 -1
  21. data/lib/packetgen/header/ip/option.rb +2 -1
  22. data/lib/packetgen/header/ipv6/addr.rb +3 -0
  23. data/lib/packetgen/header/mdns.rb +19 -25
  24. data/lib/packetgen/header/mld.rb +1 -1
  25. data/lib/packetgen/header/ospfv2/lsa.rb +7 -3
  26. data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -4
  27. data/lib/packetgen/header/ospfv2.rb +1 -1
  28. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +14 -5
  29. data/lib/packetgen/header/ospfv3/lsa.rb +8 -4
  30. data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -4
  31. data/lib/packetgen/header/ospfv3.rb +1 -1
  32. data/lib/packetgen/header/snmp.rb +20 -14
  33. data/lib/packetgen/header/tcp/option.rb +1 -1
  34. data/lib/packetgen/header/tcp.rb +12 -5
  35. data/lib/packetgen/header/tftp.rb +15 -9
  36. data/lib/packetgen/inspect.rb +15 -9
  37. data/lib/packetgen/packet.rb +51 -5
  38. data/lib/packetgen/pcapng/file.rb +17 -15
  39. data/lib/packetgen/pcapng.rb +1 -0
  40. data/lib/packetgen/pcaprub_wrapper.rb +0 -4
  41. data/lib/packetgen/types/abstract_tlv.rb +1 -1
  42. data/lib/packetgen/types/array.rb +8 -1
  43. data/lib/packetgen/types/cstring.rb +20 -7
  44. data/lib/packetgen/types/fields.rb +19 -19
  45. data/lib/packetgen/types/int.rb +7 -0
  46. data/lib/packetgen/types/oui.rb +1 -1
  47. data/lib/packetgen/types/string.rb +16 -3
  48. data/lib/packetgen/types/tlv.rb +17 -9
  49. data/lib/packetgen/unknown_packet.rb +84 -0
  50. data/lib/packetgen/utils.rb +60 -27
  51. data/lib/packetgen/version.rb +1 -1
  52. data/lib/packetgen.rb +13 -4
  53. metadata +7 -7
@@ -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:
@@ -229,9 +229,13 @@ module PacketGen
229
229
 
230
230
  def get_lsa_class_by_human_type(htype)
231
231
  klassname = "LSA#{htype.to_s.delete('-')}"
232
- if OSPFv2.const_defined? klassname
233
- OSPFv2.const_get klassname
234
- else
232
+ begin
233
+ if OSPFv2.const_defined? klassname
234
+ OSPFv2.const_get klassname
235
+ else
236
+ LSA
237
+ end
238
+ rescue NameError
235
239
  LSA
236
240
  end
237
241
  end
@@ -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
 
@@ -218,9 +218,13 @@ module PacketGen
218
218
 
219
219
  def get_lsa_class_by_human_type(htype)
220
220
  klassname = "LSA#{htype.to_s.delete('-')}"
221
- if OSPFv3.const_defined? klassname
222
- OSPFv3.const_get klassname
223
- else
221
+ begin
222
+ if OSPFv3.const_defined? klassname
223
+ OSPFv3.const_get klassname
224
+ else
225
+ LSA
226
+ end
227
+ rescue NameError
224
228
  LSA
225
229
  end
226
230
  end
@@ -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
@@ -286,20 +286,11 @@ module PacketGen
286
286
  def inspect
287
287
  str = super
288
288
  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
289
+ str << if self[:data].chosen.nil?
290
+ Inspect::FMT_ATTR % [self[:data].type, :data, '']
291
+ else
292
+ inspect_data
293
+ end
303
294
  end
304
295
 
305
296
  # @api private
@@ -315,6 +306,21 @@ module PacketGen
315
306
 
316
307
  packet.udp.sport = packet.udp.dport
317
308
  end
309
+
310
+ private
311
+
312
+ def inspect_data
313
+ data = self[:data]
314
+ str = Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
315
+ str << Inspect.dashed_line('ASN.1 content')
316
+ str << data.chosen_value.inspect(1)
317
+ begin
318
+ str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
319
+ rescue StandardError => e
320
+ raise unless e.message.match?(/TAG.*not handled/)
321
+ end
322
+ str
323
+ end
318
324
  end
319
325
 
320
326
  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
@@ -81,7 +84,7 @@ module PacketGen
81
84
  # @return [Array<Packet>] captured packet
82
85
  def self.capture(**kwargs, &block)
83
86
  capture = Capture.new(**kwargs)
84
- if block_given?
87
+ if block
85
88
  capture.start(&block)
86
89
  else
87
90
  capture.start
@@ -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
@@ -216,7 +221,7 @@ module PacketGen
216
221
  # @return [Array] see return from {PcapNG::File#to_file}
217
222
  # @see File
218
223
  def to_f(filename)
219
- PcapNG::File.new.array_to_file(file: filename, array: [self])
224
+ PcapNG::File.new.read_array([self]).to_f(filename)
220
225
  end
221
226
  alias write to_f
222
227
 
@@ -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
@@ -287,7 +293,7 @@ module PacketGen
287
293
  if first_header.nil?
288
294
  # No decoding forced for first header. Have to guess it!
289
295
  first_header = guess_first_header(binary_str)
290
- raise ParseError, 'cannot identify first header in string' if first_header.nil?
296
+ raise ParseError, "cannot identify first header in string: #{binary_str.inspect}" if first_header.nil?
291
297
  end
292
298
 
293
299
  add first_header
@@ -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
@@ -264,7 +262,7 @@ module PacketGen
264
262
  # @param [Time, nil] timestamp initial timestamp, used for first packet
265
263
  # @param [Numeric, nil] ts_inc timestamp increment, in seconds, to increment
266
264
  # initial timestamp for each packet
267
- # @return [void]
265
+ # @return [self]
268
266
  # @note if +timestamp+ and/or +ts_inc+ are nil, {SPB} sections are created
269
267
  # for each packet, else {EPB} ones are used
270
268
  # @since 3.1.6
@@ -276,11 +274,12 @@ module PacketGen
276
274
  classify_block(section, block)
277
275
  ts = update_ts(ts, ts_inc)
278
276
  end
277
+ self
279
278
  end
280
279
 
281
280
  # Update current object from a hash of packets and timestamps
282
281
  # @param [Hash{Time => Packet}] hsh
283
- # @return [void]
282
+ # @return [self]
284
283
  # @since 3.1.6
285
284
  def read_hash(hsh)
286
285
  section = create_new_shb_section
@@ -288,6 +287,7 @@ module PacketGen
288
287
  block = create_block_from_pkt(pkt, section, ts, 0)
289
288
  classify_block(section, block)
290
289
  end
290
+ self
291
291
  end
292
292
 
293
293
  # @return [String]
@@ -315,12 +315,12 @@ module PacketGen
315
315
  shb = parse_shb(SHB.new, io)
316
316
  raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
317
317
 
318
- to_parse = if shb.section_len.to_i != 0xffffffffffffffff
319
- # Section length is defined
320
- StringIO.new(io.read(shb.section_len.to_i))
321
- else
318
+ to_parse = if shb.section_len.to_i == 0xffffffffffffffff
322
319
  # section length is undefined
323
320
  io
321
+ else
322
+ # Section length is defined
323
+ StringIO.new(io.read(shb.section_len.to_i))
324
324
  end
325
325
 
326
326
  until to_parse.eof?
@@ -386,6 +386,7 @@ module PacketGen
386
386
  end
387
387
  end
388
388
 
389
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
389
390
  # Extract and check options for #array_to_file
390
391
  def array_to_file_options_from_hash(options)
391
392
  %i[filename arr ts].each do |deprecated_opt|
@@ -402,6 +403,7 @@ module PacketGen
402
403
 
403
404
  [filename, ary, ts, ts_inc, append]
404
405
  end
406
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
405
407
 
406
408
  def create_new_shb_section
407
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