packetgen 3.2.0 → 3.2.1
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/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/response.rb +43 -23
- data/lib/packetgen/header/igmp.rb +1 -1
- data/lib/packetgen/header/ip/option.rb +2 -1
- 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 +20 -14
- 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 +8 -1
- 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/utils.rb +55 -21
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +3 -3
- metadata +3 -3
@@ -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
|
@@ -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
|
-
|
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
|
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
|
-
|
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
|
@@ -62,7 +62,7 @@ module PacketGen
|
|
62
62
|
HUMAN_SEPARATOR = ','
|
63
63
|
|
64
64
|
# rubocop:disable Naming/AccessorMethodName
|
65
|
-
class <<self
|
65
|
+
class << self
|
66
66
|
# Get class set with {.set_of}.
|
67
67
|
# @return [Class]
|
68
68
|
# @since 3.0.0
|
@@ -154,6 +154,8 @@ module PacketGen
|
|
154
154
|
self
|
155
155
|
end
|
156
156
|
|
157
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
158
|
+
|
157
159
|
# Populate object from a string
|
158
160
|
# @param [String] str
|
159
161
|
# @return [self]
|
@@ -171,6 +173,7 @@ module PacketGen
|
|
171
173
|
end
|
172
174
|
self
|
173
175
|
end
|
176
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
174
177
|
|
175
178
|
# Get size in bytes
|
176
179
|
# @return [Integer]
|
@@ -228,18 +231,22 @@ module PacketGen
|
|
228
231
|
class ArrayOfInt8 < Array
|
229
232
|
set_of Int8
|
230
233
|
end
|
234
|
+
|
231
235
|
# Specialized array to handle serie of {Int16}.
|
232
236
|
class ArrayOfInt16 < Array
|
233
237
|
set_of Int16
|
234
238
|
end
|
239
|
+
|
235
240
|
# Specialized array to handle serie of {Int16le}.
|
236
241
|
class ArrayOfInt16le < Array
|
237
242
|
set_of Int16le
|
238
243
|
end
|
244
|
+
|
239
245
|
# Specialized array to handle serie of {Int32}.
|
240
246
|
class ArrayOfInt32 < Types::Array
|
241
247
|
set_of Types::Int32
|
242
248
|
end
|
249
|
+
|
243
250
|
# Specialized array to handle serie of {Int32le}.
|
244
251
|
class ArrayOfInt32le < Types::Array
|
245
252
|
set_of Types::Int32le
|
@@ -115,7 +115,7 @@ module PacketGen
|
|
115
115
|
# @private bit field definitions
|
116
116
|
@bit_fields = {}
|
117
117
|
|
118
|
-
class <<self
|
118
|
+
class << self
|
119
119
|
# Get field definitions for this class.
|
120
120
|
# @return [Hash]
|
121
121
|
# @since 3.1.0
|
@@ -282,7 +282,7 @@ module PacketGen
|
|
282
282
|
type = field_defs[attr].type
|
283
283
|
raise TypeError, "#{attr} is not a PacketGen::Types::Int" unless type < Types::Int
|
284
284
|
|
285
|
-
total_size = type.new.
|
285
|
+
total_size = type.new.nbits
|
286
286
|
idx = total_size - 1
|
287
287
|
|
288
288
|
until args.empty?
|
@@ -358,15 +358,15 @@ module PacketGen
|
|
358
358
|
clear_mask = compute_clear_mask(total_size, field_mask)
|
359
359
|
|
360
360
|
class_eval <<-METHODS
|
361
|
-
def #{name}?
|
362
|
-
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
363
|
-
val != 0
|
364
|
-
end
|
365
|
-
def #{name}=(v)
|
366
|
-
val = v ? 1 : 0
|
367
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
368
|
-
self[:#{attr}].value |= val << #{shift}
|
369
|
-
end
|
361
|
+
def #{name}? # def bit?
|
362
|
+
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift} # val = (self[:attr}].to_i & 1}) >> 1
|
363
|
+
val != 0 # val != 0
|
364
|
+
end # end
|
365
|
+
def #{name}=(v) # def bit=(v)
|
366
|
+
val = v ? 1 : 0 # val = v ? 1 : 0
|
367
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask} # self[:attr].value = self[:attr].to_i & 0xfffd
|
368
|
+
self[:#{attr}].value |= val << #{shift} # self[:attr].value |= val << 1
|
369
|
+
end # end
|
370
370
|
METHODS
|
371
371
|
end
|
372
372
|
|
@@ -375,13 +375,13 @@ module PacketGen
|
|
375
375
|
clear_mask = compute_clear_mask(total_size, field_mask)
|
376
376
|
|
377
377
|
class_eval <<-METHODS
|
378
|
-
def #{name}
|
379
|
-
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
380
|
-
end
|
381
|
-
def #{name}=(v)
|
382
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
383
|
-
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
384
|
-
end
|
378
|
+
def #{name} # def multibit
|
379
|
+
(self[:#{attr}].to_i & #{field_mask}) >> #{shift} # (self[:attr].to_i & 6) >> 1
|
380
|
+
end # end
|
381
|
+
def #{name}=(v) # def multibit=(v)
|
382
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask} # self[:attr].value = self[:attr].to_i & 0xfff9
|
383
|
+
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift} # self[:attr].value |= (v & 3) << 1
|
384
|
+
end # end
|
385
385
|
METHODS
|
386
386
|
end
|
387
387
|
|
@@ -523,7 +523,7 @@ module PacketGen
|
|
523
523
|
# Return object as a hash
|
524
524
|
# @return [Hash] keys: attributes, values: attribute values
|
525
525
|
def to_h
|
526
|
-
|
526
|
+
fields.map { |f| [f, @fields[f].to_human] }.to_h
|
527
527
|
end
|
528
528
|
|
529
529
|
# Get offset of given field in {Fields} structure.
|
data/lib/packetgen/types/int.rb
CHANGED
data/lib/packetgen/types/oui.rb
CHANGED
data/lib/packetgen/types/tlv.rb
CHANGED
@@ -56,12 +56,8 @@ module PacketGen
|
|
56
56
|
def initialize(options={})
|
57
57
|
Deprecation.deprecated_class(self.class, AbstractTLV)
|
58
58
|
super
|
59
|
-
|
60
|
-
|
61
|
-
self[:value] = options[:v].new if options[:v]
|
62
|
-
self.type = options[:type] if options[:type]
|
63
|
-
self.value = options[:value] if options[:value]
|
64
|
-
self.length = options[:length] if options[:length]
|
59
|
+
initialize_types(options)
|
60
|
+
initialize_values(options)
|
65
61
|
end
|
66
62
|
|
67
63
|
# Populate object from a binary string
|
@@ -137,9 +133,9 @@ module PacketGen
|
|
137
133
|
else
|
138
134
|
'%s'
|
139
135
|
end
|
140
|
-
|
141
|
-
"#{name} type:#{@typestr} length:#{
|
142
|
-
|
136
|
+
lenstr = "%-#{(2**self[:length].nbits - 1).to_s.size}u"
|
137
|
+
"#{name} type:#{@typestr} length:#{lenstr} value:#{value.inspect}" % [human_type,
|
138
|
+
length]
|
143
139
|
end
|
144
140
|
|
145
141
|
private
|
@@ -147,6 +143,18 @@ module PacketGen
|
|
147
143
|
def human_types?
|
148
144
|
self.class.const_defined? :TYPES
|
149
145
|
end
|
146
|
+
|
147
|
+
def initialize_types(options)
|
148
|
+
self[:type] = options[:t].new(self.type) if options[:t]
|
149
|
+
self[:length] = options[:l].new(self.length) if options[:l]
|
150
|
+
self[:value] = options[:v].new if options[:v]
|
151
|
+
end
|
152
|
+
|
153
|
+
def initialize_values(options)
|
154
|
+
self.type = options[:type] if options[:type]
|
155
|
+
self.value = options[:value] if options[:value]
|
156
|
+
self.length = options[:length] if options[:length]
|
157
|
+
end
|
150
158
|
end
|
151
159
|
end
|
152
160
|
end
|