packetgen 3.1.3 → 3.1.4

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/lib/packetgen.rb +24 -2
  3. data/lib/packetgen/capture.rb +30 -24
  4. data/lib/packetgen/config.rb +2 -2
  5. data/lib/packetgen/deprecation.rb +33 -7
  6. data/lib/packetgen/header.rb +2 -9
  7. data/lib/packetgen/header/arp.rb +2 -2
  8. data/lib/packetgen/header/asn1_base.rb +2 -2
  9. data/lib/packetgen/header/base.rb +2 -4
  10. data/lib/packetgen/header/bootp.rb +3 -3
  11. data/lib/packetgen/header/dhcp.rb +2 -2
  12. data/lib/packetgen/header/dhcp/option.rb +2 -2
  13. data/lib/packetgen/header/dhcp/options.rb +2 -2
  14. data/lib/packetgen/header/dhcpv6.rb +12 -12
  15. data/lib/packetgen/header/dhcpv6/duid.rb +8 -4
  16. data/lib/packetgen/header/dhcpv6/option.rb +4 -4
  17. data/lib/packetgen/header/dhcpv6/options.rb +2 -2
  18. data/lib/packetgen/header/dhcpv6/relay.rb +2 -2
  19. data/lib/packetgen/header/dns.rb +9 -9
  20. data/lib/packetgen/header/dns/name.rb +2 -2
  21. data/lib/packetgen/header/dns/opt.rb +2 -2
  22. data/lib/packetgen/header/dns/option.rb +2 -2
  23. data/lib/packetgen/header/dns/qdsection.rb +2 -2
  24. data/lib/packetgen/header/dns/question.rb +35 -35
  25. data/lib/packetgen/header/dns/rr.rb +3 -3
  26. data/lib/packetgen/header/dns/rrsection.rb +2 -2
  27. data/lib/packetgen/header/dot11.rb +5 -13
  28. data/lib/packetgen/header/dot11/control.rb +5 -5
  29. data/lib/packetgen/header/dot11/data.rb +2 -2
  30. data/lib/packetgen/header/dot11/element.rb +16 -16
  31. data/lib/packetgen/header/dot11/management.rb +2 -2
  32. data/lib/packetgen/header/dot11/sub_mngt.rb +2 -12
  33. data/lib/packetgen/header/dot1q.rb +2 -2
  34. data/lib/packetgen/header/dot1x.rb +6 -6
  35. data/lib/packetgen/header/eap.rb +16 -16
  36. data/lib/packetgen/header/eap/fast.rb +2 -2
  37. data/lib/packetgen/header/eap/md5.rb +2 -2
  38. data/lib/packetgen/header/eap/tls.rb +2 -2
  39. data/lib/packetgen/header/eap/ttls.rb +2 -2
  40. data/lib/packetgen/header/eth.rb +8 -5
  41. data/lib/packetgen/header/gre.rb +2 -2
  42. data/lib/packetgen/header/http.rb +2 -0
  43. data/lib/packetgen/header/http/headers.rb +2 -2
  44. data/lib/packetgen/header/http/request.rb +5 -5
  45. data/lib/packetgen/header/http/response.rb +6 -6
  46. data/lib/packetgen/header/http/verbs.rb +2 -2
  47. data/lib/packetgen/header/icmp.rb +2 -2
  48. data/lib/packetgen/header/icmpv6.rb +2 -2
  49. data/lib/packetgen/header/igmp.rb +4 -4
  50. data/lib/packetgen/header/igmpv3.rb +3 -3
  51. data/lib/packetgen/header/igmpv3/group_record.rb +6 -6
  52. data/lib/packetgen/header/igmpv3/mq.rb +2 -2
  53. data/lib/packetgen/header/igmpv3/mr.rb +2 -2
  54. data/lib/packetgen/header/ip.rb +3 -5
  55. data/lib/packetgen/header/ip/addr.rb +7 -2
  56. data/lib/packetgen/header/ip/option.rb +4 -6
  57. data/lib/packetgen/header/ip/options.rb +3 -5
  58. data/lib/packetgen/header/ipv6.rb +2 -2
  59. data/lib/packetgen/header/ipv6/addr.rb +7 -2
  60. data/lib/packetgen/header/ipv6/extension.rb +2 -2
  61. data/lib/packetgen/header/ipv6/hop_by_hop.rb +3 -3
  62. data/lib/packetgen/header/llc.rb +2 -2
  63. data/lib/packetgen/header/mdns.rb +2 -2
  64. data/lib/packetgen/header/mld.rb +2 -2
  65. data/lib/packetgen/header/mldv2.rb +2 -2
  66. data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -2
  67. data/lib/packetgen/header/mldv2/mlq.rb +2 -2
  68. data/lib/packetgen/header/mldv2/mlr.rb +2 -2
  69. data/lib/packetgen/header/ospfv2.rb +9 -9
  70. data/lib/packetgen/header/ospfv2/db_description.rb +2 -2
  71. data/lib/packetgen/header/ospfv2/hello.rb +2 -2
  72. data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -2
  73. data/lib/packetgen/header/ospfv2/ls_request.rb +2 -2
  74. data/lib/packetgen/header/ospfv2/ls_update.rb +2 -2
  75. data/lib/packetgen/header/ospfv2/lsa.rb +3 -5
  76. data/lib/packetgen/header/ospfv2/lsa_header.rb +6 -6
  77. data/lib/packetgen/header/ospfv3.rb +2 -2
  78. data/lib/packetgen/header/ospfv3/db_description.rb +2 -2
  79. data/lib/packetgen/header/ospfv3/hello.rb +2 -2
  80. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -2
  81. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
  82. data/lib/packetgen/header/ospfv3/ls_request.rb +2 -2
  83. data/lib/packetgen/header/ospfv3/ls_update.rb +2 -2
  84. data/lib/packetgen/header/ospfv3/lsa.rb +3 -5
  85. data/lib/packetgen/header/ospfv3/lsa_header.rb +7 -7
  86. data/lib/packetgen/header/snmp.rb +31 -28
  87. data/lib/packetgen/header/tcp.rb +3 -3
  88. data/lib/packetgen/header/tcp/option.rb +3 -5
  89. data/lib/packetgen/header/tcp/options.rb +2 -2
  90. data/lib/packetgen/header/tftp.rb +6 -6
  91. data/lib/packetgen/header/udp.rb +3 -3
  92. data/lib/packetgen/headerable.rb +5 -4
  93. data/lib/packetgen/inject.rb +23 -0
  94. data/lib/packetgen/inspect.rb +24 -5
  95. data/lib/packetgen/packet.rb +76 -51
  96. data/lib/packetgen/pcap.rb +29 -0
  97. data/lib/packetgen/pcapng.rb +2 -2
  98. data/lib/packetgen/pcapng/block.rb +12 -12
  99. data/lib/packetgen/pcapng/epb.rb +3 -7
  100. data/lib/packetgen/pcapng/file.rb +134 -95
  101. data/lib/packetgen/pcapng/idb.rb +30 -30
  102. data/lib/packetgen/pcapng/shb.rb +25 -34
  103. data/lib/packetgen/pcapng/spb.rb +4 -8
  104. data/lib/packetgen/pcapng/unknown_block.rb +2 -2
  105. data/lib/packetgen/pcaprub_wrapper.rb +67 -0
  106. data/lib/packetgen/proto.rb +2 -2
  107. data/lib/packetgen/types.rb +2 -0
  108. data/lib/packetgen/types/abstract_tlv.rb +24 -6
  109. data/lib/packetgen/types/array.rb +5 -5
  110. data/lib/packetgen/types/cstring.rb +2 -2
  111. data/lib/packetgen/types/enum.rb +3 -2
  112. data/lib/packetgen/types/fields.rb +5 -7
  113. data/lib/packetgen/types/int.rb +3 -5
  114. data/lib/packetgen/types/int_string.rb +2 -2
  115. data/lib/packetgen/types/length_from.rb +3 -3
  116. data/lib/packetgen/types/oui.rb +2 -2
  117. data/lib/packetgen/types/string.rb +2 -2
  118. data/lib/packetgen/types/tlv.rb +2 -2
  119. data/lib/packetgen/utils.rb +2 -2
  120. data/lib/packetgen/utils/arp_spoofer.rb +2 -2
  121. data/lib/packetgen/version.rb +3 -3
  122. metadata +26 -50
  123. data/.gitignore +0 -13
  124. data/.rubocop.yml +0 -30
  125. data/.travis.yml +0 -19
  126. data/Gemfile +0 -4
  127. data/Rakefile +0 -21
  128. data/packetgen.gemspec +0 -36
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of PacketGen
4
+ # See https://github.com/sdaubert/packetgen for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+ require_relative 'pcaprub_wrapper'
8
+
9
+ module PacketGen
10
+ # Module to read PCAP files
11
+ # @author Sylvain Daubert
12
+ # @api private
13
+ # @since 3.1.4
14
+ module Pcap
15
+ # Read a PCAP file
16
+ # @param [String] filename
17
+ # @return [Array<Packet>]
18
+ # @author Kent Gruber
19
+ def self.read(filename)
20
+ packets = []
21
+ PCAPRUBWrapper.read_pcap(filename: filename) do |packet|
22
+ next unless (packet = PacketGen.parse(packet.to_s))
23
+
24
+ packets << packet
25
+ end
26
+ packets
27
+ end
28
+ end
29
+ end
@@ -1,10 +1,10 @@
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
7
-
8
8
  require 'stringio'
