packetgen 3.1.4 → 3.2.0
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.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/bin/pgconsole +1 -0
- data/lib/packetgen.rb +19 -3
- data/lib/packetgen/capture.rb +30 -9
- data/lib/packetgen/config.rb +15 -9
- data/lib/packetgen/deprecation.rb +1 -1
- data/lib/packetgen/header/asn1_base.rb +19 -9
- data/lib/packetgen/header/base.rb +68 -70
- data/lib/packetgen/header/dhcpv6/duid.rb +3 -1
- data/lib/packetgen/header/dhcpv6/option.rb +4 -12
- data/lib/packetgen/header/dns/name.rb +18 -7
- data/lib/packetgen/header/dns/qdsection.rb +1 -1
- data/lib/packetgen/header/dns/question.rb +2 -0
- data/lib/packetgen/header/dot11.rb +25 -38
- data/lib/packetgen/header/dot11/data.rb +28 -34
- data/lib/packetgen/header/dot1x.rb +1 -14
- data/lib/packetgen/header/eap.rb +14 -17
- data/lib/packetgen/header/eth.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +4 -2
- data/lib/packetgen/header/http/request.rb +37 -18
- data/lib/packetgen/header/http/response.rb +11 -5
- data/lib/packetgen/header/http/verbs.rb +1 -1
- data/lib/packetgen/header/igmpv3/group_record.rb +2 -0
- data/lib/packetgen/header/ip.rb +27 -26
- data/lib/packetgen/header/ip/addr.rb +3 -1
- data/lib/packetgen/header/ip/option.rb +4 -4
- data/lib/packetgen/header/ipv6/addr.rb +2 -0
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -0
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -3
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -0
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv3/lsa.rb +9 -3
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
- data/lib/packetgen/header/snmp.rb +3 -2
- data/lib/packetgen/header/tcp.rb +1 -20
- data/lib/packetgen/header/tcp/option.rb +8 -6
- data/lib/packetgen/inspect.rb +1 -17
- data/lib/packetgen/packet.rb +10 -6
- data/lib/packetgen/pcapng.rb +11 -11
- data/lib/packetgen/pcapng/block.rb +15 -2
- data/lib/packetgen/pcapng/epb.rb +22 -15
- data/lib/packetgen/pcapng/file.rb +166 -81
- data/lib/packetgen/pcapng/idb.rb +7 -9
- data/lib/packetgen/pcapng/shb.rb +35 -28
- data/lib/packetgen/pcapng/spb.rb +16 -12
- data/lib/packetgen/pcapng/unknown_block.rb +3 -11
- data/lib/packetgen/pcaprub_wrapper.rb +25 -11
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/abstract_tlv.rb +3 -1
- data/lib/packetgen/types/array.rb +17 -10
- data/lib/packetgen/types/cstring.rb +56 -19
- data/lib/packetgen/types/enum.rb +4 -0
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +180 -113
- data/lib/packetgen/types/int.rb +15 -1
- data/lib/packetgen/types/int_string.rb +8 -0
- data/lib/packetgen/types/length_from.rb +18 -10
- data/lib/packetgen/types/oui.rb +2 -0
- data/lib/packetgen/types/string.rb +58 -7
- data/lib/packetgen/types/tlv.rb +2 -0
- data/lib/packetgen/unknown_packet.rb +84 -0
- data/lib/packetgen/utils.rb +6 -7
- data/lib/packetgen/version.rb +1 -1
- metadata +18 -15
data/lib/packetgen/packet.rb
CHANGED
@@ -6,6 +6,8 @@
|
|
6
6
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
7
7
|
# This program is published under MIT license.
|
8
8
|
|
9
|
+
# rubocop:disable Metrics/ClassLength
|
10
|
+
|
9
11
|
module PacketGen
|
10
12
|
# An object of type {Packet} handles a network packet. This packet may contain
|
11
13
|
# multiple protocol headers, starting from MAC layer or from Network (OSI) layer.
|
@@ -77,10 +79,10 @@ module PacketGen
|
|
77
79
|
# @yieldparam [Packet,String] packet if a block is given, yield each
|
78
80
|
# captured packet (Packet or raw data String, depending on +:parse+ option)
|
79
81
|
# @return [Array<Packet>] captured packet
|
80
|
-
def self.capture(**kwargs)
|
81
|
-
capture = Capture.new(kwargs)
|
82
|
-
if
|
83
|
-
capture.start
|
82
|
+
def self.capture(**kwargs, &block)
|
83
|
+
capture = Capture.new(**kwargs)
|
84
|
+
if block
|
85
|
+
capture.start(&block)
|
84
86
|
else
|
85
87
|
capture.start
|
86
88
|
end
|
@@ -214,7 +216,7 @@ module PacketGen
|
|
214
216
|
# @return [Array] see return from {PcapNG::File#to_file}
|
215
217
|
# @see File
|
216
218
|
def to_f(filename)
|
217
|
-
PcapNG::File.new.
|
219
|
+
PcapNG::File.new.read_array([self]).to_f(filename)
|
218
220
|
end
|
219
221
|
alias write to_f
|
220
222
|
|
@@ -285,7 +287,7 @@ module PacketGen
|
|
285
287
|
if first_header.nil?
|
286
288
|
# No decoding forced for first header. Have to guess it!
|
287
289
|
first_header = guess_first_header(binary_str)
|
288
|
-
raise ParseError,
|
290
|
+
raise ParseError, "cannot identify first header in string: #{binary_str.inspect}" if first_header.nil?
|
289
291
|
end
|
290
292
|
|
291
293
|
add first_header
|
@@ -522,5 +524,7 @@ module PacketGen
|
|
522
524
|
end
|
523
525
|
end
|
524
526
|
|
527
|
+
# rubocop:enable Metrics/ClassLength
|
528
|
+
|
525
529
|
require_relative 'headerable'
|
526
530
|
require_relative 'header'
|
data/lib/packetgen/pcapng.rb
CHANGED
@@ -13,13 +13,13 @@ module PacketGen
|
|
13
13
|
# @author Sylvain Daubert
|
14
14
|
module PcapNG
|
15
15
|
# Section Header Block type number
|
16
|
-
SHB_TYPE = Types::Int32.new(0x0A0D0D0A, :little)
|
16
|
+
SHB_TYPE = Types::Int32.new(0x0A0D0D0A, :little).freeze
|
17
17
|
# Interface Description Block type number
|
18
|
-
IDB_TYPE = Types::Int32.new(1, :little)
|
18
|
+
IDB_TYPE = Types::Int32.new(1, :little).freeze
|
19
19
|
# Simple Packet Block type number
|
20
|
-
SPB_TYPE = Types::Int32.new(3, :little)
|
20
|
+
SPB_TYPE = Types::Int32.new(3, :little).freeze
|
21
21
|
# Enhanced Packet Block type number
|
22
|
-
EPB_TYPE = Types::Int32.new(6, :little)
|
22
|
+
EPB_TYPE = Types::Int32.new(6, :little).freeze
|
23
23
|
|
24
24
|
# IEEE 802.3 Ethernet (10Mb, 100Mb, 1000Mb, and up)
|
25
25
|
LINKTYPE_ETHERNET = 1
|
@@ -46,10 +46,10 @@ module PacketGen
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
require_relative 'pcapng/block
|
50
|
-
require_relative 'pcapng/unknown_block
|
51
|
-
require_relative 'pcapng/shb
|
52
|
-
require_relative 'pcapng/idb
|
53
|
-
require_relative 'pcapng/epb
|
54
|
-
require_relative 'pcapng/spb
|
55
|
-
require_relative 'pcapng/file
|
49
|
+
require_relative 'pcapng/block'
|
50
|
+
require_relative 'pcapng/unknown_block'
|
51
|
+
require_relative 'pcapng/shb'
|
52
|
+
require_relative 'pcapng/idb'
|
53
|
+
require_relative 'pcapng/epb'
|
54
|
+
require_relative 'pcapng/spb'
|
55
|
+
require_relative 'pcapng/file'
|
@@ -49,7 +49,9 @@ module PacketGen
|
|
49
49
|
# @return [void]
|
50
50
|
def pad_field(*fields)
|
51
51
|
fields.each do |field|
|
52
|
-
|
52
|
+
obj = @fields[field]
|
53
|
+
pad_size = (obj.sz % 4).zero? ? 0 : (4 - (obj.sz % 4))
|
54
|
+
obj << "\x00" * pad_size
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
@@ -59,7 +61,7 @@ module PacketGen
|
|
59
61
|
# Must be called by all subclass #initialize method.
|
60
62
|
# @param [:little, :big] endian
|
61
63
|
# @return [:little, :big] returns endian
|
62
|
-
def
|
64
|
+
def endianness(endian)
|
63
65
|
raise ArgumentError, "unknown endianness for #{self.class}" unless %i[little big].include?(endian)
|
64
66
|
|
65
67
|
@endian = endian
|
@@ -76,6 +78,17 @@ module PacketGen
|
|
76
78
|
|
77
79
|
StringIO.new(force_binary(str_or_io.to_s))
|
78
80
|
end
|
81
|
+
|
82
|
+
def remove_padding(io, data_len)
|
83
|
+
data_pad_len = (4 - (data_len % 4)) % 4
|
84
|
+
io.read data_pad_len
|
85
|
+
data_pad_len
|
86
|
+
end
|
87
|
+
|
88
|
+
def read_blocklen2_and_check(io)
|
89
|
+
self[:block_len2].read io.read(4)
|
90
|
+
check_len_coherency
|
91
|
+
end
|
79
92
|
end
|
80
93
|
end
|
81
94
|
end
|
data/lib/packetgen/pcapng/epb.rb
CHANGED
@@ -73,7 +73,7 @@ module PacketGen
|
|
73
73
|
# @option options [Integer] :block_len2 block total length
|
74
74
|
def initialize(options={})
|
75
75
|
super
|
76
|
-
|
76
|
+
endianness(options[:endian] || :little)
|
77
77
|
recalc_block_len
|
78
78
|
self.type = options[:type] || PcapNG::EPB_TYPE.to_i
|
79
79
|
end
|
@@ -85,22 +85,13 @@ module PacketGen
|
|
85
85
|
io = to_io(str_or_io)
|
86
86
|
return self if io.eof?
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
self[:tsh].read io.read(4)
|
92
|
-
self[:tsl].read io.read(4)
|
93
|
-
self[:cap_len].read io.read(4)
|
94
|
-
self[:orig_len].read io.read(4)
|
88
|
+
%i[type block_len interface_id tsh tsl cap_len orig_len].each do |attr|
|
89
|
+
self[attr].read io.read(self[attr].sz)
|
90
|
+
end
|
95
91
|
self[:data].read io.read(self.cap_len)
|
96
|
-
|
97
|
-
io
|
98
|
-
options_len = self.block_len - self.cap_len - data_pad_len
|
99
|
-
options_len -= MIN_SIZE
|
100
|
-
self[:options].read io.read(options_len)
|
101
|
-
self[:block_len2].read io.read(4)
|
92
|
+
read_options(io)
|
93
|
+
read_blocklen2_and_check(io)
|
102
94
|
|
103
|
-
check_len_coherency
|
104
95
|
self
|
105
96
|
end
|
106
97
|
|
@@ -110,6 +101,16 @@ module PacketGen
|
|
110
101
|
Time.at((self.tsh << 32 | self.tsl) * ts_resol)
|
111
102
|
end
|
112
103
|
|
104
|
+
# Set timestamp from a Time object
|
105
|
+
# @param [Time] time
|
106
|
+
# @return [Time] time
|
107
|
+
def timestamp=(time)
|
108
|
+
tstamp = (time.to_r / ts_resol).to_i
|
109
|
+
self.tsh = (tstamp & 0xffffffff00000000) >> 32
|
110
|
+
self.tsl = tstamp & 0xffffffff
|
111
|
+
time
|
112
|
+
end
|
113
|
+
|
113
114
|
# Return the object as a String
|
114
115
|
# @return [String]
|
115
116
|
def to_s
|
@@ -127,6 +128,12 @@ module PacketGen
|
|
127
128
|
@interface.ts_resol
|
128
129
|
end
|
129
130
|
end
|
131
|
+
|
132
|
+
def read_options(io)
|
133
|
+
data_pad_len = remove_padding(io, self.cap_len)
|
134
|
+
options_len = self.block_len - self.cap_len - data_pad_len - MIN_SIZE
|
135
|
+
self[:options].read io.read(options_len)
|
136
|
+
end
|
130
137
|
end
|
131
138
|
end
|
132
139
|
end
|
@@ -22,9 +22,9 @@ module PacketGen
|
|
22
22
|
|
23
23
|
# @private
|
24
24
|
BLOCK_TYPES = Hash[
|
25
|
-
PcapNG.constants(false).select { |c| c.to_s
|
25
|
+
PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.map do |c|
|
26
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
|
27
|
+
klass = PcapNG.const_get(c.to_s[0..-6]) # @todo use delete_suffix('_TYPE') when support for Ruby 2.4 will stop
|
28
28
|
[type_value, klass]
|
29
29
|
end
|
30
30
|
].freeze
|
@@ -68,20 +68,13 @@ module PacketGen
|
|
68
68
|
def readfile(fname, &blk)
|
69
69
|
raise ArgumentError, "cannot read file #{fname}" unless ::File.readable?(fname)
|
70
70
|
|
71
|
-
::File.open(fname, 'rb')
|
72
|
-
parse_section(f) until f.eof?
|
73
|
-
end
|
74
|
-
|
71
|
+
::File.open(fname, 'rb') { |f| parse_section(f) until f.eof? }
|
75
72
|
return unless blk
|
76
73
|
|
77
74
|
count = 0
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
count += 1
|
82
|
-
yield pkt
|
83
|
-
end
|
84
|
-
end
|
75
|
+
each_packet_with_interface do |pkt, _itf|
|
76
|
+
count += 1
|
77
|
+
yield pkt
|
85
78
|
end
|
86
79
|
count
|
87
80
|
end
|
@@ -98,12 +91,10 @@ module PacketGen
|
|
98
91
|
# @return [Integer] number of packets
|
99
92
|
# @raise [ArgumentError] cannot read +fname+
|
100
93
|
def read_packet_bytes(fname, &blk)
|
101
|
-
count = 0
|
102
94
|
packets = [] unless blk
|
103
95
|
|
104
|
-
readfile(fname) do |packet|
|
96
|
+
count = readfile(fname) do |packet|
|
105
97
|
if blk
|
106
|
-
count += 1
|
107
98
|
yield packet.data.to_s, packet.interface.link_type
|
108
99
|
else
|
109
100
|
packets << packet.data.to_s
|
@@ -124,19 +115,11 @@ module PacketGen
|
|
124
115
|
# @return [Integer] number of packets
|
125
116
|
# @raise [ArgumentError] cannot read +fname+
|
126
117
|
def read_packets(fname, &blk)
|
127
|
-
count = 0
|
128
118
|
packets = [] unless blk
|
129
119
|
|
130
|
-
read_packet_bytes(fname) do |packet, link_type|
|
131
|
-
|
132
|
-
parsed_pkt = if first_header.nil?
|
133
|
-
# unknown link type, try to guess
|
134
|
-
Packet.parse(packet)
|
135
|
-
else
|
136
|
-
Packet.parse(packet, first_header: first_header)
|
137
|
-
end
|
120
|
+
count = read_packet_bytes(fname) do |packet, link_type|
|
121
|
+
parsed_pkt = parse_packet(packet, link_type)
|
138
122
|
if blk
|
139
|
-
count += 1
|
140
123
|
yield parsed_pkt
|
141
124
|
else
|
142
125
|
packets << parsed_pkt
|
@@ -158,6 +141,8 @@ module PacketGen
|
|
158
141
|
@sections.clear
|
159
142
|
end
|
160
143
|
|
144
|
+
# @deprecated
|
145
|
+
# Prefer use of {#to_a} or {#to_h}.
|
161
146
|
# Translates a {File} into an array of packets.
|
162
147
|
# @param [Hash] options
|
163
148
|
# @option options [String] :file if given, object is cleared and filename
|
@@ -167,37 +152,59 @@ module PacketGen
|
|
167
152
|
# as value. There is one hash per packet.
|
168
153
|
# @return [Array<Packet>,Array<Hash>]
|
169
154
|
def file_to_array(options={})
|
170
|
-
Deprecation.
|
171
|
-
Deprecation.deprecated_option(self.class, __method__, :keep_ts) if options[:keep_ts]
|
155
|
+
Deprecation.deprecated(self.class, __method__)
|
172
156
|
|
173
|
-
|
174
|
-
reread
|
157
|
+
file = options[:file] || options[:filename]
|
158
|
+
reread file
|
175
159
|
|
176
160
|
ary = []
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
ary.concat(itf.packets.map(&blk))
|
185
|
-
end
|
161
|
+
blk = if options[:keep_timestamps] || options[:keep_ts]
|
162
|
+
proc { |pkt| { pkt.timestamp => pkt.data.to_s } }
|
163
|
+
else
|
164
|
+
proc { |pkt| pkt.data.to_s }
|
165
|
+
end
|
166
|
+
each_packet_with_interface do |pkt, _itf|
|
167
|
+
ary << blk.call(pkt)
|
186
168
|
end
|
169
|
+
|
170
|
+
ary
|
171
|
+
end
|
172
|
+
|
173
|
+
# Translates a {File} into an array of packets.
|
174
|
+
# @return [Array<Packet>]
|
175
|
+
# @since 3.1.6
|
176
|
+
def to_a
|
177
|
+
ary = []
|
178
|
+
each_packet_with_interface do |pkt, itf|
|
179
|
+
ary << parse_packet(pkt.data.to_s, itf.link_type)
|
180
|
+
end
|
181
|
+
|
187
182
|
ary
|
188
183
|
end
|
189
184
|
|
185
|
+
# Translates a {File} into a hash with timestamps as keys.
|
186
|
+
# @note Only packets from {EPB} sections are extracted, as {SPB} ones do not have timestamp.
|
187
|
+
# @return [Hash{Time => Packet}]
|
188
|
+
# @since 3.1.6
|
189
|
+
def to_h
|
190
|
+
hsh = {}
|
191
|
+
each_packet_with_interface do |pkt, itf|
|
192
|
+
next if pkt.is_a?(SPB)
|
193
|
+
|
194
|
+
hsh[pkt.timestamp] = parse_packet(pkt.data.to_s, itf.link_type)
|
195
|
+
end
|
196
|
+
|
197
|
+
hsh
|
198
|
+
end
|
199
|
+
|
190
200
|
# Writes the {File} to a file.
|
191
201
|
# @param [Hash] options
|
192
202
|
# @option options [Boolean] :append (default: +false+) if set to +true+,
|
193
203
|
# the packets are appended to the file, rather than overwriting it
|
194
204
|
# @return [Array] array of 2 elements: filename and size written
|
205
|
+
# @todo for 4.0, replace +options+ by +append+ kwarg
|
195
206
|
def to_file(filename, options={})
|
196
|
-
mode =
|
197
|
-
'ab'
|
198
|
-
else
|
199
|
-
'wb'
|
200
|
-
end
|
207
|
+
mode = (options[:append] && ::File.exist?(filename)) ? 'ab' : 'wb'
|
201
208
|
::File.open(filename, mode) { |f| f.write(self.to_s) }
|
202
209
|
[filename, self.to_s.size]
|
203
210
|
end
|
@@ -217,6 +224,7 @@ module PacketGen
|
|
217
224
|
self.to_file(filename.to_s, append: true)
|
218
225
|
end
|
219
226
|
|
227
|
+
# @deprecated Prefer use of {#read_array} or {#read_hash}.
|
220
228
|
# @overload array_to_file(ary)
|
221
229
|
# Update {File} object with packets.
|
222
230
|
# @param [Array] ary as generated by {#file_to_array} or Array of Packet objects.
|
@@ -238,12 +246,10 @@ module PacketGen
|
|
238
246
|
filename, ary, ts, ts_inc, append = array_to_file_options(options)
|
239
247
|
|
240
248
|
section = create_new_shb_section
|
241
|
-
ts_resol = section.interfaces.last.ts_resol
|
242
249
|
|
243
|
-
ts_add_val = 0 # value to add to ts in Array case
|
244
250
|
ary.each do |pkt|
|
245
|
-
classify_block(section, epb_from_pkt(pkt, section
|
246
|
-
|
251
|
+
classify_block(section, epb_from_pkt(pkt, section, ts))
|
252
|
+
ts += ts_inc
|
247
253
|
end
|
248
254
|
|
249
255
|
if filename
|
@@ -253,6 +259,54 @@ module PacketGen
|
|
253
259
|
end
|
254
260
|
end
|
255
261
|
|
262
|
+
# Update current object from an array of packets
|
263
|
+
# @param [Array<Packet>] packets
|
264
|
+
# @param [Time, nil] timestamp initial timestamp, used for first packet
|
265
|
+
# @param [Numeric, nil] ts_inc timestamp increment, in seconds, to increment
|
266
|
+
# initial timestamp for each packet
|
267
|
+
# @return [self]
|
268
|
+
# @note if +timestamp+ and/or +ts_inc+ are nil, {SPB} sections are created
|
269
|
+
# for each packet, else {EPB} ones are used
|
270
|
+
# @since 3.1.6
|
271
|
+
def read_array(packets, timestamp: nil, ts_inc: nil)
|
272
|
+
ts = timestamp
|
273
|
+
section = create_new_shb_section
|
274
|
+
packets.each do |pkt|
|
275
|
+
block = create_block_from_pkt(pkt, section, ts, ts_inc)
|
276
|
+
classify_block(section, block)
|
277
|
+
ts = update_ts(ts, ts_inc)
|
278
|
+
end
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
# Update current object from a hash of packets and timestamps
|
283
|
+
# @param [Hash{Time => Packet}] hsh
|
284
|
+
# @return [self]
|
285
|
+
# @since 3.1.6
|
286
|
+
def read_hash(hsh)
|
287
|
+
section = create_new_shb_section
|
288
|
+
hsh.each do |ts, pkt|
|
289
|
+
block = create_block_from_pkt(pkt, section, ts, 0)
|
290
|
+
classify_block(section, block)
|
291
|
+
end
|
292
|
+
self
|
293
|
+
end
|
294
|
+
|
295
|
+
# @return [String]
|
296
|
+
# @since 3.1.6
|
297
|
+
def inspect
|
298
|
+
str = +''
|
299
|
+
sections.each do |section|
|
300
|
+
str << section.inspect
|
301
|
+
section.interfaces.each do |itf|
|
302
|
+
str << itf.inspect
|
303
|
+
itf.packets.each { |block| str << block.inspect }
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
str
|
308
|
+
end
|
309
|
+
|
256
310
|
private
|
257
311
|
|
258
312
|
# Parse a section. A section is made of at least a SHB. It than may contain
|
@@ -260,8 +314,7 @@ module PacketGen
|
|
260
314
|
# @param [IO] io
|
261
315
|
# @return [void]
|
262
316
|
def parse_section(io)
|
263
|
-
shb = SHB.new
|
264
|
-
shb = parse_shb(shb, io)
|
317
|
+
shb = parse_shb(SHB.new, io)
|
265
318
|
raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
|
266
319
|
|
267
320
|
to_parse = if shb.section_len.to_i != 0xffffffffffffffff
|
@@ -294,17 +347,18 @@ module PacketGen
|
|
294
347
|
# @param [SHB] shb header of current section
|
295
348
|
# @return [Block]
|
296
349
|
def parse(type, io, shb)
|
297
|
-
|
298
|
-
BLOCK_TYPES[type.to_i]
|
299
|
-
else
|
300
|
-
UnknownBlock
|
301
|
-
end
|
302
|
-
|
303
|
-
block = klass.new(endian: shb.endian)
|
350
|
+
block = guess_block_type(type).new(endian: shb.endian)
|
304
351
|
classify_block shb, block
|
305
352
|
block.read(io)
|
306
353
|
end
|
307
354
|
|
355
|
+
# Guess class to use from type
|
356
|
+
# @param [Types::Int] type
|
357
|
+
# @return [Block]
|
358
|
+
def guess_block_type(type)
|
359
|
+
BLOCK_TYPES.key?(type.to_i) ? BLOCK_TYPES[type.to_i] : UnknownBlock
|
360
|
+
end
|
361
|
+
|
308
362
|
# Classify block from its type
|
309
363
|
# @param [SHB] shb header of current section
|
310
364
|
# @param [Block] block block to classify
|
@@ -315,16 +369,11 @@ module PacketGen
|
|
315
369
|
@sections << block
|
316
370
|
when IDB
|
317
371
|
shb << block
|
318
|
-
|
319
|
-
|
320
|
-
shb.interfaces[
|
321
|
-
block.interface = shb.interfaces[block.interface_id]
|
322
|
-
when SPB
|
323
|
-
shb.interfaces[0] << block
|
324
|
-
block.interface = shb.interfaces[0]
|
372
|
+
when SPB, EPB
|
373
|
+
ifid = block.is_a?(EPB) ? block.interface_id : 0
|
374
|
+
shb.interfaces[ifid] << block
|
325
375
|
else
|
326
|
-
shb.
|
327
|
-
block.section = shb
|
376
|
+
shb.add_unknown_block(block)
|
328
377
|
end
|
329
378
|
end
|
330
379
|
|
@@ -341,9 +390,9 @@ module PacketGen
|
|
341
390
|
|
342
391
|
# Extract and check options for #array_to_file
|
343
392
|
def array_to_file_options_from_hash(options)
|
344
|
-
|
345
|
-
|
346
|
-
|
393
|
+
%i[filename arr ts].each do |deprecated_opt|
|
394
|
+
Deprecation.deprecated_option(self.class, :array_to_file, deprecated_opt) if options[deprecated_opt]
|
395
|
+
end
|
347
396
|
|
348
397
|
filename = options[:filename] || options[:file]
|
349
398
|
ary = options[:array] || options[:arr]
|
@@ -368,10 +417,8 @@ module PacketGen
|
|
368
417
|
# Compute tsh and tsl from ts
|
369
418
|
def calc_ts(timeslot, ts_resol)
|
370
419
|
this_ts = (timeslot / ts_resol).to_i
|
371
|
-
this_tsh = this_ts >> 32
|
372
|
-
this_tsl = this_ts & 0xffffffff
|
373
420
|
|
374
|
-
[
|
421
|
+
[this_ts >> 32, this_ts & 0xffffffff]
|
375
422
|
end
|
376
423
|
|
377
424
|
def reread(filename)
|
@@ -381,18 +428,34 @@ module PacketGen
|
|
381
428
|
readfile filename
|
382
429
|
end
|
383
430
|
|
384
|
-
def
|
385
|
-
|
386
|
-
|
387
|
-
this_ts = pkt.keys.first.to_i
|
388
|
-
this_data = pkt.values.first.to_s
|
431
|
+
def create_block_from_pkt(pkt, section, timestamp, ts_inc)
|
432
|
+
if timestamp.nil? || ts_inc.nil?
|
433
|
+
spb_from_pkt(pkt, section)
|
389
434
|
else
|
390
|
-
|
391
|
-
this_data = pkt.to_s
|
435
|
+
epb_from_pkt(pkt, section, timestamp)
|
392
436
|
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def spb_from_pkt(pkt, section)
|
440
|
+
pkt_s = pkt.to_s
|
441
|
+
size = pkt_s.size
|
442
|
+
SPB.new(endian: section.endian,
|
443
|
+
block_len: size,
|
444
|
+
orig_len: size,
|
445
|
+
data: pkt_s)
|
446
|
+
end
|
447
|
+
|
448
|
+
# @todo remove hash case when #array_to_file will be removed
|
449
|
+
def epb_from_pkt(pkt, section, timestamp)
|
450
|
+
this_ts, this_data = case pkt
|
451
|
+
when Hash
|
452
|
+
[pkt.keys.first.to_i, pkt.values.first.to_s]
|
453
|
+
else
|
454
|
+
[timestamp.to_r, pkt.to_s]
|
455
|
+
end
|
393
456
|
this_cap_len = this_data.size
|
394
|
-
this_tsh, this_tsl = calc_ts(this_ts, ts_resol)
|
395
|
-
EPB.new(endian: endian,
|
457
|
+
this_tsh, this_tsl = calc_ts(this_ts, section.interfaces.last.ts_resol)
|
458
|
+
EPB.new(endian: section.endian,
|
396
459
|
interface_id: 0,
|
397
460
|
tsh: this_tsh,
|
398
461
|
tsl: this_tsl,
|
@@ -400,6 +463,28 @@ module PacketGen
|
|
400
463
|
orig_len: this_cap_len,
|
401
464
|
data: this_data)
|
402
465
|
end
|
466
|
+
|
467
|
+
def update_ts(timestamp, ts_inc)
|
468
|
+
return nil if timestamp.nil? || ts_inc.nil?
|
469
|
+
|
470
|
+
timestamp + ts_inc
|
471
|
+
end
|
472
|
+
|
473
|
+
# Iterate over each xPB with its associated interface
|
474
|
+
# @return [void]
|
475
|
+
# @yieldparam [String] xpb
|
476
|
+
# @yieldparam [IDB] itf
|
477
|
+
def each_packet_with_interface
|
478
|
+
sections.each do |section|
|
479
|
+
section.interfaces.each do |itf|
|
480
|
+
itf.packets.each { |xpb| yield xpb, itf }
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
def parse_packet(data, link_type)
|
486
|
+
Packet.parse(data, first_header: KNOWN_LINK_TYPES[link_type])
|
487
|
+
end
|
403
488
|
end
|
404
489
|
end
|
405
490
|
end
|