packetgen 3.2.2 → 3.3.0

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: ad942df146df9daf8c38e049fc112b13c93fd38a45362e8dd2a43c6e8382b224
4
- data.tar.gz: 77b48a6af0170a912e91b888456c31881bfe1fd30a693796c849a946b5e27bac
3
+ metadata.gz: de85a6f18ac001823cdbd0802c8946ead811be724c9069266b78c493d99feb6b
4
+ data.tar.gz: ef73ca367e87bb47ca4f37ee387c7a73d0ad0f19cebaca151443560f42508559
5
5
  SHA512:
6
- metadata.gz: 98f7f9d7dd652741cdce08cbe081310c4f4ca6745702efc5755806614f30c7930498610f9925a6d7abeef1b8b64abfa2857c77bcc638872f31577fe587ad1e63
7
- data.tar.gz: cc4e18519b09f7eaa753f9f2e4a500c5b3d0de2aed5bbd275b636d5c21ec763dca2a34da27a16336d65e2ec86d827812c0f546c5e67dfd9b500d683f8baac7ac
6
+ metadata.gz: '01605812af7b7d53111bfdc0d4d095cb6f0df4975634db17700d7c15c6acc63ba82585e6c5a5d2d93c130d566f45bb62d9ff3709c27e0f7cf4ea0c20ba7c172f'
7
+ data.tar.gz: e4a54c74e032ee12d744f94c657416591c0f056a005da4b104c017294d73819596a28ec59c71597f8d0f2398da79a8b7784809d5e30cd5da9d53fc655101e2f4
@@ -27,6 +27,11 @@ module PacketGen
27
27
  # @return [Array<String>]
28
28
  attr_reader :raw_packets
29
29
 
30
+ # Get timestamps associated with {#packets} and {#raw_packets}
31
+ # @return [Array<Time>]
32
+ # @since 3.3.0
33
+ attr_reader :timestamps
34
+
30
35
  # Get interface name
31
36
  # @return [String]
32
37
  attr_reader :iface
@@ -54,6 +59,7 @@ module PacketGen
54
59
 
55
60
  @packets = []
56
61
  @raw_packets = []
62
+ @timestamps = []
57
63
  set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
58
64
  end
59
65
 
@@ -61,16 +67,18 @@ module PacketGen
61
67
  # @see {#initialize} for parameters
62
68
  # @yieldparam [Packet,String] packet if a block is given, yield each
63
69
  # captured packet (Packet or raw data String, depending on +:parse+ option)
70
+ # @yieldparam [Time] timestamp packet timestamp
64
71
  # @since 3.0.0 arguments are kwargs and no more a hash
65
72
  # @since 3.1.5 add monitor argument
73
+ # @since 3.3.0 add packet timestamp as second yield parameter
66
74
  # @author Sylvain Daubert
67
75
  # @author optix2000 - add monitor argument
68
76
  def start(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: nil, monitor: nil, &block)
69
77
  set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
70
78
 
71
79
  @cap_thread = Thread.new do
72
- PCAPRUBWrapper.capture(**capture_args) do |packet_data|
73
- add_packet(packet_data, &block)
80
+ PCAPRUBWrapper.capture(**capture_args) do |packet|
81
+ add_packet(packet, &block)
74
82
  break if defined?(@max) && (raw_packets.size >= @max)
75
83
  end
76
84
  end
@@ -119,18 +127,21 @@ module PacketGen
119
127
  PCAPRUBWrapper.filter_on(pcap: pcap, filter: filter)
120
128
  end
121
129
 
122
- def add_packet(data, &block)
123
- raw_packets << data
130
+ def add_packet(packet, &block)
131
+ raw_packets << packet.data
132
+ ts = Time.at(packet.time, packet.microsec.to_r, :usec)
133
+ timestamps << ts
134
+
124
135
  if @parse
125
136
  begin
126
- packet = Packet.parse(data)
137
+ packet = Packet.parse(packet.data)
127
138
  rescue ParseError
128
- packet = UnknownPacket.new.parse(data)
139
+ packet = UnknownPacket.new.parse(packet.data)
129
140
  end
130
141
  packets << packet
131
- block&.call(packet)
142
+ block&.call(packet, ts)
132
143
  elsif block
133
- yield data
144
+ yield data, ts
134
145
  end
135
146
  end
136
147
  end
@@ -67,9 +67,9 @@ module PacketGen
67
67
  @pointer = str[start, 2]
68
68
  break
69
69
  else
70
- label = add_label_from(str[start..-1])
70
+ label = add_label_from(str[start..])
71
71
  start += label.sz
72
- break if label.length.zero? || str[start..-1].length.zero?
72
+ break if label.empty? || str[start..].empty?
73
73
  end
74
74
  end
75
75
  # force resolution of compressed names
@@ -110,7 +110,7 @@ module PacketGen
110
110
  ptr = index & mask