9
9
 
10
10
  module PacketGen
@@ -1,10 +1,10 @@
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
7
-
8
8
  module PacketGen
9
9
  module PcapNG
10
10
  # @abstract Base class for all block types
@@ -34,7 +34,7 @@ module PacketGen
34
34
  # @return [Boolean]
35
35
  # @since 2.7.0
36
36
  def options?
37
- @fields.key?(:options) && @fields[:options].sz > 0
37
+ @fields.key?(:options) && @fields[:options].sz.positive?
38
38
  end
39
39
 
40
40
  # Calculate block length and update :block_len and block_len2 fields
@@ -49,9 +49,7 @@ module PacketGen
49
49
  # @return [void]
50
50
  def pad_field(*fields)
51
51
  fields.each do |field|
52
- unless (@fields[field].sz % 4).zero?
53
- @fields[field] << "\x00" * (4 - (@fields[field].sz % 4))
54
- end
52
+ @fields[field] << "\x00" * (4 - (@fields[field].sz % 4)) unless (@fields[field].sz % 4).zero?
55
53
  end
56
54
  end
57
55
 
@@ -62,9 +60,7 @@ module PacketGen
62
60
  # @param [:little, :big] endian
63
61
  # @return [:little, :big] returns endian
64
62
  def set_endianness(endian)
