packetgen 3.2.0 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/pgconsole +3 -3
- data/lib/packetgen/header/arp.rb +24 -13
- data/lib/packetgen/header/asn1_base.rb +2 -2
- data/lib/packetgen/header/base.rb +1 -1
- data/lib/packetgen/header/dhcpv6/duid.rb +6 -0
- data/lib/packetgen/header/dhcpv6/option.rb +11 -13
- data/lib/packetgen/header/dns/opt.rb +2 -2
- data/lib/packetgen/header/dns/rr.rb +61 -28
- data/lib/packetgen/header/dns.rb +13 -6
- data/lib/packetgen/header/dot11/management.rb +2 -5
- data/lib/packetgen/header/dot11.rb +1 -1
- data/lib/packetgen/header/eap.rb +1 -1
- data/lib/packetgen/header/eth.rb +1 -1
- data/lib/packetgen/header/http/headers.rb +16 -1
- data/lib/packetgen/header/http/response.rb +43 -23
- data/lib/packetgen/header/igmp.rb +1 -1
- data/lib/packetgen/header/ip/option.rb +36 -10
- data/lib/packetgen/header/ipv6/addr.rb +3 -0
- data/lib/packetgen/header/mdns.rb +19 -25
- data/lib/packetgen/header/mld.rb +1 -1
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -4
- data/lib/packetgen/header/ospfv2.rb +1 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +14 -5
- data/lib/packetgen/header/ospfv3/lsa.rb +1 -1
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -4
- data/lib/packetgen/header/ospfv3.rb +1 -1
- data/lib/packetgen/header/snmp.rb +39 -16
- data/lib/packetgen/header/tcp/option.rb +1 -1
- data/lib/packetgen/header/tcp.rb +12 -5
- data/lib/packetgen/header/tftp.rb +15 -9
- data/lib/packetgen/inspect.rb +15 -9
- data/lib/packetgen/packet.rb +48 -2
- data/lib/packetgen/pcapng/file.rb +13 -13
- data/lib/packetgen/pcapng.rb +1 -0
- data/lib/packetgen/pcaprub_wrapper.rb +0 -4
- data/lib/packetgen/types/abstract_tlv.rb +1 -1
- data/lib/packetgen/types/array.rb +35 -13
- data/lib/packetgen/types/fields.rb +19 -19
- data/lib/packetgen/types/int.rb +7 -0
- data/lib/packetgen/types/oui.rb +1 -1
- data/lib/packetgen/types/tlv.rb +17 -9
- data/lib/packetgen/unknown_packet.rb +3 -2
- data/lib/packetgen/utils.rb +67 -24
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +3 -3
- metadata +3 -3
@@ -31,32 +31,10 @@ module PacketGen
|
|
31
31
|
case iph
|
32
32
|
when IP
|
33
33
|
iph.dst = '224.0.0.251'
|
34
|
-
|
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
|
-
|
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
|
data/lib/packetgen/header/mld.rb
CHANGED
@@ -68,7 +68,7 @@ module PacketGen
|
|
68
68
|
# directly called
|
69
69
|
def added_to_packet(packet)
|
70
70
|
mld_idx = packet.headers.size
|
71
|
-
packet.instance_eval "def mldize() @headers[#{mld_idx}].mldize; end"
|
71
|
+
packet.instance_eval "def mldize() @headers[#{mld_idx}].mldize; end" # def mldize() @headers[3].mldize; end
|
72
72
|
end
|
73
73
|
|
74
74
|
# Fixup IP header according to RFC 2710:
|
@@ -77,17 +77,15 @@ module PacketGen
|
|
77
77
|
# Compute and set Fletcher-16 checksum on LSA
|
78
78
|
# @return [Integer]
|
79
79
|
def calc_checksum
|
80
|
-
bytes = to_s[2..-1].unpack('C*')
|
81
|
-
|
82
80
|
c0 = c1 = 0
|
83
|
-
|
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 -
|
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
|
-
|
75
|
-
|
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
|
-
|
38
|
+
"neighbor_id:#{neighbor_interface_id},neighbor_router:#{neighbor_router_id}>"
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -78,17 +78,15 @@ module PacketGen
|
|
78
78
|
# Compute and set Fletcher-16 checksum on LSA
|
79
79
|
# @return [Integer]
|
80
80
|
def calc_checksum
|
81
|
-
bytes = to_s[2..-1].unpack('C*')
|
82
|
-
|
83
81
|
c0 = c1 = 0
|
84
|
-
|
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 -
|
89
|
+
x = ((sz - 17) * c0 - c1) % 255
|
92
90
|
x += 255 if x <= 0
|
93
91
|
y = 255 * 2 - c0 - x
|
94
92
|
y -= 255 if y > 255
|
@@ -145,7 +145,7 @@ module PacketGen
|
|
145
145
|
# directly called
|
146
146
|
def added_to_packet(packet)
|
147
147
|
ospf_idx = packet.headers.size
|
148
|
-
packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end"
|
148
|
+
packet.instance_eval "def ospfize(**kwargs) @headers[#{ospf_idx}].ospfize(**kwargs); end" # def ospfize(**kwargs) @headers[2].ospfize(**kwargs); end
|
149
149
|
end
|
150
150
|
|
151
151
|
# Compute checksum and set +checksum+ field
|
@@ -74,6 +74,18 @@ module PacketGen
|
|
74
74
|
# @author Sylvain Daubert
|
75
75
|
class VariableBindings < RASN1::Model
|
76
76
|
sequence_of :bindings, VarBind
|
77
|
+
|
78
|
+
# Get 'idx'th element from the list
|
79
|
+
# @return [VarBind,nil]
|
80
|
+
def [](idx)
|
81
|
+
value[idx]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Get element counts in list
|
85
|
+
# @return [Integer]
|
86
|
+
def size
|
87
|
+
value.size
|
88
|
+
end
|
77
89
|
end
|
78
90
|
|
79
91
|
# Class to handle GetRequest PDU
|
@@ -119,6 +131,10 @@ module PacketGen
|
|
119
131
|
integer(:error, value: 0, enum: ERRORS),
|
120
132
|
integer(:error_index, value: 0),
|
121
133
|
model(:varbindlist, VariableBindings)]
|
134
|
+
|
135
|
+
def initialize(args={})
|
136
|
+
super
|
137
|
+
end
|
122
138
|
end
|
123
139
|
|
124
140
|
# Class to handle GetNextRequest PDU
|
@@ -264,11 +280,12 @@ module PacketGen
|
|
264
280
|
data.chosen = options[:chosen_pdu] if options[:chosen_pdu]
|
265
281
|
return unless options[:pdu]
|
266
282
|
|
267
|
-
|
283
|
+
klass = data.root.chosen_value.class
|
284
|
+
data.root.value[data.chosen] = klass.new(options[:pdu])
|
268
285
|
end
|
269
286
|
|
270
287
|
# accessor to data payload
|
271
|
-
# @return [
|
288
|
+
# @return [ASN1::Types::Choice]
|
272
289
|
def data
|
273
290
|
@elements[:data]
|
274
291
|
end
|
@@ -286,20 +303,11 @@ module PacketGen
|
|
286
303
|
def inspect
|
287
304
|
str = super
|
288
305
|
str << Inspect.shift_level
|
289
|
-
if self[:data].chosen.nil?
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
str << Inspect.dashed_line('ASN.1 content')
|
295
|
-
str << data.chosen_value.inspect(1)
|
296
|
-
begin
|
297
|
-
str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
|
298
|
-
rescue StandardError => e
|
299
|
-
raise unless e.message.match?(/TAG.*not handled/)
|
300
|
-
end
|
301
|
-
str
|
302
|
-
end
|
306
|
+
str << if self[:data].chosen.nil?
|
307
|
+
Inspect::FMT_ATTR % [self[:data].type, :data, '']
|
308
|
+
else
|
309
|
+
inspect_data
|
310
|
+
end
|
303
311
|
end
|
304
312
|
|
305
313
|
# @api private
|
@@ -315,6 +323,21 @@ module PacketGen
|
|
315
323
|
|
316
324
|
packet.udp.sport = packet.udp.dport
|
317
325
|
end
|
326
|
+
|
327
|
+
private
|
328
|
+
|
329
|
+
def inspect_data
|
330
|
+
data = self[:data]
|
331
|
+
str = Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
|
332
|
+
str << Inspect.dashed_line('ASN.1 content')
|
333
|
+
str << data.chosen_value.inspect(1)
|
334
|
+
begin
|
335
|
+
str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
|
336
|
+
rescue StandardError => e
|
337
|
+
raise unless e.message.match?(/TAG.*not handled/)
|
338
|
+
end
|
339
|
+
str
|
340
|
+
end
|
318
341
|
end
|
319
342
|
|
320
343
|
self.add_class SNMP
|
@@ -43,7 +43,7 @@ module PacketGen
|
|
43
43
|
# @!attribute value
|
44
44
|
# @return [Integer,String] option value
|
45
45
|
define_field :value, Types::String, optional: ->(h) { h.length? && h.length > 2 },
|
46
|
-
|
46
|
+
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
47
47
|
|
48
48
|
# @param [hash] options
|
49
49
|
# @option options [Integer] :kind
|
data/lib/packetgen/header/tcp.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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
|
data/lib/packetgen/inspect.rb
CHANGED
@@ -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
|
-
|
109
|
-
str <<
|
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
|
-
|
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 <<
|
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
|
data/lib/packetgen/packet.rb
CHANGED
@@ -51,6 +51,9 @@ module PacketGen
|
|
51
51
|
# Get packet headers, ordered as they appear in the packet.
|
52
52
|
# @return [Array<Header::Base>]
|
53
53
|
attr_reader :headers
|
54
|
+
# Activaye or deactivate header cache (activated by default)
|
55
|
+
# @return [Boolean]
|
56
|
+
attr_accessor :cache_headers
|
54
57
|
|
55
58
|
# Create a new Packet
|
56
59
|
# @param [String] protocol base protocol for packet
|
@@ -121,6 +124,8 @@ module PacketGen
|
|
121
124
|
# @private
|
122
125
|
def initialize
|
123
126
|
@headers = []
|
127
|
+
@header_cache = {}
|
128
|
+
@cache_headers = true
|
124
129
|
end
|
125
130
|
|
126
131
|
# Add a protocol header in packet.
|
@@ -166,7 +171,7 @@ module PacketGen
|
|
166
171
|
# @raise [ArgumentError] unknown protocol
|
167
172
|
def is?(protocol)
|
168
173
|
klass = check_protocol protocol
|
169
|
-
headers.any?
|
174
|
+
headers.any?(klass)
|
170
175
|
end
|
171
176
|
|
172
177
|
# Recalculate all packet checksums
|
@@ -271,6 +276,7 @@ module PacketGen
|
|
271
276
|
headers.delete(hdr)
|
272
277
|
add_header(next_hdr, previous_header: prev_hdr) if prev_hdr && next_hdr
|
273
278
|
end
|
279
|
+
invalidate_header_cache
|
274
280
|
rescue ArgumentError => e
|
275
281
|
raise FormatError, e.message
|
276
282
|
end
|
@@ -356,6 +362,7 @@ module PacketGen
|
|
356
362
|
headers.each do |header|
|
357
363
|
add_magic_header_method header
|
358
364
|
end
|
365
|
+
invalidate_header_cache
|
359
366
|
end
|
360
367
|
|
361
368
|
# Give first header of packet
|
@@ -409,7 +416,7 @@ module PacketGen
|
|
409
416
|
# @return [Header::Base]
|
410
417
|
def header(klass, arg)
|
411
418
|
layer = arg.is_a?(Integer) ? arg : 1
|
412
|
-
header =
|
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 =
|
25
|
-
PcapNG.
|
26
|
-
|
27
|
-
|
28
|
-
|
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 =
|
205
|
+
mode = options[:append] && ::File.exist?(filename) ? 'ab' : 'wb'
|
208
206
|
::File.open(filename, mode) { |f| f.write(self.to_s) }
|
209
207
|
[filename, self.to_s.size]
|
210
208
|
end
|
@@ -317,12 +315,12 @@ module PacketGen
|
|
317
315
|
shb = parse_shb(SHB.new, io)
|
318
316
|
raise InvalidFileError, 'no Section header found' unless shb.is_a?(SHB)
|
319
317
|
|
320
|
-
to_parse = if shb.section_len.to_i
|
321
|
-
# Section length is defined
|
322
|
-
StringIO.new(io.read(shb.section_len.to_i))
|
323
|
-
else
|
318
|
+
to_parse = if shb.section_len.to_i == 0xffffffffffffffff
|
324
319
|
# section length is undefined
|
325
320
|
io
|
321
|
+
else
|
322
|
+
# Section length is defined
|
323
|
+
StringIO.new(io.read(shb.section_len.to_i))
|
326
324
|
end
|
327
325
|
|
328
326
|
until to_parse.eof?
|
@@ -388,6 +386,7 @@ module PacketGen
|
|
388
386
|
end
|
389
387
|
end
|
390
388
|
|
389
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
391
390
|
# Extract and check options for #array_to_file
|
392
391
|
def array_to_file_options_from_hash(options)
|
393
392
|
%i[filename arr ts].each do |deprecated_opt|
|
@@ -404,6 +403,7 @@ module PacketGen
|
|
404
403
|
|
405
404
|
[filename, ary, ts, ts_inc, append]
|
406
405
|
end
|
406
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
407
407
|
|
408
408
|
def create_new_shb_section
|
409
409
|
section = SHB.new
|
data/lib/packetgen/pcapng.rb
CHANGED
@@ -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
|