111
111
  name = Name.new
112
112
  name.dns = @dns
113
- @pointer_name = name.read(self.dns.to_s[ptr..-1]).to_human
113
+ @pointer_name = name.read(self.dns.to_s[ptr..]).to_human
114
114
  end
115
115
 
116
116
  def record_from_hash(_hsh)
@@ -108,7 +108,7 @@ module PacketGen
108
108
  name.dns = self[:name].dns
109
109
 
110
110
  pref = Types::Int16.new.read(self[:rdata][0, 2])
111
- exchange = name.read(self[:rdata][2..-1]).to_human
111
+ exchange = name.read(self[:rdata][2..]).to_human
112
112
 
113
113
  '%u %s' % [pref.to_i, exchange]
114
114
  end
@@ -118,7 +118,7 @@ module PacketGen
118
118
  name = Name.new
119
119
  name.dns = self[:name].dns
120
120
  mname = name.read(self[:rdata]).dup
121
- rname = name.read(self[:rdata][mname.sz..-1])
121
+ rname = name.read(self[:rdata][mname.sz..])
122
122
 
123
123
  serial = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz, 4])
124
124
  refresh = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 4, 4])
@@ -403,7 +403,7 @@ module PacketGen
403
403
  define_applicable_fields
404
404
  if fcs
405
405
  old_read str[0...-4]
406
- self[:fcs].read str[-4..-1]
406
+ self[:fcs].read str[-4..]
407
407
  else
408
408
  old_read str
409
409
  end
@@ -107,7 +107,7 @@ module PacketGen
107
107
 
108
108
  def headers_and_payload_from_lines(lines)
109
109
  if (data_index = lines.find_index(''))
110
- data = lines[data_index + 1..-1].join("\n")
110
+ data = lines[data_index + 1..].join("\n")
111
111
  headers = lines[0..data_index - 1].join("\n")
112
112
  else
113
113
  headers = lines.join("\n")
@@ -126,7 +126,7 @@ module PacketGen
126
126
 
127
127
  self[:version].read first_line[0]
128
128
  self[:status_code].read first_line[1]
129
- self[:status_mesg].read first_line[2..-1].join(' ')
129
+ self[:status_mesg].read first_line[2..].join(' ')
130
130
  end
131
131
 
132
132
  def raise_on_bad_version_status
@@ -18,7 +18,7 @@ module PacketGen
18
18
  # @return [self]
19
19
  # array << '192.168.1.12'
20
20
  def push(addr)
21
- addr = addr.is_a?(Addr) ? addr : Addr.new.from_human(addr)
21
+ addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
22
22
  super(addr)
23
23
  end
24
24
  end
@@ -77,7 +77,7 @@ module PacketGen
77
77
  Option.constants.each do |cst|
78
78
  next unless cst.to_s.end_with? '_TYPE'
79
79
 
80
- optname = cst.to_s.sub(/_TYPE/, '')
80
+ optname = cst.to_s.sub('_TYPE', '')
81
81
  @types[optname] = Option.const_get(cst)
82
82
  end
83
83
  @types
@@ -107,7 +107,7 @@ module PacketGen
107
107
  # @return [self]
108
108
  # array << '2001:1234::125'
109
109
  def push(addr)
110
- addr = addr.is_a?(Addr) ? addr : Addr.new.from_human(addr)
110
+ addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
111
111
  super(addr)
112
112
  end
113
113
  end
@@ -78,7 +78,7 @@ module PacketGen
78
78
  # @return [Integer]
79
79
  def calc_checksum
80
80
  c0 = c1 = 0
81
- to_s[2..-1].unpack('C*').each do |byte|
81
+ to_s[2..].unpack('C*').each do |byte|
82
82
  c0 += byte
83
83
  c1 += c0
84
84
  end
@@ -79,7 +79,7 @@ module PacketGen
79
79
  # @return [Integer]
80
80
  def calc_checksum
81
81
  c0 = c1 = 0
82
- to_s[2..-1].unpack('C*').each do |byte|
82
+ to_s[2..].unpack('C*').each do |byte|
83
83
  c0 += byte
84
84
  c1 += c0
85
85
  end
@@ -24,7 +24,7 @@ module PacketGen
24
24
  Option.constants.each do |cst|
25
25
  next unless cst.to_s.end_with? '_KIND'
26
26
 
27
- optname = cst.to_s.sub(/_KIND/, '')
27
+ optname = cst.to_s.sub('_KIND', '')
28
28
  @klasses[Option.const_get(cst)] = TCP.const_get(optname)
29
29
  end
30
30
  @klasses
@@ -46,7 +46,7 @@ module PacketGen
46
46
  def method_name
47
47
  return @method_name if defined? @method_name
48
48
 