65
- unless %i[little big].include? endian
66
- raise ArgumentError, "unknown endianness for #{self.class}"
67
- end
63
+ raise ArgumentError, "unknown endianness for #{self.class}" unless %i[little big].include?(endian)
68
64
 
69
65
  @endian = endian
70
66
  @fields.each { |_f, v| v.endian = endian if v.is_a?(Types::Int) }
@@ -72,9 +68,13 @@ module PacketGen
72
68
  end
73
69
 
74
70
  def check_len_coherency
75
- unless self.block_len == self.block_len2
76
- raise InvalidFileError, 'Incoherency in Block length'
77
- end
71
+ raise InvalidFileError, 'Incoherency in Block length' unless self.block_len == self.block_len2
72
+ end
73
+
74
+ def to_io(str_or_io)
75
+ return str_or_io if str_or_io.respond_to? :read
76
+
77
+ StringIO.new(force_binary(str_or_io.to_s))
78
78
  end
79
79
  end
80
80
  end
@@ -1,10 +1,10 @@
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
7
-
8
8
  module PacketGen
9
9
  module PcapNG
10
10
  # {EPB} represents a Enhanced Packet Block (EPB) of a pcapng file.
@@ -82,11 +82,7 @@ module PacketGen
82
82
  # @param [::String,IO] str_or_io
