packetgen 3.1.8 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 539fce01eed5ce8711896ea7c9f22d29e3878b5165676ff673dd527c748d1fdb
4
- data.tar.gz: bd724c164c6adf60b772b1ead15f9861853f4723711fe44cfdf49520a16a78c7
3
+ metadata.gz: 8f3faa715cd36e918df79355267c50690bdde15f1566e23947d26890e7b89a82
4
+ data.tar.gz: d374447f230500b0c5be84b225d3a5576f019afc4870dc6512c659bc2e069d67
5
5
  SHA512:
6
- metadata.gz: f63e7926b399ee2550fdb29fa688bf4c580ad7b8be2f0518089e94c758d1fb84d70f9e1f148c004d5008697b6dbf83bc32637f994119126ceace6e1ef259c1a0
7
- data.tar.gz: 8be8c39afec1aee25250b7c8e7f1bbcc81f680356079cca3d179fc671f407d53a4365b6df72c58c9b2947df6e6fe1f80f28b3cb9d31f2dfa445b61aaa3de1693
6
+ metadata.gz: de7911facea630eaa2d3d4afd2ae15e1cbd927241ebf0c63ec096c64eac31c58e519d379476763c50fc1b4290029cec4b14dbf9e96ae9aa05dc06701cf45af32
7
+ data.tar.gz: 69881fc66b4af80177bdad4b5b2daa4bd28259596bbf8a36112998aa9a8c117c7c9898180372635fcc1b47376e2fab4fb5cece88be5c000277cdce825fb03168
data/lib/packetgen.rb CHANGED
@@ -95,7 +95,15 @@ module PacketGen
95
95
  # Get default network interface (ie. first non-loopback declared interface)
96
96
  # @return [String]
97
97
  def self.default_iface
98
- Interfacez.default
98
+ return @default_iface if defined? @default_iface
99
+
100
+ @default_iface = Interfacez.raw_interface_addresses.each do |iface|
101
+ next unless iface.broadaddr
102
+ next unless Interfacez.ipv4_address_of(iface.name)
103
+ next unless Interfacez.ipv6_address_of(iface.name)
104
+
105
+ break iface.name
106
+ end
99
107
  end
100
108
 
101
109
  # Get loopback network interface
@@ -126,6 +134,7 @@ require 'packetgen/types'
126
134
  require 'packetgen/pcapng'
127
135
  require 'packetgen/pcap'
128
136
  require 'packetgen/packet'
137
+ require 'packetgen/unknown_packet'
129
138
  require 'packetgen/capture'
130
139
  require 'packetgen/inject'
131
140
  require 'packetgen/proto'
@@ -122,7 +122,11 @@ module PacketGen
122
122
  def add_packet(data, &block)
123
123
  raw_packets << data
124
124
  if @parse
125
- packet = Packet.parse(data)
125
+ begin
126
+ packet = Packet.parse(data)
127
+ rescue ParseError
128
+ packet = UnknownPacket.new.parse(data)
129
+ end
126
130
  packets << packet
127
131
  block&.call(packet)
128
132
  elsif block
@@ -19,14 +19,20 @@ module PacketGen
19
19
  class ASN1Base < RASN1::Model
20
20
  include Headerable
21
21
 
22
- # Define some methods from given ASN.1 fields to mimic {Base} attributes
23
- # @param [Array<Symbol>] attributes
24
- # @return [void]
25
- def self.define_attributes(*attributes)
26
- @attributes = attributes
27
- attributes.each do |attr|
28
- class_eval "def #{attr}; @elements[:#{attr}].value; end\n" \
29
- "def #{attr}=(v); @elements[:#{attr}].value = v; end"
22
+ class <<self
23
+ # Define some methods from given ASN.1 fields to mimic {Base} attributes
24
+ # @param [Array<Symbol>] attributes
25
+ # @return [void]
26
+ def define_attributes(*attributes)
27
+ @attributes = attributes
28
+ attributes.each do |attr|
29
+ class_eval "def #{attr}; @elements[:#{attr}].value; end\n" \
30
+ "def #{attr}=(v); @elements[:#{attr}].value = v; end"
31
+ end
32
+ end
33
+
34
+ def known_headers
35
+ @known_headers ||= {}.freeze
30
36
  end
