packetgen 3.2.1 → 3.2.2
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/lib/packetgen/header/dhcpv6/duid.rb +6 -0
- data/lib/packetgen/header/http/headers.rb +16 -1
- data/lib/packetgen/header/ip/option.rb +34 -9
- data/lib/packetgen/header/snmp.rb +19 -2
- data/lib/packetgen/types/array.rb +30 -15
- data/lib/packetgen/unknown_packet.rb +3 -2
- data/lib/packetgen/utils.rb +19 -10
- data/lib/packetgen/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad942df146df9daf8c38e049fc112b13c93fd38a45362e8dd2a43c6e8382b224
|
4
|
+
data.tar.gz: 77b48a6af0170a912e91b888456c31881bfe1fd30a693796c849a946b5e27bac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98f7f9d7dd652741cdce08cbe081310c4f4ca6745702efc5755806614f30c7930498610f9925a6d7abeef1b8b64abfa2857c77bcc638872f31577fe587ad1e63
|
7
|
+
data.tar.gz: cc4e18519b09f7eaa753f9f2e4a500c5b3d0de2aed5bbd275b636d5c21ec763dca2a34da27a16336d65e2ec86d827812c0f546c5e67dfd9b500d683f8baac7ac
|
@@ -34,13 +34,28 @@ module PacketGen
|
|
34
34
|
|
35
35
|
k, v = h.split(':', 2)
|
36
36
|
[k, v.strip]
|
37
|
-
end.
|
37
|
+
end.compact.to_h
|
38
38
|
when Hash
|
39
39
|
@data = s_or_h
|
40
40
|
end
|
41
41
|
self
|
42
42
|
end
|
43
43
|
|
44
|
+
# Get header value from its name
|
45
|
+
# @param [String] header header name
|
46
|
+
# @return [String] header value
|
47
|
+
def [](header)
|
48
|
+
data[header]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Say if +self+ include +header+ header
|
52
|
+
# @param [String] header header name
|
53
|
+
# @return [Boolean]
|
54
|
+
def header?(header)
|
55
|
+
data.key?(header)
|
56
|
+
end
|
57
|
+
alias has_header? header?
|
58
|
+
|
44
59
|
# Get binary string.
|
45
60
|
# @return [String]
|
46
61
|
def to_s
|
@@ -86,25 +86,23 @@ module PacketGen
|
|
86
86
|
# Factory to build an option from its type
|
87
87
|
# @return [Option]
|
88
88
|
def self.build(options={})
|
89
|
-
type = options
|
89
|
+
type = options[:type]
|
90
90
|
klass = case type
|
91
91
|
when String
|
92
92
|
types.key?(type) ? IP.const_get(type) : self
|
93
|
-
when Integer
|
94
|
-
types.value?(type) ? IP.const_get(types.key(type)) : self
|
95
93
|
else
|
96
|
-
self
|
94
|
+
types.value?(type) ? IP.const_get(types.key(type.to_i)) : self
|
97
95
|
end
|
96
|
+
options.delete(:type) if klass != self
|
98
97
|
klass.new(options)
|
99
98
|
end
|
100
99
|
|
101
100
|
def initialize(options={})
|
102
|
-
unless options[:type]
|
103
|
-
|
104
|
-
options[:type] = Option.const_get("#{opt_name}_TYPE") if Option.const_defined? "#{opt_name}_TYPE"
|
105
|
-
end
|
101
|
+
options[:type] = class2type unless options[:type]
|
102
|
+
|
106
103
|
super
|
107
|
-
|
104
|
+
initialize_length_if_needed(options)
|
105
|
+
initialize_data_if_needed(options)
|
108
106
|
end
|
109
107
|
|
110
108
|
# Get binary string. Set {#length} field.
|
@@ -121,6 +119,25 @@ module PacketGen
|
|
121
119
|
str << ":#{self[:data].to_s.inspect}" if respond_to?(:length) && (length > 2) && !self[:data].to_s.empty?
|
122
120
|
str
|
123
121
|
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def class2type
|
126
|
+
opt_name = self.class.to_s.gsub(/.*::/, '')
|
127
|
+
Option.const_get("#{opt_name}_TYPE") if Option.const_defined? "#{opt_name}_TYPE"
|
128
|
+
end
|
129
|
+
|
130
|
+
def initialize_length_if_needed(options)
|
131
|
+
self.length = sz if respond_to?(:length) && options[:length].nil?
|
132
|
+
end
|
133
|
+
|
134
|
+
def initialize_data_if_needed(options)
|
135
|
+
return unless fields.include?(:data) && self[:data].respond_to?(:from_human) && options.key?(:data)
|
136
|
+
|
137
|
+
# Force data if data is set in options but not length
|
138
|
+
self.length += options[:data].size
|
139
|
+
self[:data].from_human(options[:data])
|
140
|
+
end
|
124
141
|
end
|
125
142
|
|
126
143
|
# End-of-option-List IP option
|
@@ -173,6 +190,10 @@ module PacketGen
|
|
173
190
|
# 16-bit stream ID
|
174
191
|
# @return [Integer]
|
175
192
|
define_field :id, Types::Int16
|
193
|
+
|
194
|
+
def to_human
|
195
|
+
super << ":#{self.id}"
|
196
|
+
end
|
176
197
|
end
|
177
198
|
|
178
199
|
# Router Alert IP option
|
@@ -183,6 +204,10 @@ module PacketGen
|
|
183
204
|
# 16-bit value. Should be 0.
|
184
205
|
# @return [Integer]
|
185
206
|
define_field :value, Types::Int16, default: 0
|
207
|
+
|
208
|
+
def to_human
|
209
|
+
super << ":#{self.value}"
|
210
|
+
end
|
186
211
|
end
|
187
212
|
end
|
188
213
|
end
|
@@ -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
|
@@ -154,26 +154,19 @@ module PacketGen
|
|
154
154
|
self
|
155
155
|
end
|
156
156
|
|
157
|
-
#
|
158
|
-
|
159
|
-
# Populate object from a string
|
160
|
-
# @param [String] str
|
157
|
+
# Populate object from a string or from an array of hashes
|
158
|
+
# @param [String, Array<Hash>] data
|
161
159
|
# @return [self]
|
162
|
-
def read(
|
160
|
+
def read(data)
|
163
161
|
clear
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
obj = create_object_from_str(str)
|
170
|
-
@array << obj
|
171
|
-
str.slice!(0, obj.sz)
|
172
|
-
break if @counter && self.size == @counter.to_i
|
162
|
+
case data
|
163
|
+
when ::Array
|
164
|
+
read_from_array(data)
|
165
|
+
else
|
166
|
+
read_from_string(data)
|
173
167
|
end
|
174
168
|
self
|
175
169
|
end
|
176
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
177
170
|
|
178
171
|
# Get size in bytes
|
179
172
|
# @return [Integer]
|
@@ -201,6 +194,28 @@ module PacketGen
|
|
201
194
|
|
202
195
|
private
|
203
196
|
|
197
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
198
|
+
|
199
|
+
def read_from_string(str)
|
200
|
+
return self if str.nil? || @counter&.to_i&.zero?
|
201
|
+
|
202
|
+
str = read_with_length_from(str)
|
203
|
+
until str.empty? || (@counter && self.size == @counter.to_i)
|
204
|
+
obj = create_object_from_str(str)
|
205
|
+
@array << obj
|
206
|
+
str.slice!(0, obj.sz)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
210
|
+
|
211
|
+
def read_from_array(ary)
|
212
|
+
return self if ary.empty?
|
213
|
+
|
214
|
+
ary.each do |hsh|
|
215
|
+
self << hsh
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
204
219
|
def record_from_hash(hsh)
|
205
220
|
obj_klass = self.class.set_of_klass
|
206
221
|
raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of' unless obj_klass
|
@@ -61,7 +61,8 @@ module PacketGen
|
|
61
61
|
|
62
62
|
# @return [String]
|
63
63
|
def inspect
|
64
|
-
|
64
|
+
str = Inspect.dashed_line(self.class)
|
65
|
+
str << Inspect.inspect_body(body)
|
65
66
|
end
|
66
67
|
|
67
68
|
# equality if {#to_s} is equal
|
@@ -74,7 +75,7 @@ module PacketGen
|
|
74
75
|
# @return [Boolean]
|
75
76
|
def ===(other)
|
76
77
|
case other
|
77
|
-
when
|
78
|
+
when UnknownPacket
|
78
79
|
self == other
|
79
80
|
else
|
80
81
|
false
|
data/lib/packetgen/utils.rb
CHANGED
@@ -25,23 +25,32 @@ module PacketGen
|
|
25
25
|
' (ip dst %<target2>s and not ip src %<local_ip>s))' \
|
26
26
|
' and ether dst %<local_mac>s'
|
27
27
|
|
28
|
+
# @private
|
29
|
+
ARP_PATH = '/usr/sbin/arp'
|
30
|
+
# @private
|
31
|
+
IP_PATH = '/usr/bin/ip'
|
32
|
+
# @private
|
33
|
+
ARP_LINE_RE = /\((\d+\.\d+\.\d+\.\d+)\) at (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})(?: \[ether\])? on (\w+)/.freeze
|
34
|
+
# @private
|
35
|
+
IP_LINE_RE = /^(\d+\.\d+\.\d+\.\d+) dev (\w+) lladdr (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})/.freeze
|
36
|
+
|
28
37
|
# Get local ARP cache
|
29
38
|
# @return [Hash] key: IP address, value: array containing MAC address and
|
30
39
|
# interface name
|
31
40
|
def self.arp_cache
|
32
|
-
return self.cache_from_arp_command if File.exist?(
|
33
|
-
return self.cache_from_ip_command if File.exist?(
|
41
|
+
return self.cache_from_arp_command if File.exist?(ARP_PATH)
|
42
|
+
return self.cache_from_ip_command if File.exist?(IP_PATH)
|
34
43
|
|
35
44
|
{}
|
36
45
|
end
|
37
46
|
|
38
47
|
# @private
|
39
|
-
def self.cache_from_arp_command
|
40
|
-
raw_cache
|
48
|
+
def self.cache_from_arp_command(raw_cache=nil)
|
49
|
+
raw_cache ||= `#{ARP_PATH} -an`
|
41
50
|
|
42
51
|
cache = {}
|
43
52
|
raw_cache.split("\n").each do |line|
|
44
|
-
match = line.match(
|
53
|
+
match = line.match(ARP_LINE_RE)
|
45
54
|
cache[match[1]] = [match[2], match[4]] if match
|
46
55
|
end
|
47
56
|
|
@@ -49,12 +58,12 @@ module PacketGen
|
|
49
58
|
end
|
50
59
|
|
51
60
|
# @private
|
52
|
-
def self.cache_from_ip_command
|
53
|
-
raw_cache
|
61
|
+
def self.cache_from_ip_command(raw_cache=nil)
|
62
|
+
raw_cache ||= `#{IP_PATH} neigh`
|
54
63
|
|
55
64
|
cache = {}
|
56
65
|
raw_cache.split("\n").each do |line|
|
57
|
-
match = line.match(
|
66
|
+
match = line.match(IP_LINE_RE)
|
58
67
|
cache[match[1]] = [match[3], match[2]] if match
|
59
68
|
end
|
60
69
|
|
@@ -155,7 +164,7 @@ module PacketGen
|
|
155
164
|
# end
|
156
165
|
# @since 2.2.0
|
157
166
|
# @raise [RuntimeError] user don't have permission to capture packets on network device.
|
158
|
-
def self.mitm(target1, target2, options={})
|
167
|
+
def self.mitm(target1, target2, options={}, &block)
|
159
168
|
options = { iface: PacketGen.default_iface }.merge(options)
|
160
169
|
|
161
170
|
spoofer = Utils::ARPSpoofer.new(options)
|
@@ -168,7 +177,7 @@ module PacketGen
|
|
168
177
|
filter: MITM_FILTER % { target1: target1, target2: target2, local_ip: cfg.ipaddr(options[:iface]), local_mac: my_mac })
|
169
178
|
|
170
179
|
spoofer.start_all
|
171
|
-
mitm_core(capture, target1, target2, my_mac, &
|
180
|
+
mitm_core(capture, target1, target2, my_mac, &block)
|
172
181
|
spoofer.stop_all
|
173
182
|
end
|
174
183
|
|
data/lib/packetgen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interfacez
|