83
83
  # @return [self]
84
84
  def read(str_or_io)
85
- io = if str_or_io.respond_to? :read
86
- str_or_io
87
- else
88
- StringIO.new(force_binary(str_or_io.to_s))
89
- end
85
+ io = to_io(str_or_io)
90
86
  return self if io.eof?
91
87
 
92
88
  self[:type].read io.read(4)
@@ -1,10 +1,10 @@
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
7
-
8
8
  module PacketGen
9
9
  module PcapNG
10
10
  # PcapNG::File is a complete Pcap-NG file handler.
@@ -20,6 +20,15 @@ module PacketGen
20
20
  LINKTYPE_IPV6 => 'IPv6'
21
21
  }.freeze
22
22
 
23
+ # @private
24
+ BLOCK_TYPES = Hash[
25
+ PcapNG.constants(false).select { |c| c.to_s =~ /_TYPE/ }.map do |c|
26
+ type_value = PcapNG.const_get(c).to_i
27
+ klass = PcapNG.const_get(c.to_s[0..-6]) # use delete_suffix('_TYPE') when support for Ruby 2.4 will stop
28
+ [type_value, klass]
29
+ end
30
+ ].freeze
31
+
23
32
  # Get file sections
24
33
  # @return [Array]
25
34
  attr_accessor :sections
@@ -57,9 +66,7 @@ module PacketGen
57
66
  # @return [Integer] return number of yielded blocks (only if a block is given)
58
67
  # @raise [ArgumentError] cannot read +fname+
59
68
  def readfile(fname, &blk)
60
- unless ::File.readable?(fname)
61
- raise ArgumentError, "cannot read file #{fname}"
62
- end
69
+ raise ArgumentError, "cannot read file #{fname}" unless ::File.readable?(fname)
63
70
 
64
71
  ::File.open(fname, 'rb') do |f|
65
72
  parse_section(f) until f.eof?
@@ -153,29 +160,28 @@ module PacketGen
153
160
 
154
161
  # Translates a {File} into an array of packets.
155
162
  # @param [Hash] options
156
- # @option options [String] :filename if given, object is cleared and filename
163
+ # @option options [String] :file if given, object is cleared and filename
157
164
  # is analyzed before generating array. Else, array is generated from +self+
158
- # @option options [String] :file same as +:filename+
159
165
  # @option options [Boolean] :keep_timestamps if +true+ (default value: +false+),
160
166
  # generates an array of hashes, each one with timestamp as key and packet
161
167
  # as value. There is one hash per packet.
162
- # @option options [Boolean] :keep_ts same as +:keep_timestamp+
163
168
  # @return [Array<Packet>,Array<Hash>]
164
169
  def file_to_array(options={})
170
+ Deprecation.deprecated_option(self.class, __method__, :filename) if options[:filename]
171
+ Deprecation.deprecated_option(self.class, __method__, :keep_ts) if options[:keep_ts]
172
+
165
173
  filename = options[:filename] || options[:file]
166
- if filename
167
- clear
168
- readfile filename
169
- end
174
+ reread filename
170
175
 
171
176
  ary = []
172
177
  @sections.each do |section|
173
178
  section.interfaces.each do |itf|
174
- if options[:keep_timestamps] || options[:keep_ts]
175
- ary.concat(itf.packets.map { |pkt| { pkt.timestamp => pkt.data.to_s } })
176
- else
177
- ary.concat(itf.packets.map { |pkt| pkt.data.to_s })
178
- end
179
+ blk = if options[:keep_timestamps] || options[:keep_ts]
180
+ proc { |pkt| { pkt.timestamp => pkt.data.to_s } }
181
+ else
182
+ proc { |pkt| pkt.data.to_s }
183
+ end
184
+ ary.concat(itf.packets.map(&blk))
179
185
  end
180
186
  end