31
37
  end
32
38
 
@@ -37,7 +43,11 @@ module PacketGen
37
43
  # @param [String] str
38
44
  # @return [ASN1Base] self
39
45
  def read(str)
40
- parse(str, ber: true)
46
+ begin
47
+ parse(str, ber: true)
48
+ rescue RASN1::ASN1Error
49
+ # suppress exception to allow guessing
50
+ end
41
51
  self
42
52
  end
43
53
 
@@ -67,59 +67,49 @@ module PacketGen
67
67
  # Get destination MAC address
68
68
  # @return [String]
69
69
  def dst
70
- ds = frame_ctrl & 3
71
- case ds
72
- when 0, 2
73
- self.mac1
74
- when 1, 3
75
- self.mac3
76
- end
70
+ _src_mac, dst_mac = src_dst_from_mac
71
+ self.send(dst_mac)
77
72
  end
78
73
 
79
74
  # Set destination MAC address
80
75
  # @param [String] mac MAC address to set
81
76
  # @return [String]
82
77
  def dst=(mac)
83
- ds = frame_ctrl & 3
84
- case ds
85
- when 0, 2
86
- self.mac1 = mac
87
- when 1, 3
88
- self.mac3 = mac
89
- end
78
+ _src_mac, dst_mac = src_dst_from_mac
79
+ self.send("#{dst_mac}=", mac)
90
80
  end
91
81
 
92
82
  # Get source MAC address
93
83
  # @return [String]
94
84
  def src
95
- ds = frame_ctrl & 3
96
- case ds
97
- when 0, 1
98
- self.mac2
99
- when 2
100
- self.mac3
101
- when 3
102
- self.mac4
103
- end
85
+ src_mac, = src_dst_from_mac
86
+ self.send(src_mac)
104
87
  end
105
88
 
106
89
  # Set source MAC address
107
90
  # @param [String] mac MAC address to set
108
91
  # @return [String]
109
92
  def src=(mac)
93
+ src_mac, = src_dst_from_mac
94
+ self.send("#{src_mac}=", mac)
95
+ end
96
+
97
+ private
98
+
99
+ def src_dst_from_mac
110
100
  ds = frame_ctrl & 3
111
101
  case ds
112
- when 0, 1
113
- self.mac2 = mac
102
+ when 0
103
+ %i[mac2 mac1]
104
+ when 1
105
+ %i[mac2 mac3]
114
106
  when 2
115
- self.mac3 = mac
107
+ %i[mac3 mac1]
116
108
  when 3
117
- self.mac4 = mac
109
+ %i[mac4 mac3]
118
110
  end
119
111
  end
120
112
 
121
- private
122
-
123
113
  def define_applicable_fields
124
114
  super
125
115
  if (subtype >= 8) && !@applicable_fields.include?(:qos_ctrl)
@@ -81,6 +81,10 @@ module PacketGen
81
81
  self
82
82
  end
83
83
 
84
+ def parse?
85
+ VERBS.include?(self.verb) && self.version.start_with?('HTTP/1.')
86
+ end
87
+
84
88
  # String representation of data.
85
89
  # @return [String]
86
90
  def to_s
@@ -116,6 +120,6 @@ module PacketGen
116
120
  end
117
121
 
118
122
  self.add_class HTTP::Request
119
- TCP.bind HTTP::Request, body: ->(b) { HTTP::REQUEST_REGEX =~ b.chars.select(&:valid_encoding?).join }
123
+ TCP.bind HTTP::Request, body: ->(b) { b.nil? ? '' : HTTP::REQUEST_REGEX =~ b }
120
124
  end
