packetgen 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/packetgen/header/arp.rb +54 -125
- data/lib/packetgen/header/base.rb +175 -0
- data/lib/packetgen/header/dns/name.rb +110 -0
- data/lib/packetgen/header/dns/opt.rb +137 -0
- data/lib/packetgen/header/dns/option.rb +17 -0
- data/lib/packetgen/header/dns/qdsection.rb +39 -0
- data/lib/packetgen/header/dns/question.rb +129 -0
- data/lib/packetgen/header/dns/rr.rb +89 -0
- data/lib/packetgen/header/dns/rrsection.rb +72 -0
- data/lib/packetgen/header/dns.rb +276 -0
- data/lib/packetgen/header/esp.rb +38 -70
- data/lib/packetgen/header/eth.rb +35 -106
- data/lib/packetgen/header/icmp.rb +19 -70
- data/lib/packetgen/header/icmpv6.rb +3 -3
- data/lib/packetgen/header/ip.rb +54 -210
- data/lib/packetgen/header/ipv6.rb +73 -164
- data/lib/packetgen/header/tcp/option.rb +34 -50
- data/lib/packetgen/header/tcp/options.rb +19 -20
- data/lib/packetgen/header/tcp.rb +66 -129
- data/lib/packetgen/header/udp.rb +31 -88
- data/lib/packetgen/header.rb +5 -10
- data/lib/packetgen/inspect.rb +5 -4
- data/lib/packetgen/packet.rb +74 -57
- data/lib/packetgen/pcapng/block.rb +49 -7
- data/lib/packetgen/pcapng/epb.rb +36 -34
- data/lib/packetgen/pcapng/file.rb +24 -8
- data/lib/packetgen/pcapng/idb.rb +28 -33
- data/lib/packetgen/pcapng/shb.rb +35 -39
- data/lib/packetgen/pcapng/spb.rb +18 -27
- data/lib/packetgen/pcapng/unknown_block.rb +11 -21
- data/lib/packetgen/pcapng.rb +9 -7
- data/lib/packetgen/types/array.rb +56 -0
- data/lib/packetgen/types/fields.rb +325 -0
- data/lib/packetgen/types/int.rb +164 -0
- data/lib/packetgen/types/int_string.rb +69 -0
- data/lib/packetgen/types/string.rb +36 -0
- data/lib/packetgen/types/tlv.rb +41 -0
- data/lib/packetgen/types.rb +13 -0
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +1 -1
- metadata +19 -6
- data/lib/packetgen/header/header_class_methods.rb +0 -106
- data/lib/packetgen/header/header_methods.rb +0 -73
- data/lib/packetgen/structfu.rb +0 -363
data/lib/packetgen/inspect.rb
CHANGED
@@ -9,7 +9,7 @@ module PacketGen
|
|
9
9
|
INSPECT_MAX_WIDTH = 70
|
10
10
|
|
11
11
|
# Format to inspect attribute
|
12
|
-
INSPECT_FMT_ATTR = "%
|
12
|
+
INSPECT_FMT_ATTR = "%10s %12s: %s\n"
|
13
13
|
|
14
14
|
# Create a dashed line with +obj+ class writing in it
|
15
15
|
# @param [String] name
|
@@ -26,7 +26,7 @@ module PacketGen
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# @param [#to_i] value
|
29
|
-
# @param [Integer]
|
29
|
+
# @param [Integer] hexsize
|
30
30
|
# @return [String]
|
31
31
|
def self.int_dec_hex(value, hexsize)
|
32
32
|
"%-10s (0x%0#{hexsize}x)" % [value.to_i, value.to_i]
|
@@ -34,7 +34,7 @@ module PacketGen
|
|
34
34
|
|
35
35
|
# Format an attribute for +#inspect+.
|
36
36
|
# 3 cases are handled:
|
37
|
-
# * attribute value is a {
|
37
|
+
# * attribute value is a {Types::Int}: show value as integer and in
|
38
38
|
# hexdecimal format,
|
39
39
|
# * attribute value responds to +#to_human+: call it,
|
40
40
|
# * else, +#to_s+ is used to format attribute value.
|
@@ -44,7 +44,7 @@ module PacketGen
|
|
44
44
|
# @return [String]
|
45
45
|
def self.inspect_attribute(attr, value, level=1)
|
46
46
|
str = shift_level(level)
|
47
|
-
val = if value.is_a?
|
47
|
+
val = if value.is_a? Types::Int
|
48
48
|
int_dec_hex(value, value.to_s.size * 2)
|
49
49
|
elsif value.respond_to? :to_human
|
50
50
|
value.to_human
|
@@ -57,6 +57,7 @@ module PacketGen
|
|
57
57
|
# @param [#to_s] body
|
58
58
|
# @return [String]
|
59
59
|
def self.inspect_body(body)
|
60
|
+
return '' if body.nil?
|
60
61
|
str = dashed_line('Body', 2)
|
61
62
|
str << (0..15).to_a.map { |v| " %02d" % v}.join << "\n"
|
62
63
|
str << '-' * INSPECT_MAX_WIDTH << "\n"
|
data/lib/packetgen/packet.rb
CHANGED
@@ -65,54 +65,7 @@ module PacketGen
|
|
65
65
|
# @return [Packet]
|
66
66
|
# @raise [ArgumentError] +first_header+ is an unknown header
|
67
67
|
def self.parse(binary_str, first_header: nil)
|
68
|
-
|
69
|
-
|
70
|
-
if first_header.nil?
|
71
|
-
# No decoding forced for first header. Have to guess it!
|
72
|
-
Header.all.each do |hklass|
|
73
|
-
hdr = hklass.new
|
74
|
-
hdr.read binary_str
|
75
|
-
# First header is found when:
|
76
|
-
# * for one known header,
|
77
|
-
# * it exists a known binding with a upper header
|
78
|
-
hklass.known_headers.each do |nh, bindings|
|
79
|
-
bindings.each do |binding|
|
80
|
-
if hdr.send(binding.key) == binding.value
|
81
|
-
first_header = hklass.to_s.gsub(/.*::/, '')
|
82
|
-
break
|
83
|
-
end
|
84
|
-
break unless first_header.nil?
|
85
|
-
end
|
86
|
-
end
|
87
|
-
break unless first_header.nil?
|
88
|
-
end
|
89
|
-
if first_header.nil?
|
90
|
-
raise ParseError, 'cannot identify first header in string'
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
pkt.add(first_header)
|
95
|
-
pkt.headers.last.read binary_str
|
96
|
-
|
97
|
-
# Decode upper headers recursively
|
98
|
-
decode_packet_bottom_up = true
|
99
|
-
while decode_packet_bottom_up do
|
100
|
-
last_known_hdr = pkt.headers.last
|
101
|
-
last_known_hdr.class.known_headers.each do |nh, bindings|
|
102
|
-
bindings.each do |binding|
|
103
|
-
if last_known_hdr.send(binding.key) == binding.value
|
104
|
-
str = last_known_hdr.body
|
105
|
-
pkt.add nh.to_s.gsub(/.*::/, '')
|
106
|
-
pkt.headers.last.read str
|
107
|
-
break
|
108
|
-
end
|
109
|
-
end
|
110
|
-
break unless last_known_hdr == pkt.headers.last
|
111
|
-
end
|
112
|
-
decode_packet_bottom_up = (pkt.headers.last != last_known_hdr)
|
113
|
-
end
|
114
|
-
|
115
|
-
pkt
|
68
|
+
new.parse binary_str, first_header: first_header
|
116
69
|
end
|
117
70
|
|
118
71
|
# Capture packets from +iface+
|
@@ -206,9 +159,9 @@ module PacketGen
|
|
206
159
|
end
|
207
160
|
|
208
161
|
# Get packet body
|
209
|
-
# @return [
|
162
|
+
# @return [Types]
|
210
163
|
def body
|
211
|
-
@headers.last.body
|
164
|
+
@headers.last.body if @headers.last.respond_to? :body
|
212
165
|
end
|
213
166
|
|
214
167
|
# Set packet body
|
@@ -268,12 +221,37 @@ module PacketGen
|
|
268
221
|
prev_header = idx > 0 ? @headers[idx - 1] : nil
|
269
222
|
next_header = (idx+1) < @headers.size ? @headers[idx + 1] : nil
|
270
223
|
@headers.delete_at(idx)
|
271
|
-
|
224
|
+
if prev_header and next_header
|
225
|
+
add_header(next_header, previous_header: prev_header)
|
226
|
+
end
|
272
227
|
end
|
273
228
|
rescue ArgumentError => ex
|
274
229
|
raise FormatError, ex.message
|
275
230
|
end
|
276
231
|
|
232
|
+
# Parse a binary string and populate Packet from it.
|
233
|
+
# @param [String] binary_str
|
234
|
+
# @param [String,nil] first_header First protocol header. +nil+ means discover it!
|
235
|
+
# @return [Packet] self
|
236
|
+
# @raise [ArgumentError] +first_header+ is an unknown header
|
237
|
+
def parse(binary_str, first_header: nil)
|
238
|
+
@headers.clear
|
239
|
+
|
240
|
+
if first_header.nil?
|
241
|
+
# No decoding forced for first header. Have to guess it!
|
242
|
+
first_header = guess_first_header(binary_str)
|
243
|
+
if first_header.nil?
|
244
|
+
raise ParseError, 'cannot identify first header in string'
|
245
|
+
end
|
246
|
+
end
|
247
|
+
add first_header
|
248
|
+
@headers[-1, 1] = @headers.last.read(binary_str)
|
249
|
+
|
250
|
+
# Decode upper headers recursively
|
251
|
+
decode_bottom_up
|
252
|
+
self
|
253
|
+
end
|
254
|
+
|
277
255
|
# @return [String]
|
278
256
|
def inspect
|
279
257
|
str = Inspect.dashed_line(self.class)
|
@@ -332,23 +310,23 @@ module PacketGen
|
|
332
310
|
end
|
333
311
|
|
334
312
|
# Add a header to packet
|
335
|
-
# @param [Header::
|
336
|
-
# @param [Header::
|
313
|
+
# @param [Header::Base] header
|
314
|
+
# @param [Header::Base] previous_header
|
337
315
|
# @return [void]
|
338
|
-
def add_header(header, previous_header
|
316
|
+
def add_header(header, previous_header: nil, parsing: false)
|
339
317
|
protocol = header.protocol_name
|
340
318
|
prev_header = previous_header || @headers.last
|
341
319
|
if prev_header
|
342
320
|
bindings = prev_header.class.known_headers[header.class]
|
343
|
-
if bindings.nil?
|
321
|
+
if bindings.nil?
|
344
322
|
msg = "#{prev_header.class} knowns no layer association with #{protocol}. "
|
345
323
|
msg << "Try #{prev_header.class}.bind_layer(PacketGen::Header::#{protocol}, "
|
346
324
|
msg << "#{prev_header.protocol_name.downcase}_proto_field: "
|
347
325
|
msg << "value_for_#{protocol.downcase})"
|
348
326
|
raise ArgumentError, msg
|
349
327
|
end
|
350
|
-
|
351
|
-
prev_header
|
328
|
+
bindings.set(prev_header) if !bindings.empty? and !parsing
|
329
|
+
prev_header[:body] = header
|
352
330
|
end
|
353
331
|
header.packet = self
|
354
332
|
@headers << header unless previous_header
|
@@ -357,6 +335,45 @@ module PacketGen
|
|
357
335
|
"header(#{header.class}, arg); end"
|
358
336
|
end
|
359
337
|
end
|
338
|
+
|
339
|
+
def guess_first_header(binary_str)
|
340
|
+
first_header = nil
|
341
|
+
Header.all.each do |hklass|
|
342
|
+
hdr = hklass.new
|
343
|
+
# #read may return another object (more specific class)
|
344
|
+
hdr = hdr.read(binary_str)
|
345
|
+
# First header is found when:
|
346
|
+
# * for one known header,
|
347
|
+
# * it exists a known binding with a upper header
|
348
|
+
search_header(hdr) do
|
349
|
+
first_header = hklass.to_s.gsub(/.*::/, '')
|
350
|
+
end
|
351
|
+
break unless first_header.nil?
|
352
|
+
end
|
353
|
+
first_header
|
354
|
+
end
|
355
|
+
|
356
|
+
def decode_bottom_up
|
357
|
+
decode_packet_bottom_up = true
|
358
|
+
while decode_packet_bottom_up do
|
359
|
+
last_known_hdr = @headers.last
|
360
|
+
search_header(last_known_hdr) do |nh|
|
361
|
+
str = last_known_hdr.body
|
362
|
+
add_header nh.new, parsing: true
|
363
|
+
@headers[-1, 1] = @headers.last.read(str)
|
364
|
+
end
|
365
|
+
decode_packet_bottom_up = (@headers.last != last_known_hdr)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def search_header(hdr)
|
370
|
+
hdr.class.known_headers.each do |nh, bindings|
|
371
|
+
if bindings.check?(hdr)
|
372
|
+
yield nh
|
373
|
+
break
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
360
377
|
end
|
361
378
|
end
|
362
379
|
|
@@ -6,20 +6,41 @@
|
|
6
6
|
module PacketGen
|
7
7
|
module PcapNG
|
8
8
|
|
9
|
-
#
|
10
|
-
|
9
|
+
# @abstract Base class for all block types
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
class Block < Types::Fields
|
12
|
+
|
13
|
+
# @return [:little, :big]
|
14
|
+
attr_accessor :endian
|
15
|
+
|
16
|
+
# @!attribute type
|
17
|
+
# 32-bit block type
|
18
|
+
# @return [Integer]
|
19
|
+
define_field :type, Types::Int32
|
20
|
+
# @!attribute block_len
|
21
|
+
# 32-bit block length
|
22
|
+
# @return [Integer]
|
23
|
+
define_field :block_len, Types::Int32
|
24
|
+
# @!attribute block_len
|
25
|
+
# 32-bit block length
|
26
|
+
# @return [Integer]
|
27
|
+
define_field :block_len2, Types::Int32
|
28
|
+
|
29
|
+
def initialize(options={})
|
30
|
+
super
|
31
|
+
end
|
11
32
|
|
12
33
|
# Has this block option?
|
13
34
|
# @return [Boolean]
|
14
35
|
def has_options?
|
15
|
-
|
36
|
+
@fields.has_key?(:options) && @fields[:options].sz > 0
|
16
37
|
end
|
17
38
|
|
18
39
|
# Calculate block length and update :block_len and block_len2 fields
|
19
40
|
# @return [void]
|
20
41
|
def recalc_block_len
|
21
|
-
len =
|
22
|
-
self
|
42
|
+
len = fields.map { |f| @fields[f].to_s }.join.size
|
43
|
+
self.block_len = self.block_len2 = len
|
23
44
|
end
|
24
45
|
|
25
46
|
# Pad given field to 32 bit boundary, if needed
|
@@ -27,11 +48,32 @@ module PacketGen
|
|
27
48
|
# @return [void]
|
28
49
|
def pad_field(*fields)
|
29
50
|
fields.each do |field|
|
30
|
-
unless
|
31
|
-
|
51
|
+
unless @fields[field].size % 4 == 0
|
52
|
+
@fields[field] << "\x00" * (4 - (@fields[field].size % 4))
|
32
53
|
end
|
33
54
|
end
|
34
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Set the endianness for the various Int classes handled by self.
|
60
|
+
# Must be called by all subclass #initialize method.
|
61
|
+
# @param [:little, :big] e
|
62
|
+
# @return [:little, :big] returns e
|
63
|
+
def set_endianness(e)
|
64
|
+
unless [:little, :big].include? e
|
65
|
+
raise ArgumentError, "unknown endianness for #{self.class}"
|
66
|
+
end
|
67
|
+
@endian = e
|
68
|
+
@fields.each { |f_, v| v.endian = e if v.is_a?(Types::Int) }
|
69
|
+
e
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_len_coherency
|
73
|
+
unless self[:block_len].to_i == self[:block_len2].to_i
|
74
|
+
raise InvalidFileError, 'Incoherency in Block length'
|
75
|
+
end
|
76
|
+
end
|
35
77
|
end
|
36
78
|
end
|
37
79
|
end
|
data/lib/packetgen/pcapng/epb.rb
CHANGED
@@ -19,18 +19,42 @@ module PacketGen
|
|
19
19
|
# String :data
|
20
20
|
# String :options
|
21
21
|
# Int32 :block_len2
|
22
|
-
class EPB <
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
class EPB < Block
|
23
|
+
|
24
|
+
# Minimum EPB size
|
25
|
+
MIN_SIZE = 8*4
|
26
26
|
|
27
27
|
# @return [:little, :big]
|
28
28
|
attr_accessor :endian
|
29
29
|
# @return [IPB]
|
30
30
|
attr_accessor :interface
|
31
31
|
|
32
|
-
#
|
33
|
-
|
32
|
+
# @!attribute interface_id
|
33
|
+
# 32-bit interface ID
|
34
|
+
# @return [Integer]
|
35
|
+
define_field_before :block_len2, :interface_id, Types::Int32, default: 0
|
36
|
+
# @!attribute tsh
|
37
|
+
# high 32-bit timestamp value
|
38
|
+
# @return [Integer]
|
39
|
+
define_field_before :block_len2, :tsh, Types::Int32, default: 0
|
40
|
+
# @!attribute tsl
|
41
|
+
# low 32-bit imestamp value
|
42
|
+
# @return [Integer]
|
43
|
+
define_field_before :block_len2, :tsl, Types::Int32, default: 0
|
44
|
+
# @!attribute cap_len
|
45
|
+
# 32-bit capture length
|
46
|
+
# @return [Integer]
|
47
|
+
define_field_before :block_len2, :cap_len, Types::Int32, default: 0
|
48
|
+
# @!attribute orig_len
|
49
|
+
# 32-bit original length
|
50
|
+
# @return [Integer]
|
51
|
+
define_field_before :block_len2, :orig_len, Types::Int32, default: 0
|
52
|
+
# @!attribute data
|
53
|
+
# @return [Types::String]
|
54
|
+
define_field_before :block_len2, :data, Types::String
|
55
|
+
# @!attribute options
|
56
|
+
# @return [Types::String]
|
57
|
+
define_field_before :block_len2, :options, Types::String
|
34
58
|
|
35
59
|
# @param [Hash] options
|
36
60
|
# @option options [:little, :big] :endian set block endianness
|
@@ -47,29 +71,10 @@ module PacketGen
|
|
47
71
|
# @option options [::String] :options
|
48
72
|
# @option options [Integer] :block_len2 block total length
|
49
73
|
def initialize(options={})
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
options[:options], options[:block_len2])
|
55
|
-
end
|
56
|
-
|
57
|
-
# Used by {#initialize} to set the initial fields
|
58
|
-
# @param [Hash] options
|
59
|
-
# @see #initialize possible options
|
60
|
-
# @return [Hash] return +options+
|
61
|
-
def init_fields(options={})
|
62
|
-
options[:type] = @int32.new(options[:type] || PcapNG::EPB_TYPE.to_i)
|
63
|
-
options[:block_len] = @int32.new(options[:block_len] || MIN_SIZE)
|
64
|
-
options[:interface_id] = @int32.new(options[:interface_id] || 0)
|
65
|
-
options[:tsh] = @int32.new(options[:tsh] || 0)
|
66
|
-
options[:tsl] = @int32.new(options[:tsl] || 0)
|
67
|
-
options[:cap_len] = @int32.new(options[:cap_len] || 0)
|
68
|
-
options[:orig_len] = @int32.new(options[:orig_len] || 0)
|
69
|
-
options[:data] = StructFu::String.new(options[:data] || '')
|
70
|
-
options[:options] = StructFu::String.new(options[:options] || '')
|
71
|
-
options[:block_len2] = @int32.new(options[:block_len2] || MIN_SIZE)
|
72
|
-
options
|
74
|
+
super
|
75
|
+
set_endianness(options[:endian] || :little)
|
76
|
+
recalc_block_len
|
77
|
+
self.type = options[:type] || PcapNG::EPB_TYPE.to_i
|
73
78
|
end
|
74
79
|
|
75
80
|
# Reads a String or a IO to populate the object
|
@@ -98,10 +103,7 @@ module PacketGen
|
|
98
103
|
self[:options].read io.read(options_len)
|
99
104
|
self[:block_len2].read io.read(4)
|
100
105
|
|
101
|
-
|
102
|
-
raise InvalidFileError, 'Incoherency in Extended Packet Block'
|
103
|
-
end
|
104
|
-
|
106
|
+
check_len_coherency
|
105
107
|
self
|
106
108
|
end
|
107
109
|
|
@@ -116,7 +118,7 @@ module PacketGen
|
|
116
118
|
def to_s
|
117
119
|
pad_field :data, :options
|
118
120
|
recalc_block_len
|
119
|
-
|
121
|
+
fields.map { |f| @fields[f].to_s }.join
|
120
122
|
end
|
121
123
|
|
122
124
|
|
@@ -8,6 +8,14 @@ module PacketGen
|
|
8
8
|
|
9
9
|
# PcapNG::File is a complete Pcap-NG file handler.
|
10
10
|
class File
|
11
|
+
|
12
|
+
# Known link types
|
13
|
+
KNOWN_LINK_TYPES = {
|
14
|
+
LINKTYPE_ETHERNET => 'Eth',
|
15
|
+
LINKTYPE_IPV4 => 'IP',
|
16
|
+
LINKTYPE_IPV6 => 'IPv6'
|
17
|
+
}
|
18
|
+
|
11
19
|
# Get file sections
|
12
20
|
# @return [Array]
|
13
21
|
attr_accessor :sections
|
@@ -74,6 +82,7 @@ module PacketGen
|
|
74
82
|
# @overload read_packet_bytes(fname)
|
75
83
|
# @param [String] fname pcapng file name
|
76
84
|
# @yieldparam [String] raw packet raw data
|
85
|
+
# @yieldparam [Integer] interface's link_type from which packet was captured
|
77
86
|
# @return [Integer] number of packets
|
78
87
|
# @raise [ArgumentError] cannot read +fname+
|
79
88
|
def read_packet_bytes(fname, &blk)
|
@@ -83,7 +92,7 @@ module PacketGen
|
|
83
92
|
readfile(fname) do |packet|
|
84
93
|
if blk
|
85
94
|
count += 1
|
86
|
-
yield packet.data.to_s
|
95
|
+
yield packet.data.to_s, packet.interface.link_type
|
87
96
|
else
|
88
97
|
packets << packet.data.to_s
|
89
98
|
end
|
@@ -106,12 +115,19 @@ module PacketGen
|
|
106
115
|
count = 0
|
107
116
|
packets = [] unless blk
|
108
117
|
|
109
|
-
read_packet_bytes(fname) do |packet|
|
118
|
+
read_packet_bytes(fname) do |packet, link_type|
|
119
|
+
first_header = KNOWN_LINK_TYPES[link_type]
|
120
|
+
parsed_pkt = if first_header.nil?
|
121
|
+
# unknown link type, try to guess
|
122
|
+
Packet.parse(packet)
|
123
|
+
else
|
124
|
+
Packet.parse(packet, first_header: first_header)
|
125
|
+
end
|
110
126
|
if blk
|
111
127
|
count += 1
|
112
|
-
yield
|
128
|
+
yield parsed_pkt
|
113
129
|
else
|
114
|
-
packets <<
|
130
|
+
packets << parsed_pkt
|
115
131
|
end
|
116
132
|
end
|
117
133
|
|
@@ -277,7 +293,7 @@ module PacketGen
|
|
277
293
|
# @return [void]
|
278
294
|
def parse_section(io)
|
279
295
|
shb = SHB.new
|
280
|
-
type =
|
296
|
+
type = Types::Int32.new(0, shb.endian).read(io.read(4))
|
281
297
|
io.seek(-4, IO::SEEK_CUR)
|
282
298
|
shb = parse(type, io, shb)
|
283
299
|
raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
|
@@ -287,7 +303,7 @@ module PacketGen
|
|
287
303
|
section = StringIO.new(io.read(shb.section_len.to_i))
|
288
304
|
while !section.eof? do
|
289
305
|
shb = @sections.last
|
290
|
-
type =
|
306
|
+
type = Types::Int32.new(0, shb.endian).read(section.read(4))
|
291
307
|
section.seek(-4, IO::SEEK_CUR)
|
292
308
|
block = parse(type, section, shb)
|
293
309
|
end
|
@@ -295,7 +311,7 @@ module PacketGen
|
|
295
311
|
# section length is undefined
|
296
312
|
while !io.eof?
|
297
313
|
shb = @sections.last
|
298
|
-
type =
|
314
|
+
type = Types::Int32.new(0, shb.endian).read(io.read(4))
|
299
315
|
io.seek(-4, IO::SEEK_CUR)
|
300
316
|
block = parse(type, io, shb)
|
301
317
|
end
|
@@ -303,7 +319,7 @@ module PacketGen
|
|
303
319
|
end
|
304
320
|
|
305
321
|
# Parse a block from its type
|
306
|
-
# @param [
|
322
|
+
# @param [Types::Int32] type
|
307
323
|
# @param [IO] io stream from which parse block
|
308
324
|
# @param [SHB] shb header of current section
|
309
325
|
# @return [void]
|
data/lib/packetgen/pcapng/idb.rb
CHANGED
@@ -16,10 +16,13 @@ module PacketGen
|
|
16
16
|
# Int64 :snaplen Default: 0 (no limit)
|
17
17
|
# String :options
|
18
18
|
# Int32 :block_len2
|
19
|
-
class IDB <
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
class IDB < Block
|
20
|
+
|
21
|
+
# Minimum IDB size
|
22
|
+
MIN_SIZE = 5*4
|
23
|
+
|
24
|
+
# Option code for if_tsresol option
|
25
|
+
OPTION_IF_TSRESOL = 9
|
23
26
|
|
24
27
|
# @return [:little, :big]
|
25
28
|
attr_accessor :endian
|
@@ -28,11 +31,21 @@ module PacketGen
|
|
28
31
|
# @return [Array<EPB,SPB>]
|
29
32
|
attr_accessor :packets
|
30
33
|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
# @!attribute link_type
|
35
|
+
# 16-bit link type
|
36
|
+
# @return [Integer]
|
37
|
+
define_field_before :block_len2, :link_type, Types::Int16, default: 1
|
38
|
+
# @!attribute reserved
|
39
|
+
# 16-bit reserved field
|
40
|
+
# @return [Integer]
|
41
|
+
define_field_before :block_len2, :reserved, Types::Int16, default: 0
|
42
|
+
# @!attribute snaplen
|
43
|
+
# 32-bit snap length
|
44
|
+
# @return [Integer]
|
45
|
+
define_field_before :block_len2, :snaplen, Types::Int32, default: 0
|
46
|
+
# @!attribute options
|
47
|
+
# @return [Types::String]
|
48
|
+
define_field_before :block_len2, :options, Types::String
|
36
49
|
|
37
50
|
# @param [Hash] options
|
38
51
|
# @option options [:little, :big] :endian set block endianness
|
@@ -45,27 +58,12 @@ module PacketGen
|
|
45
58
|
# @option options [::String] :options
|
46
59
|
# @option options [Integer] :block_len2 block total length
|
47
60
|
def initialize(options={})
|
48
|
-
|
61
|
+
super
|
62
|
+
set_endianness(options[:endian] || :little)
|
49
63
|
@packets = []
|
50
64
|
@options_decoded = false
|
51
|
-
|
52
|
-
|
53
|
-
options[:snaplen], options[:options], options[:block_len2])
|
54
|
-
end
|
55
|
-
|
56
|
-
# Used by {#initialize} to set the initial fields
|
57
|
-
# @see #initialize possible options
|
58
|
-
# @param [Hash] options
|
59
|
-
# @return [Hash] return +options+
|
60
|
-
def init_fields(options={})
|
61
|
-
options[:type] = @int32.new(options[:type] || PcapNG::IDB_TYPE.to_i)
|
62
|
-
options[:block_len] = @int32.new(options[:block_len] || MIN_SIZE)
|
63
|
-
options[:link_type] = @int16.new(options[:link_type] || 1)
|
64
|
-
options[:reserved] = @int16.new(options[:reserved] || 0)
|
65
|
-
options[:snaplen] = @int32.new(options[:snaplen] || 0)
|
66
|
-
options[:options] = StructFu::String.new(options[:options] || '')
|
67
|
-
options[:block_len2] = @int32.new(options[:block_len2] || MIN_SIZE)
|
68
|
-
options
|
65
|
+
recalc_block_len
|
66
|
+
self.type = options[:type] || PcapNG::IDB_TYPE.to_i
|
69
67
|
end
|
70
68
|
|
71
69
|
# Reads a String or a IO to populate the object
|
@@ -87,10 +85,7 @@ module PacketGen
|
|
87
85
|
self[:options].read io.read(self[:block_len].to_i - MIN_SIZE)
|
88
86
|
self[:block_len2].read io.read(4)
|
89
87
|
|
90
|
-
|
91
|
-
raise InvalidFileError, 'Incoherency in Interface Description Block'
|
92
|
-
end
|
93
|
-
|
88
|
+
check_len_coherency
|
94
89
|
self
|
95
90
|
end
|
96
91
|
|
@@ -141,7 +136,7 @@ module PacketGen
|
|
141
136
|
def to_s
|
142
137
|
pad_field :options
|
143
138
|
recalc_block_len
|
144
|
-
|
139
|
+
fields.map { |f| @fields[f].to_s }.join << @packets.map(&:to_s).join
|
145
140
|
end
|
146
141
|
|
147
142
|
end
|