181
187
  ary
@@ -219,7 +225,7 @@ module PacketGen
219
225
  # @overload array_to_file(options={})
220
226
  # Update {File} and/or write it to a file
221
227
  # @param [Hash] options
222
- # @option options [String] :filename file written on disk only if given
228
+ # @option options [String] :file file written on disk only if given
223
229
  # @option options [Array] :array can either be an array of packet data,
224
230
  # or a hash-value pair of timestamp => data.
225
231
  # @option options [Time] :timestamp set an initial timestamp
@@ -229,53 +235,15 @@ module PacketGen
229
235
  # the file
230
236
  # @return [Array] see return value from {#to_file}
231
237
  def array_to_file(options={})
232
- case options
233
- when Hash
234
- filename = options[:filename] || options[:file]
235
- ary = options[:array] || options[:arr]
236
- unless ary.is_a? Array
237
- raise ArgumentError, ':array parameter needs to be an array'
238
- end
239
- ts = options[:timestamp] || options[:ts] || Time.now
240
- ts_inc = options[:ts_inc] || 1
241
- append = !options[:append].nil?
242
- when Array
243
- ary = options
244
- ts = Time.now
245
- ts_inc = 1
246
- filename = nil
247
- append = false
248
- else
249
- raise ArgumentError, 'unknown argument. Need either a Hash or Array'
250
- end
238
+ filename, ary, ts, ts_inc, append = array_to_file_options(options)
251
239
 
252
- section = SHB.new
253
- @sections << section
254
- itf = IDB.new(endian: section.endian)
255
- classify_block section, itf
240
+ section = create_new_shb_section
241
+ ts_resol = section.interfaces.last.ts_resol
256
242
 
257
- ary.each_with_index do |pkt, i|
258
- case pkt
259
- when Hash
260
- this_ts = pkt.keys.first.to_i
261
- this_cap_len = pkt.values.first.to_s.size
262
- this_data = pkt.values.first.to_s
263
- else
264
- this_ts = (ts + ts_inc * i).to_i
265
- this_cap_len = pkt.to_s.size
266
- this_data = pkt.to_s
267
- end
268
- this_ts = (this_ts / itf.ts_resol).to_i
269
- this_tsh = this_ts >> 32
270
- this_tsl = this_ts & 0xffffffff
271
- this_pkt = EPB.new(endian: section.endian,
272
- interface_id: 0,
273
- tsh: this_tsh,
274
- tsl: this_tsl,
275
- cap_len: this_cap_len,
276
- orig_len: this_cap_len,
277
- data: this_data)
278
- classify_block section, this_pkt
243
+ ts_add_val = 0 # value to add to ts in Array case
244
+ ary.each do |pkt|
245
+ classify_block(section, epb_from_pkt(pkt, section.endian, ts, ts_resol, ts_add_val))
246
+ ts_add_val += ts_inc
279
247
  end
280
248
 
281
249
  if filename
@@ -288,53 +256,51 @@ module PacketGen
288
256
  private
289
257
 
290
258
  # Parse a section. A section is made of at least a SHB. It than may contain
291
- # others blocks, such as IDB, SPB or EPB.
259
+ # others blocks, such as IDB, SPB or EPB.
292
260
  # @param [IO] io
293
261
  # @return [void]
294
262
  def parse_section(io)
295
263
  shb = SHB.new
296
- type = Types::Int32.new(0, shb.endian).read(io.read(4))
297
- io.seek(-4, IO::SEEK_CUR)
298
- shb = parse(type, io, shb)
264
+ shb = parse_shb(shb, io)
299
265
  raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
300
266
 