121
125
  end
@@ -87,15 +87,21 @@ module PacketGen
87
87
  end
88
88
  unless headers.empty?
89
89
  first_line = headers.shift.split
90
- self[:version].read first_line[0]
91
- self[:status_code].read first_line[1]
92
- self[:status_mesg].read first_line[2..-1].join(' ')
90
+ if first_line.size >= 3
91
+ self[:version].read first_line[0]
92
+ self[:status_code].read first_line[1]
93
+ self[:status_mesg].read first_line[2..-1].join(' ')
94
+ end
93
95
  self[:headers].read(headers.join("\n"))
94
96
  end
95
97
  self[:body].read data.join("\n")
96
98
  self
97
99
  end
98
100
 
101
+ def parse?
102
+ version.start_with?('HTTP/1.')
103
+ end
104
+
99
105
  # String representation of data.
100
106
  # @return [String]
101
107
  def to_s
@@ -112,6 +118,6 @@ module PacketGen
112
118
  end
113
119
 
114
120
  self.add_class HTTP::Response
115
- TCP.bind HTTP::Response, body: ->(b) { %r[^HTTP/1\.1\s\d{3,}\s.+] =~ b.chars.select(&:valid_encoding?).join }
121
+ TCP.bind HTTP::Response, body: ->(b) { b.nil? ? '' : %r[^HTTP/1\.1\s\d{3,}\s.+] =~ b }
116
122
  end
117
123
  end
@@ -16,7 +16,7 @@ module PacketGen
16
16
  VERBS = %w[GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH].freeze
17
17
 
18
18
  # Identifiable HTTP request regular expression.
19
- REQUEST_REGEX = Regexp.new("(#{VERBS.dup.join('|')})\\s+\\S+\\s+HTTP/1.1")
19
+ REQUEST_REGEX = Regexp.new("^(#{VERBS.dup.join('|')})\\s+\\S+\\s+HTTP/1.1")
20
20
  end
21
21
  end
22
22
  end
@@ -229,9 +229,13 @@ module PacketGen
229
229
 
230
230
  def get_lsa_class_by_human_type(htype)
231
231
  klassname = "LSA#{htype.to_s.delete('-')}"
232
- if OSPFv2.const_defined? klassname
233
- OSPFv2.const_get klassname
234
- else
232
+ begin
233
+ if OSPFv2.const_defined? klassname
234
+ OSPFv2.const_get klassname
235
+ else
236
+ LSA
237
+ end
238
+ rescue NameError
235
239
  LSA
236
240
  end
237
241
  end
@@ -218,9 +218,13 @@ module PacketGen
218
218
 
219
219
  def get_lsa_class_by_human_type(htype)
220
220
  klassname = "LSA#{htype.to_s.delete('-')}"
221
- if OSPFv3.const_defined? klassname
222
- OSPFv3.const_get klassname
223
- else
221
+ begin
222
+ if OSPFv3.const_defined? klassname
223
+ OSPFv3.const_get klassname
224
+ else
225
+ LSA
226
+ end
227
+ rescue NameError
224
228
  LSA
225
229
  end
226
230
  end
@@ -81,7 +81,7 @@ module PacketGen
81
81
  # @return [Array<Packet>] captured packet
82
82
  def self.capture(**kwargs, &block)
83
83
  capture = Capture.new(**kwargs)
84
- if block_given?
84
+ if block
85
85
  capture.start(&block)
86
86
  else
87
87
  capture.start
@@ -216,7 +216,7 @@ module PacketGen
216
216
  # @return [Array] see return from {PcapNG::File#to_file}
217
217
  # @see File
218
218
  def to_f(filename)
219
- PcapNG::File.new.array_to_file(file: filename, array: [self])
219
+ PcapNG::File.new.read_array([self]).to_f(filename)
220
220
  end
221
221
  alias write to_f
222
222
 