49
- @method_name = protocol_name.downcase.gsub(/::/, '_')
49
+ @method_name = protocol_name.downcase.gsub('::', '_')
50
50
  end
51
51
 
52
52
  # @abstract Should be redefined by subclasses. This method should check invariant
@@ -36,7 +36,8 @@ module PacketGen
36
36
  # @param [Integer] hexsize
37
37
  # @return [String]
38
38
  def self.int_dec_hex(value, hexsize)
39
- "%-16s (0x%0#{hexsize}x)" % [value.to_i, value.to_i]
39
+ fmt = "%-16s (0x%0#{hexsize}x)"
40
+ fmt % [value.to_i, value.to_i]
40
41
  end
41
42
 
42
43
  # @param [String] str
@@ -44,7 +45,8 @@ module PacketGen
44
45
  # @param [Integer] hexsize
45
46
  # @return [String]
46
47
  def self.enum_human_hex(str, int, hexsize)
47
- "%-16s (0x%0#{hexsize}x)" % [str, int]
48
+ fmt = "%-16s (0x%0#{hexsize}x)"
49
+ fmt % [str, int]
48
50
  end
49
51
 
50
52
  # Simple formatter to inspect an attribute
@@ -90,7 +92,8 @@ module PacketGen
90
92
  val = case attr
91
93
  when RASN1::Types::Enumerated
92
94
  hexsize = attr.value_size * 2
93
- "%-16s (0x%0#{hexsize}x)" % [attr.value, attr.to_i]
95
+ fmt = "%-16s (0x%0#{hexsize}x)"
96
+ fmt % [attr.value, attr.to_i]
94
97
  when RASN1::Types::Integer
95
98
  int_dec_hex(attr.value, attr.value_size * 2)
96
99
  when RASN1::Model
@@ -81,7 +81,9 @@ module PacketGen
81
81
  # @see Capture#initialize
82
82
  # @yieldparam [Packet,String] packet if a block is given, yield each
83
83
  # captured packet (Packet or raw data String, depending on +:parse+ option)
84
+ # @yieldparam [Time] timestamp packet timestamp
84
85
  # @return [Array<Packet>] captured packet
86
+ # @since 3.3.0 add packet timestamp as second yield parameter
85
87
  def self.capture(**kwargs, &block)
86
88
  capture = Capture.new(**kwargs)
87
89
  if block
@@ -21,11 +21,11 @@ module PacketGen
21
21
  }.freeze
22
22
 
23
23
  # @private
24
- BLOCK_TYPES = PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.map do |c|
24
+ BLOCK_TYPES = PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.to_h do |c|
25
25
  type_value = PcapNG.const_get(c).to_i
26
26
  klass = PcapNG.const_get(c.to_s.delete_suffix('_TYPE'))
27
27
  [type_value, klass]
28
- end.to_h.freeze
28
+ end.freeze
29
29
 
30
30
  # Get file sections
31
31
  # @return [Array]
@@ -44,7 +44,7 @@ module PacketGen
44
44
  # @param [Boolean] promisc
45
45
  # @param [String] filter BPF filter
46
46
  # @param [Boolean] monitor
47
- # @yieldparam [String] packet_data binary packet data
47
+ # @yieldparam [String] packet_data packet data
48
48
  # @return [void]
49
49
  # @author Sylvain Daubert
50
50
  # @author optix2000 - add support for setting monitor mode
@@ -52,7 +52,7 @@ module PacketGen
52
52
  def self.capture(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, filter: nil, monitor: nil, &block)
53
53
  pcap = self.open_iface(iface: iface, snaplen: snaplen, promisc: promisc, monitor: monitor)
54
54
  pcap.setfilter filter unless filter.nil?
55
- pcap.each(&block)
55
+ pcap.each_packet(&block)
56
56
  end
57
57
 
58
58
  # Inject given data onto wire
@@ -19,7 +19,7 @@ module PacketGen
19
19
  proto_constants = Socket.constants.grep(/IPPROTO_/)
20
20
  @cache = {}
21
21
  proto_constants.each do |const_sym|
22
- name = const_sym.to_s[8..-1].downcase
22
+ name = const_sym.to_s[8..].downcase
23
23
  number = Socket.const_get(const_sym)
24
24
  @cache[name] = number
25
25
  end
@@ -322,12 +322,14 @@ module PacketGen
322
322
  define << "def #{name}; self[:#{name}].to_i; end"
323
323
  define << "def #{name}=(val) self[:#{name}].value = val; end"
324
324
  else
325
+ # rubocop:disable Layout/LineContinuationLeadingSpace
325
326
  define << "def #{name}\n" \
326
327
  " to_and_from_human?(:#{name}) ? self[:#{name}].to_human : self[:#{name}]\n" \
327
328
  'end'
328
329
  define << "def #{name}=(val)\n" \