301
- if shb.section_len.to_i != 0xffffffffffffffff
302
- # Section length is defined
303
- section = StringIO.new(io.read(shb.section_len.to_i))
304
- until section.eof?
305
- shb = @sections.last
306
- type = Types::Int32.new(0, shb.endian).read(section.read(4))
307
- section.seek(-4, IO::SEEK_CUR)
308
- parse(type, section, shb)
309
- end
310
- else
311
- # section length is undefined
312
- until io.eof?
313
- shb = @sections.last
314
- type = Types::Int32.new(0, shb.endian).read(io.read(4))
315
- io.seek(-4, IO::SEEK_CUR)
316
- parse(type, io, shb)
317
- end
267
+ to_parse = if shb.section_len.to_i != 0xffffffffffffffff
268
+ # Section length is defined
269
+ StringIO.new(io.read(shb.section_len.to_i))
270
+ else
271
+ # section length is undefined
272
+ io
273
+ end
274
+
275
+ until to_parse.eof?
276
+ shb = @sections.last
277
+ parse_shb shb, to_parse
318
278
  end
319
279
  end
320
280
 
281
+ # Parse a SHB
282
+ # @param [SHB] shb SHB to parse
283
+ # @param [IO] io stream from which parse SHB
284
+ # @return [SHB]
285
+ def parse_shb(shb, io)
286
+ type = Types::Int32.new(0, shb.endian).read(io.read(4))
287
+ io.seek(-4, IO::SEEK_CUR)
288
+ parse(type, io, shb)
289
+ end
290
+
321
291
  # Parse a block from its type
322
292
  # @param [Types::Int32] type
323
293
  # @param [IO] io stream from which parse block
324
294
  # @param [SHB] shb header of current section
325
- # @return [void]
295
+ # @return [Block]
326
296
  def parse(type, io, shb)
327
- types = PcapNG.constants(false).select { |c| c.to_s =~ /_TYPE/ }
328
- .map { |c| [PcapNG.const_get(c).to_i, c] }
329
- types = Hash[types]
330
-
331
- if types.key?(type.to_i)
332
- klass = PcapNG.const_get(types[type.to_i].to_s.gsub(/_TYPE/, '').to_sym)
333
- block = klass.new(endian: shb.endian)
334
- else
335
- block = UnknownBlock.new(endian: shb.endian)
336
- end
297
+ klass = if BLOCK_TYPES.key?(type.to_i)
298
+ BLOCK_TYPES[type.to_i]
299
+ else
300
+ UnknownBlock
301
+ end
337
302
 
303
+ block = klass.new(endian: shb.endian)
338
304
  classify_block shb, block
339
305
  block.read(io)
340
306
  end
@@ -361,6 +327,79 @@ module PacketGen
361
327
  block.section = shb
362
328
  end
363
329
  end
330
+
331
+ def array_to_file_options(options)
332
+ case options
333
+ when Hash
334
+ array_to_file_options_from_hash(options)
335
+ when Array
336
+ [nil, options, Time.now, 1, false]
337
+ else
338
+ raise ArgumentError, 'unknown argument. Need either a Hash or Array'
339
+ end
340
+ end
341
+
342
+ # Extract and check options for #array_to_file
343
+ def array_to_file_options_from_hash(options)
344
+ Deprecation.deprecated_option(self.class, :array_to_file, :filename) if options[:filename]
345
+ Deprecation.deprecated_option(self.class, :array_to_file, :arr) if options[:arr]
346
+ Deprecation.deprecated_option(self.class, :array_to_file, :ts) if options[:ts]
347
+
348
+ filename = options[:filename] || options[:file]
349
+ ary = options[:array] || options[:arr]
350
+ raise ArgumentError, ':array parameter needs to be an array' unless ary.is_a? Array
351
+
352
+ ts = options[:timestamp] || options[:ts] || Time.now
353
+ ts_inc = options[:ts_inc] || 1
354
+ append = !options[:append].nil?
355
+
356
+ [filename, ary, ts, ts_inc, append]
357
+ end
358
+
359
+ def create_new_shb_section
360
+ section = SHB.new
361
+ @sections << section
362
+ itf = IDB.new(endian: section.endian)
363
+ classify_block section, itf
364
+
365
+ section
366
+ end
367
+
368
+ # Compute tsh and tsl from ts
369
+ def calc_ts(timeslot, ts_resol)
370
+ this_ts = (timeslot / ts_resol).to_i
371
+ this_tsh = this_ts >> 32
372
+ this_tsl = this_ts & 0xffffffff
373
+
374
+ [this_tsh, this_tsl]
375
+ end
376
+
377
+ def reread(filename)
378
+ return if filename.nil?
379
+
380
+ clear
381
+ readfile filename
382
+ end
383
+
384
+ def epb_from_pkt(pkt, endian, ts, ts_resol, ts_add_val)
385
+ case pkt
386
+ when Hash
387
+ this_ts = pkt.keys.first.to_i
388
+ this_data = pkt.values.first.to_s
389
+ else
390
+ this_ts = (ts + ts_add_val).to_i
391
+ this_data = pkt.to_s
392
+ end
393
+ this_cap_len = this_data.size
394
+ this_tsh, this_tsl = calc_ts(this_ts, ts_resol)
395
+ EPB.new(endian: endian,
396
+ interface_id: 0,
397
+ tsh: this_tsh,
398
+ tsl: this_tsl,
399
+ cap_len: this_cap_len,
400
+ orig_len: this_cap_len,
401
+ data: this_data)
402
+ end
364
403
  end
