packetgen 3.1.5 → 3.1.6
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/bin/pgconsole +1 -0
- data/lib/packetgen.rb +2 -2
- data/lib/packetgen/capture.rb +9 -0
- data/lib/packetgen/header/base.rb +68 -70
- data/lib/packetgen/header/dhcpv6/duid.rb +3 -1
- data/lib/packetgen/header/dhcpv6/option.rb +3 -1
- data/lib/packetgen/header/dns/name.rb +18 -7
- data/lib/packetgen/header/dns/question.rb +2 -0
- data/lib/packetgen/header/dot11.rb +23 -6
- data/lib/packetgen/header/dot11/data.rb +9 -5
- data/lib/packetgen/header/eap.rb +3 -2
- data/lib/packetgen/header/eth.rb +4 -8
- data/lib/packetgen/header/http/headers.rb +3 -4
- data/lib/packetgen/header/http/request.rb +32 -17
- data/lib/packetgen/header/http/response.rb +1 -1
- 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 +2 -3
- data/lib/packetgen/header/ip/option.rb +4 -4
- data/lib/packetgen/header/ipv6/addr.rb +1 -2
- 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 +6 -0
- 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 +2 -0
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
- data/lib/packetgen/header/snmp.rb +3 -2
- data/lib/packetgen/header/tcp/option.rb +8 -6
- data/lib/packetgen/packet.rb +7 -3
- 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 +164 -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 +8 -8
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/abstract_tlv.rb +2 -3
- data/lib/packetgen/types/array.rb +15 -9
- data/lib/packetgen/types/cstring.rb +38 -17
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +91 -56
- data/lib/packetgen/types/int.rb +2 -2
- data/lib/packetgen/types/int_string.rb +7 -2
- data/lib/packetgen/types/length_from.rb +18 -10
- data/lib/packetgen/types/oui.rb +1 -2
- data/lib/packetgen/types/string.rb +45 -8
- data/lib/packetgen/types/tlv.rb +1 -2
- data/lib/packetgen/utils.rb +2 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +13 -12
- data/lib/packetgen/inspectable.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8959dbe60df80490d1ac31eaf40b05a206860bf6bed306997a66ca9c77dfb0b
|
4
|
+
data.tar.gz: 4615a1084f86e4b0ab216b3766dbde7d1b0b2b1e3c2e6b0d2e1a63aba1ff7bd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 636f0dcea926b57cb7ec7a824744dfbcab9c6ddbb7f6749d8fda8f63fec410d20dcf199f362ae63878104725e94c7075d17f94b3f0dc8458b3d975e9521343da
|
7
|
+
data.tar.gz: 50e679400b1f882fbe2d3bc9e3ba5e01bb24dbe4a83b3372b999cbe0d1565703a7fc6afc08c437900e23b92c549c46ad422e3e76140254034c8840ba3a8ecb2e
|
data/bin/pgconsole
CHANGED
data/lib/packetgen.rb
CHANGED
@@ -32,6 +32,7 @@ module PacketGen
|
|
32
32
|
attr_reader :hdr
|
33
33
|
|
34
34
|
def initialize(prev_hdr, hdr)
|
35
|
+
super()
|
35
36
|
@prev_hdr = prev_hdr
|
36
37
|
@hdr = hdr
|
37
38
|
end
|
@@ -66,7 +67,7 @@ module PacketGen
|
|
66
67
|
# @yieldparam [Packet] packet
|
67
68
|
# @return [Array<Packet>]
|
68
69
|
def self.capture(**kwargs)
|
69
|
-
Packet.capture(kwargs) { |packet| yield packet if block_given? }
|
70
|
+
Packet.capture(**kwargs) { |packet| yield packet if block_given? }
|
70
71
|
end
|
71
72
|
|
72
73
|
# Shortcut for {Packet.read}
|
@@ -121,7 +122,6 @@ end
|
|
121
122
|
|
122
123
|
require 'packetgen/deprecation'
|
123
124
|
require 'packetgen/inspect'
|
124
|
-
require 'packetgen/inspectable'
|
125
125
|
require 'packetgen/types'
|
126
126
|
require 'packetgen/pcapng'
|
127
127
|
require 'packetgen/pcap'
|
data/lib/packetgen/capture.rb
CHANGED
@@ -15,6 +15,8 @@ module PacketGen
|
|
15
15
|
|
16
16
|
attr_reader :filter, :cap_thread, :snaplen, :promisc, :monitor
|
17
17
|
|
18
|
+
# rubocop:disable Metrics/ParameterLists
|
19
|
+
|
18
20
|
public
|
19
21
|
|
20
22
|
# Get captured packets.
|
@@ -86,6 +88,9 @@ module PacketGen
|
|
86
88
|
|
87
89
|
private
|
88
90
|
|
91
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
92
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
93
|
+
|
89
94
|
def set_options(iface, max, timeout, filter, promisc, parse, snaplen, monitor)
|
90
95
|
@max = max if max
|
91
96
|
@filter = filter unless filter.nil?
|
@@ -97,6 +102,10 @@ module PacketGen
|
|
97
102
|
@monitor = monitor unless monitor.nil?
|
98
103
|
end
|
99
104
|
|
105
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
106
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
107
|
+
# rubocop:enable Metrics/ParameterLists
|
108
|
+
|
100
109
|
def capture_args
|
101
110
|
h = { iface: iface, filter: filter, monitor: monitor }
|
102
111
|
h[:snaplen] = snaplen unless snaplen.nil?
|
@@ -99,10 +99,8 @@ module PacketGen
|
|
99
99
|
|
100
100
|
# each iterator
|
101
101
|
# @return [void]
|
102
|
-
def each
|
103
|
-
@bindings.each
|
104
|
-
yield b
|
105
|
-
end
|
102
|
+
def each(&block)
|
103
|
+
@bindings.each(&block)
|
106
104
|
end
|
107
105
|
|
108
106
|
# @return [Boolean]
|
@@ -144,74 +142,74 @@ module PacketGen
|
|
144
142
|
klass.class_eval { @known_headers = {} }
|
145
143
|
end
|
146
144
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
# Given value may be a lambda, whose alone argument is the value extracted
|
153
|
-
# from header field (or +nil+ when lambda is used to set field while adding
|
154
|
-
# a header).
|
155
|
-
#
|
156
|
-
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
157
|
-
# fields, the latter to check bindings. This may be used when multiple and
|
158
|
-
# non-trivial checks should be made.
|
159
|
-
# @return [void]
|
160
|
-
# @example Basic examples
|
161
|
-
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
162
|
-
# Header1.bind Header2, field1: 42
|
163
|
-
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
164
|
-
# # and field2 has value 43 or 44
|
165
|
-
# Header1.bind Header3, field1: 43, field2: 43
|
166
|
-
# Header1.bind Header3, field1: 43, field2: 44
|
167
|
-
# @example Defining a binding on a field using a lambda.
|
168
|
-
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
169
|
-
# # greater or equal to 44. When adding a Header2 to a Header1
|
170
|
-
# # with Packet#add, force value to 44.
|
171
|
-
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
172
|
-
# @example Defining a binding using procs key
|
173
|
-
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
174
|
-
# # and first two bytes of header1's body are null.
|
175
|
-
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
176
|
-
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
177
|
-
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
178
|
-
# @since 2.7.0
|
179
|
-
def self.bind(header_klass, args={})
|
180
|
-
if @known_headers[header_klass].nil?
|
181
|
-
bindings = Bindings.new
|
182
|
-
@known_headers[header_klass] = bindings
|
183
|
-
else
|
184
|
-
bindings = @known_headers[header_klass]
|
185
|
-
end
|
186
|
-
bindings.new_set
|
187
|
-
args.each do |key, value|
|
188
|
-
bindings << if key == :procs
|
189
|
-
ProcBinding.new(value)
|
190
|
-
else
|
191
|
-
Binding.new(key, value)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
145
|
+
class <<self
|
146
|
+
# @api private
|
147
|
+
# Get known headers
|
148
|
+
# @return [Hash] keys: header classes, values: hashes
|
149
|
+
attr_reader :known_headers
|
195
150
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
151
|
+
# Bind a upper header to current one.
|
152
|
+
# @param [Class] header_klass header class to bind to current class
|
153
|
+
# @param [Hash] args current class fields and their value when +header_klass+
|
154
|
+
# is embedded in current class.
|
155
|
+
#
|
156
|
+
# Given value may be a lambda, whose alone argument is the value extracted
|
157
|
+
# from header field (or +nil+ when lambda is used to set field while adding
|
158
|
+
# a header).
|
159
|
+
#
|
160
|
+
# Special key +procs+ may be used to set 2 lambdas, the former to set
|
161
|
+
# fields, the latter to check bindings. This may be used when multiple and
|
162
|
+
# non-trivial checks should be made.
|
163
|
+
# @return [void]
|
164
|
+
# @example Basic examples
|
165
|
+
# # Bind Header2 to Header1 when field1 from Header1 has a value of 42
|
166
|
+
# Header1.bind Header2, field1: 42
|
167
|
+
# # Bind Header3 to Header1 when field1 from Header1 has a value of 43
|
168
|
+
# # and field2 has value 43 or 44
|
169
|
+
# Header1.bind Header3, field1: 43, field2: 43
|
170
|
+
# Header1.bind Header3, field1: 43, field2: 44
|
171
|
+
# @example Defining a binding on a field using a lambda.
|
172
|
+
# # Bind Header4 to Header1 when field1 from Header1 has a value
|
173
|
+
# # greater or equal to 44. When adding a Header2 to a Header1
|
174
|
+
# # with Packet#add, force value to 44.
|
175
|
+
# Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
|
176
|
+
# @example Defining a binding using procs key
|
177
|
+
# # Bind Header5 to Header1 when field1 from Header1 has a value of 41
|
178
|
+
# # and first two bytes of header1's body are null.
|
179
|
+
# # When adding a Header2 to a Header1 with Packet#add, force value to 44.
|
180
|
+
# Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
|
181
|
+
# ->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
|
182
|
+
# @since 2.7.0
|
183
|
+
def bind(header_klass, args={})
|
184
|
+
if @known_headers[header_klass].nil?
|
185
|
+
bindings = Bindings.new
|
186
|
+
@known_headers[header_klass] = bindings
|
187
|
+
else
|
188
|
+
bindings = @known_headers[header_klass]
|
189
|
+
end
|
190
|
+
bindings.new_set
|
191
|
+
args.each do |key, value|
|
192
|
+
bindings << if key == :procs
|
193
|
+
ProcBinding.new(value)
|
194
|
+
else
|
195
|
+
Binding.new(key, value)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
209
199
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
200
|
+
# Helper method to calculate length of +hdr+ and set its +length+ field.
|
201
|
+
# To be used by +#calc_length+ in Base subclasses.
|
202
|
+
# @param [Base] hdr
|
203
|
+
# @param [Boolean] header_in_size if +true+ header is included in length,
|
204
|
+
# if +false+, only +body+ is taken into account
|
205
|
+
def calculate_and_set_length(hdr, header_in_size: true)
|
206
|
+
length = if header_in_size
|
207
|
+
hdr.sz
|
208
|
+
else
|
209
|
+
hdr[:body].sz
|
210
|
+
end
|
211
|
+
hdr.length = length
|
212
|
+
end
|
215
213
|
end
|
216
214
|
|
217
215
|
# @see Types::Fields#initialize
|
@@ -11,6 +11,8 @@ module PacketGen
|
|
11
11
|
# @abstract Base class for DUID (DHCP Unique ID)
|
12
12
|
# @author Sylvain Daubert
|
13
13
|
class DUID < Types::Fields
|
14
|
+
include Types::Fieldable
|
15
|
+
|
14
16
|
TYPES = {
|
15
17
|
'DUID-LLT' => 1,
|
16
18
|
'DUID-EN' => 2,
|
@@ -34,7 +36,7 @@ module PacketGen
|
|
34
36
|
# @param [String] str
|
35
37
|
# @return [DUID]
|
36
38
|
def read(str)
|
37
|
-
if self.
|
39
|
+
if self.instance_of?(DUID)
|
38
40
|
super
|
39
41
|
case type
|
40
42
|
when 1
|
@@ -17,6 +17,8 @@ module PacketGen
|
|
17
17
|
# field to replace it by specific option field(s).
|
18
18
|
# @author Sylvain Daubert
|
19
19
|
class Option < Types::Fields
|
20
|
+
include Types::Fieldable
|
21
|
+
|
20
22
|
# @!attribute type
|
21
23
|
# 16-bit option type
|
22
24
|
# @return [Integer]
|
@@ -85,7 +87,7 @@ module PacketGen
|
|
85
87
|
# Get human-readable {#type}
|
86
88
|
# @return [String]
|
87
89
|
def human_type
|
88
|
-
if self.
|
90
|
+
if self.instance_of?(Option)
|
89
91
|
"option#{type}"
|
90
92
|
else
|
91
93
|
self.class.to_s.sub(/.*::/, '')
|
@@ -43,28 +43,32 @@ module PacketGen
|
|
43
43
|
self << Types::IntString.new
|
44
44
|
end
|
45
45
|
|
46
|
+
# Clear name
|
47
|
+
# @return [void]
|
48
|
+
def clear
|
49
|
+
super
|
50
|
+
@pointer = nil
|
51
|
+
@pointer_name = nil
|
52
|
+
end
|
53
|
+
|
46
54
|
# Read a sequence of label from a string
|
47
55
|
# @param [String] str binary string
|
48
56
|
# @return [Name] self
|
49
57
|
def read(str)
|
50
|
-
@pointer = nil
|
51
|
-
@pointer_name = nil
|
52
58
|
clear
|
53
59
|
return self if str.nil?
|
54
60
|
|
55
61
|
PacketGen.force_binary str
|
56
62
|
start = 0
|
57
63
|
loop do
|
58
|
-
index = str[start, 2].
|
64
|
+
index = str[start, 2].unpack1('n')
|
59
65
|
if pointer? index
|
60
66
|
# Pointer on another label
|
61
67
|
@pointer = str[start, 2]
|
62
68
|
break
|
63
69
|
else
|
64
|
-
label =
|
65
|
-
label.read(str[start..-1])
|
70
|
+
label = add_label_from(str[start..-1])
|
66
71
|
start += label.sz
|
67
|
-
self << label
|
68
72
|
break if label.length.zero? || str[start..-1].length.zero?
|
69
73
|
end
|
70
74
|
end
|
@@ -101,7 +105,7 @@ module PacketGen
|
|
101
105
|
return nil unless @pointer
|
102
106
|
return @pointer_name if @pointer_name
|
103
107
|
|
104
|
-
index = @pointer.
|
108
|
+
index = @pointer.unpack1('n')
|
105
109
|
mask = ~POINTER_MASK & 0xffff
|
106
110
|
ptr = index & mask
|
107
111
|
name = Name.new
|
@@ -112,6 +116,13 @@ module PacketGen
|
|
112
116
|
def record_from_hash(_hsh)
|
113
117
|
raise NotImplementedError, "not supported by #{self.class}"
|
114
118
|
end
|
119
|
+
|
120
|
+
def add_label_from(str)
|
121
|
+
label = Types::IntString.new
|
122
|
+
label.read(str)
|
123
|
+
self << label
|
124
|
+
label
|
125
|
+
end
|
115
126
|
end
|
116
127
|
end
|
117
128
|
end
|
@@ -280,7 +280,7 @@ module PacketGen
|
|
280
280
|
def read(str)
|
281
281
|
fcs = Dot11.fcs?
|
282
282
|
|
283
|
-
if self.
|
283
|
+
if self.instance_of? Dot11
|
284
284
|
return self if str.nil?
|
285
285
|
|
286
286
|
force_binary str
|
@@ -323,7 +323,7 @@ module PacketGen
|
|
323
323
|
|
324
324
|
# @return [String]
|
325
325
|
def inspect
|
326
|
-
str = if self.
|
326
|
+
str = if self.instance_of? Dot11
|
327
327
|
Inspect.dashed_line("#{self.class} #{human_type}", 1)
|
328
328
|
elsif self.respond_to? :human_subtype
|
329
329
|
Inspect.dashed_line("#{self.class} #{human_subtype}", 1)
|
@@ -360,27 +360,44 @@ module PacketGen
|
|
360
360
|
|
361
361
|
private
|
362
362
|
|
363
|
-
def
|
363
|
+
def remove_from_applicable_fields(fields)
|
364
|
+
fields = [fields] unless fields.is_a? Array
|
365
|
+
@applicable_fields -= fields
|
366
|
+
end
|
367
|
+
|
368
|
+
def handle_mac4
|
364
369
|
if to_ds? && from_ds?
|
365
370
|
@applicable_fields[6, 0] = :mac4 unless @applicable_fields.include? :mac4
|
366
371
|
else
|
367
|
-
|
372
|
+
remove_from_applicable_fields :mac4
|
368
373
|
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def handle_ht_ctrl
|
369
377
|
if order?
|
370
378
|
unless @applicable_fields.include? :ht_ctrl
|
371
379
|
idx = @applicable_fields.index(:body)
|
372
380
|
@applicable_fields[idx, 0] = :ht_ctrl
|
373
381
|
end
|
374
382
|
else
|
375
|
-
|
383
|
+
remove_from_applicable_fields %i[ht_ctrl]
|
376
384
|
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def handle_fcs
|
377
388
|
if Dot11.fcs?
|
378
389
|
@applicable_fields << :fcs unless @applicable_fields.include? :fcs
|
379
390
|
else
|
380
|
-
|
391
|
+
remove_from_applicable_fields :fcs
|
381
392
|
end
|
382
393
|
end
|
383
394
|
|
395
|
+
def define_applicable_fields
|
396
|
+
handle_mac4
|
397
|
+
handle_ht_ctrl
|
398
|
+
handle_fcs
|
399
|
+
end
|
400
|
+
|
384
401
|
def private_read(str, fcs)
|
385
402
|
self[:frame_ctrl].read str[0, 2]
|
386
403
|
define_applicable_fields
|
@@ -44,22 +44,22 @@ module PacketGen
|
|
44
44
|
case ds
|
45
45
|
when 0
|
46
46
|
# MAC1: RA/DA, MAC2: TA/SA
|
47
|
-
|
47
|
+
invert_mac :mac1, :mac2
|
48
48
|
when 1
|
49
49
|
# MAC1: RA/BSSID, MAC2: TA/SA, MAC3: DA
|
50
|
-
|
50
|
+
invert_mac :mac1, :mac2
|
51
51
|
self.to_ds = false
|
52
52
|
self.from_ds = true
|
53
53
|
when 2
|
54
54
|
# MAC1: RA/DA, MAC2: BSSID, MAC3: SA or BSSID
|
55
|
-
|
55
|
+
invert_mac :mac1, :mac2
|
56
56
|
self.to_ds = true
|
57
57
|
self.from_ds = false
|
58
58
|
when 3
|
59
59
|
# MAC1: RA, MAC2: TA
|
60
|
-
|
60
|
+
invert_mac :mac1, :mac2
|
61
61
|
# MAC3: DA, MAC4: SA
|
62
|
-
|
62
|
+
invert_mac :mac3, :mac4
|
63
63
|
end
|
64
64
|
self
|
65
65
|
end
|
@@ -135,6 +135,10 @@ module PacketGen
|
|
135
135
|
@applicable_fields -= %i[qos_ctrl]
|
136
136
|
end
|
137
137
|
end
|
138
|
+
|
139
|
+
def invert_mac(mac1, mac2)
|
140
|
+
self[mac1], self[mac2] = self[mac2], self[mac1]
|
141
|
+
end
|
138
142
|
end
|
139
143
|
end
|
140
144
|
end
|
data/lib/packetgen/header/eap.rb
CHANGED
@@ -95,7 +95,8 @@ module PacketGen
|
|
95
95
|
# This field is present only for Request or Response packets,
|
96
96
|
# with type different from Expanded Types (254).
|
97
97
|
# @return [Integer] 8-bit request or response type
|
98
|
-
define_field :type, Types::Int8Enum,
|
98
|
+
define_field :type, Types::Int8Enum,
|
99
|
+
enum: TYPES,
|
99
100
|
optional: ->(eap) { eap.type? }
|
100
101
|
|
101
102
|
# @!attribute vendor_id
|
@@ -131,7 +132,7 @@ module PacketGen
|
|
131
132
|
# may be determined
|
132
133
|
def read(str)
|
133
134
|
super str
|
134
|
-
return self unless self.
|
135
|
+
return self unless self.instance_of?(EAP)
|
135
136
|
return self unless type?
|
136
137
|
|
137
138
|
case self.type
|