@@ -287,7 +287,7 @@ module PacketGen
287
287
  if first_header.nil?
288
288
  # No decoding forced for first header. Have to guess it!
289
289
  first_header = guess_first_header(binary_str)
290
- raise ParseError, 'cannot identify first header in string' if first_header.nil?
290
+ raise ParseError, "cannot identify first header in string: #{binary_str.inspect}" if first_header.nil?
291
291
  end
292
292
 
293
293
  add first_header
@@ -264,7 +264,7 @@ module PacketGen
264
264
  # @param [Time, nil] timestamp initial timestamp, used for first packet
265
265
  # @param [Numeric, nil] ts_inc timestamp increment, in seconds, to increment
266
266
  # initial timestamp for each packet
267
- # @return [void]
267
+ # @return [self]
268
268
  # @note if +timestamp+ and/or +ts_inc+ are nil, {SPB} sections are created
269
269
  # for each packet, else {EPB} ones are used
270
270
  # @since 3.1.6
@@ -276,11 +276,12 @@ module PacketGen
276
276
  classify_block(section, block)
277
277
  ts = update_ts(ts, ts_inc)
278
278
  end
279
+ self
279
280
  end
280
281
 
281
282
  # Update current object from a hash of packets and timestamps
282
283
  # @param [Hash{Time => Packet}] hsh
283
- # @return [void]
284
+ # @return [self]
284
285
  # @since 3.1.6
285
286
  def read_hash(hsh)
286
287
  section = create_new_shb_section
@@ -288,6 +289,7 @@ module PacketGen
288
289
  block = create_block_from_pkt(pkt, section, ts, 0)
289
290
  classify_block(section, block)
290
291
  end
292
+ self
291
293
  end
292
294
 
293
295
  # @return [String]
@@ -0,0 +1,84 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # This file is part of PacketGen
5
+ # See https://github.com/sdaubert/packetgen for more informations
6
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
7
+ # This program is published under MIT license.
8
+
9
+ module PacketGen
10
+ # Unknown packet, minimaly mimicking a {Packet}.
11
+ #
12
+ # An unknown packet is generated when capturing packets, and a packet cannot
13
+ # be parsed.
14
+ # @since 3.2.0
15
+ class UnknownPacket
16
+ # List of headers. Always empty
17
+ # @return [Array]
18
+ attr_reader :headers
19
+
20
+ def initialize
21
+ @headers = [].freeze
22
+ @binary_str = PacketGen.force_binary('')
23
+ end
24
+
25
+ # Unknown packet, so unknown protocol.
26
+ # @return [false]
27
+ def is?(_protocol)
28
+ false
29
+ end
30
+
31
+ # Get packet body
32
+ # @return [Types]
33
+ def body
34
+ @binary_str
35
+ end
36
+ alias to_s body
37
+
38
+ # Set packet body
39
+ # @param [String] str
40
+ # @return [void]
41
+ def body=(str)
42
+ @binary_str = PacketGen.force_binary(str)
43
+ end
44
+
45
+ # Write packet to a PCapNG file on disk.
46
+ # @param [String] filename
47
+ # @return [Array] see return from {PcapNG::File#to_file}
48
+ # @see File
49
+ def to_f(filename)
50
+ PcapNG::File.new.read_array([self]).to_f(filename)
51
+ end
52
+ alias write to_f
53
+
54
+ # Read binary string
55
+ # @param [String] binary_string
56
+ # @return [self]
57
+ def parse(binary_str, _first_header: nil)
58
+ @binary_str = PacketGen.force_binary(binary_str)
59
+ self
60
+ end
61
+
62
+ # @return [String]
63
+ def inspect
64
+ # TODO
65
+ end
66
+
67
+ # equality if {#to_s} is equal
68
+ # @return [Boolean]
69
+ def ==(other)
70
+ to_s == other.to_s
71
+ end
72
+
73
+ # True only if +other+ is an {UnknownPacket} and +other == self+
74
+ # @return [Boolean]
75
+ def ===(other)
76
+ case other
77
+ when UnknwonPacket
78
+ self == other
79
+ else
80
+ false
81
+ end
82
+ end
83
+ end
84
+ end
@@ -23,7 +23,7 @@ module PacketGen
23
23
  raw_cache = `/usr/sbin/arp -an`