329
330
  " to_and_from_human?(:#{name}) ? self[:#{name}].from_human(val) : self[:#{name}].read(val)\n" \
330
331
  'end'
332
+ # rubocop:enable Layout/LineContinuationLeadingSpace
331
333
  end
332
334
 
333
335
  define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
@@ -479,7 +481,7 @@ module PacketGen
479
481
  fields.each do |field|
480
482
  next unless present?(field)
481
483
 
482
- obj = self[field].read str[start..-1]
484
+ obj = self[field].read str[start..]
483
485
  start += self[field].sz
484
486
  self[field] = obj unless obj == self[field]
485
487
  end
@@ -523,7 +525,7 @@ module PacketGen
523
525
  # Return object as a hash
524
526
  # @return [Hash] keys: attributes, values: attribute values
525
527
  def to_h
526
- fields.map { |f| [f, @fields[f].to_human] }.to_h
528
+ fields.to_h { |f| [f, @fields[f].to_human] }
527
529
  end
528
530
 
529
531
  # Get offset of given field in {Fields} structure.
@@ -112,9 +112,11 @@ module PacketGen
112
112
 
113
113
  # Say if spoofing on given target is active or not
114
114
  # @param [String] target_ip target IP address
115
- # @return [Boolean,nil]
115
+ # @return [Boolean]
116
116
  def active?(target_ip)
117
+ # rubocop:disable Style/ReturnNilInPredicateMethodDefinition
117
118
  return unless @targets.key?(target_ip)
119
+ # rubocop:enable Style/ReturnNilInPredicateMethodDefinition
118
120
 
119
121
  @targets[target_ip][:active]
120
122
  end
@@ -19,11 +19,11 @@ module PacketGen
19
19
  # @private
20
20
  ARP_FILTER = 'arp src %<ipaddr>s and ether dst %<hwaddr>s'
21
21
  # @private
22
- MITM_FILTER = '((ip src %<target1>s and not ip dst %<local_ip>s) or' \
23
- ' (ip src %<target2>s and not ip dst %<local_ip>s) or' \
24
- ' (ip dst %<target1>s and not ip src %<local_ip>s) or' \
25
- ' (ip dst %<target2>s and not ip src %<local_ip>s))' \
26
- ' and ether dst %<local_mac>s'
22
+ MITM_FILTER = '((ip src %<target1>s and not ip dst %<local_ip>s) or ' \
23
+ '(ip src %<target2>s and not ip dst %<local_ip>s) or ' \
24
+ '(ip dst %<target1>s and not ip src %<local_ip>s) or ' \
25
+ '(ip dst %<target2>s and not ip src %<local_ip>s)) ' \
26
+ 'and ether dst %<local_mac>s'
27
27
 
28
28
  # @private
29
29
  ARP_PATH = '/usr/sbin/arp'
@@ -10,5 +10,5 @@
10
10
  # @author Sylvain Daubert
11
11
  module PacketGen
12
12
  # PacketGen version
13
- VERSION = '3.2.2'
13
+ VERSION = '3.3.0'
14
14
  end
data/lib/packetgen.rb CHANGED
@@ -64,8 +64,10 @@ module PacketGen
64
64
  # Shortcut for {Packet.capture}
65
65
  # Same arguments as {Capture#initialize}
66
66
  # @see Capture#initialize
67
- # @yieldparam [Packet] packet
67
+ # @yieldparam [Packet,String] packet
68
+ # @yieldparam [Time] timestamp
68
69
  # @return [Array<Packet>]
70
+ # @since 3.3.0 add packet timestamp as second yield parameter
69
71
  def self.capture(**kwargs)
70
72
  Packet.capture(**kwargs) { |packet| yield packet if block_given? }
71
73
  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.2
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2023-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interfacez
@@ -30,76 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.12.0
33
+ version: 0.13.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.12.0
40
+ version: 0.13.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rasn1
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.8'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 0.8.0
47
+ version: '0.12'
51
48
  type: :runtime
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
52
  - - "~>"
56
53
  - !ruby/object:Gem::Version
57
- version: '0.8'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 0.8.0
61
- - !ruby/object:Gem::Dependency
62
- name: rake
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '13.0'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '13.0'
75
- - !ruby/object:Gem::Dependency
76
- name: rspec
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '3.7'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '3.7'
89
- - !ruby/object:Gem::Dependency
90
- name: yard
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '0.9'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '0.9'
54
+ version: '0.12'
103
55
  description: |
104
56
  PacketGen is a network packet manipulation library. It allows reading, parsing
105
57
  and sending network packets with fun.
@@ -260,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
260
212
  requirements:
261
213
  - - ">="
262
214
  - !ruby/object:Gem::Version
263
- version: 2.5.0
215
+ version: 2.6.0
264
216
  required_rubygems_version: !ruby/object:Gem::Requirement
265
217
  requirements:
266
218
  - - ">="