365
404
  end
366
405
  end
@@ -1,10 +1,10 @@
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
7
-
8
8
  module PacketGen
9
9
  module PcapNG
10
10
  # {IDB} represents a Interface Description Block (IDB) of a pcapng file.
@@ -71,11 +71,7 @@ module PacketGen
71
71
  # @param [::String,IO] str_or_io
72
72
  # @return [self]
73
73
  def read(str_or_io)
74
- io = if str_or_io.respond_to? :read
75
- str_or_io
76
- else
77
- StringIO.new(force_binary(str_or_io.to_s))
78
- end
74
+ io = to_io(str_or_io)
79
75
  return self if io.eof?
80
76
 
81
77
  self[:type].read io.read(4)
@@ -105,29 +101,7 @@ module PacketGen
105
101
  if @options_decoded && !force
106
102
  @ts_resol
107
103
  else
108
- packstr = endian == :little ? 'v' : 'n'
109
- idx = 0
110
- options = self[:options]
111
-
112
- while idx < options.length
113
- opt_code, opt_len = options[idx, 4].unpack("#{packstr}2")
114
- if opt_code == OPTION_IF_TSRESOL && opt_len == 1
115
- tsresol = options[idx + 4, 1].unpack('C').first
116
- @ts_resol = if (tsresol & 0x80).zero?
117
- 10**-tsresol
118
- else
119
- 2**-(tsresol & 0x7f)
120
- end
121
-
122
- @options_decoded = true
123
- return @ts_resol
124
- else
125
- idx += 4 + opt_len
126
- end
127
- end
128
-
129
- @options_decoded = true
130
- @ts_resol = 1E-6 # default value
104
+ decode_ts_resol
131
105
  end
132
106
  end
133
107
 
@@ -138,6 +112,32 @@ module PacketGen
138
112
  recalc_block_len
139
113
  super << @packets.map(&:to_s).join
140
114
  end
115
+
116
+ private
117
+
118
+ def decode_ts_resol
119
+ tsresol = search_for_ts_resol_opt(self[:options])
120
+ @options_decoded = true
121
+ return @ts_resol = 1E-6 if tsresol.nil?
122
+
123
+ @ts_resol = if (tsresol & 0x80).zero?
124
+ 10**-tsresol
125
+ else
126
+ 2**-(tsresol & 0x7f)
127
+ end
128
+ end
129
+
130
+ def search_for_ts_resol_opt(options)
131
+ packstr = endian == :little ? 'v' : 'n'
132
+ idx = 0
133
+
134
+ while idx < options.length
135
+ opt_code, opt_len = options[idx, 4].unpack("#{packstr}2")
136
+ return options[idx + 4, 1].unpack('C').first if opt_code == OPTION_IF_TSRESOL && opt_len == 1
137
+
138
+ idx += 4 + opt_len
139
+ end
140
+ end
141
141
  end
142
142
  end
143
143
  end