24
24
 
25
25
  cache = {}
26
- raw_cache.split(/\n/).each do |line|
26
+ raw_cache.split("\n").each do |line|
27
27
  match = line.match(/\((\d+\.\d+\.\d+\.\d+)\) at (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})(?: \[ether\])? on (\w+)/)
28
28
  cache[match[1]] = [match[2], match[4]] if match
29
29
  end
@@ -46,7 +46,7 @@ module PacketGen
46
46
  def self.arp(ipaddr, options={})
47
47
  unless options[:no_cache]
48
48
  local_cache = self.arp_cache
49
- return local_cache[ipaddr].first if local_cache.key? ipaddr
49
+ return local_cache[ipaddr].first if local_cache.key?(ipaddr)
50
50
  end
51
51
 
52
52
  iface = options[:iface] || PacketGen.default_iface
@@ -54,13 +54,12 @@ module PacketGen
54
54
  my_hwaddr = Config.instance.hwaddr(iface)
55
55
  arp_pkt = Packet.gen('Eth', dst: 'ff:ff:ff:ff:ff:ff', src: my_hwaddr)
56
56
  .add('ARP', sha: Config.instance.hwaddr(iface),
57
- spa: Config.instance.ipaddr(iface), tpa: ipaddr)
57
+ spa: Config.instance.ipaddr(iface),
58
+ tpa: ipaddr)
58
59
 
59
60
  capture = Capture.new(iface: iface, timeout: timeout, max: 1,
60
61
  filter: "arp src #{ipaddr} and ether dst #{my_hwaddr}")
61
- cap_thread = Thread.new do
62
- capture.start
63
- end
62
+ cap_thread = Thread.new { capture.start }
64
63
 
65
64
  arp_pkt.to_w(iface)
66
65
  cap_thread.join
@@ -10,5 +10,5 @@
10
10
  # @author Sylvain Daubert
11
11
  module PacketGen
12
12
  # PacketGen version
13
- VERSION = '3.1.8'
13
+ VERSION = '3.2.0'
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.1.8
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-13 00:00:00.000000000 Z
11
+ date: 2021-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interfacez
@@ -233,10 +233,11 @@ files:
233
233
  - lib/packetgen/types/oui.rb
234
234
  - lib/packetgen/types/string.rb
235
235
  - lib/packetgen/types/tlv.rb
236
+ - lib/packetgen/unknown_packet.rb
236
237
  - lib/packetgen/utils.rb
237
238
  - lib/packetgen/utils/arp_spoofer.rb
238
239
  - lib/packetgen/version.rb
239
- homepage:
240
+ homepage:
240
241
  licenses:
241
242
  - MIT
242
243
  metadata:
@@ -245,7 +246,7 @@ metadata:
245
246
  bug_tracker_uri: https://github.com/sdaubert/packetgen/issues
246
247
  documentation_uri: https://www.rubydoc.info/gems/packetgen
247
248
  wiki_uri: https://github.com/sdaubert/packetgen/wiki
248
- post_install_message:
249
+ post_install_message:
249
250
  rdoc_options:
250
251
  - "--title"
251
252
  - PacketGen - network packet dissector
@@ -266,8 +267,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
267
  - !ruby/object:Gem::Version
267
268
  version: '0'
268
269
  requirements: []
269
- rubygems_version: 3.2.3
270
- signing_key:
270
+ rubygems_version: 3.2.5
271
+ signing_key:
271
272
  specification_version: 4
272
273
  summary: Network packet generator and dissector
273
274
  test_files: []