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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79dc573da10eb15bbd9f38e0c84ecdf9a92d076980628635d1b9e240e3ca2210
4
- data.tar.gz: 0ae2bafa08e5a4a0b176276a141b8c8326265873bb20d86a75e07bb7018275ac
3
+ metadata.gz: ad942df146df9daf8c38e049fc112b13c93fd38a45362e8dd2a43c6e8382b224
4
+ data.tar.gz: 77b48a6af0170a912e91b888456c31881bfe1fd30a693796c849a946b5e27bac
5
5
  SHA512:
6
- metadata.gz: 7c405a57b79c4a9bf0d9032b34d7381b33e8c0705c554023f6a8131c19c48fb0118201d94da62e4f74b9d53551cdbcd434cb6363f27a84e5c3e8459cb28d613b
7
- data.tar.gz: 835969235415864e05b227dd5f0fb48535e3f414e60852cf788d6d90bf29be9a3a8dcf9b636ce8d500d29720753246e11459da925fea3f72f6cb8e11291565b8
6
+ metadata.gz: 98f7f9d7dd652741cdce08cbe081310c4f4ca6745702efc5755806614f30c7930498610f9925a6d7abeef1b8b64abfa2857c77bcc638872f31577fe587ad1e63
7
+ data.tar.gz: cc4e18519b09f7eaa753f9f2e4a500c5b3d0de2aed5bbd275b636d5c21ec763dca2a34da27a16336d65e2ec86d827812c0f546c5e67dfd9b500d683f8baac7ac
@@ -58,6 +58,12 @@ module PacketGen
58
58
  def to_human
59
59
  "DUID<#{type},#{body.inspect}>"
60
60
  end
61
+
62
+ # Get human-readable type
63
+ # @return [String]
64
+ def human_type
65
+ self[:type].to_human
66
+ end
61
67
  end
62
68
 
63
69
  # rubocop:disable Naming/ClassAndModuleCamelCase
@@ -34,13 +34,28 @@ module PacketGen
34
34
 
35
35
  k, v = h.split(':', 2)
36
36
  [k, v.strip]
37
- end.reject(&:nil?).to_h
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.delete(:type)
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
- opt_name = self.class.to_s.gsub(/.*::/, '')
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
- self.length = sz if respond_to?(:length) && options[:length].nil?
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
- data.root.value[data.chosen] = data.root.chosen_value.class.new(options[:pdu])
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 [GetRequest]
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
- # rubocop:disable Metrics/CyclomaticComplexity
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(str)
160
+ def read(data)
163
161
  clear
164
- return self if str.nil?
165
- return self if @counter&.to_i&.zero?
166
-
167
- str = read_with_length_from(str)
168
- until str.empty?
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
- # TODO
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 UnknwonPacket
78
+ when UnknownPacket
78
79
  self == other
79
80
  else
80
81
  false
@@ -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?('/usr/sbin/arp')
33
- return self.cache_from_ip_command if File.exist?('/usr/bin/ip')
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 = `/usr/sbin/arp -an`
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(/\((\d+\.\d+\.\d+\.\d+)\) at (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})(?: \[ether\])? on (\w+)/)
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 = `ip neigh`
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(/^(\d+\.\d+\.\d+\.\d+) dev (\w+) lladdr (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})/)
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, &proc)
180
+ mitm_core(capture, target1, target2, my_mac, &block)
172
181
  spoofer.stop_all
173
182
  end
174
183
 
@@ -10,5 +10,5 @@
10
10
  # @author Sylvain Daubert
11
11
  module PacketGen
12
12
  # PacketGen version
13
- VERSION = '3.2.1'
13
+ VERSION = '3.2.2'
14
14
  end
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.1
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: 2021-12-27 00:00:00.000000000 Z
11
+ date: 2022-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interfacez