packetgen 3.2.2 → 3.3.1

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: ad942df146df9daf8c38e049fc112b13c93fd38a45362e8dd2a43c6e8382b224
4
- data.tar.gz: 77b48a6af0170a912e91b888456c31881bfe1fd30a693796c849a946b5e27bac
3
+ metadata.gz: cdbaefa45999efbdef944fd579a9657a4ce4cfbf247bab09a4a7692ac22f9126
4
+ data.tar.gz: 8bce62a68be0b6803eea0a1323009c0413c20e1b4628062f22bcb240909f93a5
5
5
  SHA512:
6
- metadata.gz: 98f7f9d7dd652741cdce08cbe081310c4f4ca6745702efc5755806614f30c7930498610f9925a6d7abeef1b8b64abfa2857c77bcc638872f31577fe587ad1e63
7
- data.tar.gz: cc4e18519b09f7eaa753f9f2e4a500c5b3d0de2aed5bbd275b636d5c21ec763dca2a34da27a16336d65e2ec86d827812c0f546c5e67dfd9b500d683f8baac7ac
6
+ metadata.gz: 20246ef1684a643dc0f18ecb25558e78ae70197f141dfa059bbd5559806c87229436432816a7ca3c1008910f15c010842a08dca0de5e50499fad283566953f01
7
+ data.tar.gz: c8576c49901a2c49336b638f859d80446c0773701177e3aeb4d24324c264d00f58ec4fbe6a3c5a1dd71247385f0fcb421953e4b1865144119a9d07242c0d6f97
@@ -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
@@ -60,63 +60,101 @@ module PacketGen
60
60
  class AbstractTLV < Types::Fields
61
61
  include Fieldable
62
62
 
63
+ # @private
64
+ FIELD_TYPES = { 'T' => :type, 'L' => :length, 'V' => :value }.freeze
65
+
63
66
  class << self
64
67
  # @return [Hash]
65
68
  attr_accessor :aliases
69
+ # @deprecated
66
70
  attr_accessor :header_in_length
67
- end
68
- self.aliases = {}
69
-
70
- # Generate a TLV class
71
- # @param [Class] type_class Class to use for +type+
72
- # @param [Class] length_class Class to use for +length+
73
- # @param [Class] value_class Class to use for +value+
74
- # @param [Boolean] header_in_length if +true +, +type+ and +length+ fields are
75
- # included in length
76
- # @return [Class]
77
- # @since 3.1.4 Add +header_in_length+ parameter
78
- def self.create(type_class: Int8Enum, length_class: Int8, value_class: String,
79
- aliases: {}, header_in_length: false)
80
- raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal? AbstractTLV
81
-
82
- klass = Class.new(self)
83
- klass.aliases = aliases
84
- klass.header_in_length = header_in_length
85
-
86
- if type_class < Enum
87
- klass.define_field :type, type_class, enum: {}
88
- else
89
- klass.define_field :type, type_class
71
+ # @private
72
+ attr_accessor :field_in_length
73
+
74
+ # Generate a TLV class
75
+ # @param [Class] type_class Class to use for +type+
76
+ # @param [Class] length_class Class to use for +length+
77
+ # @param [Class] value_class Class to use for +value+
78
+ # @param [Boolean] header_in_length if +true +, +type+ and +length+ fields are
79
+ # included in length. Deprecated, use +field_in_length+ instead.
80
+ # @param [String] field_order give field order. Each character in [T,L,V] MUST be present once, in the desired order.
81
+ # @param [String] field_in_length give fields to compute length on.
82
+ # @return [Class]
83
+ # @since 3.1.4 Add +header_in_length+ parameter
84
+ # @since 3.3.1 Add +field_order+ and +field_in_length' parameters. Deprecate +header_in_length+ parameter.
85
+ def create(type_class: Int8Enum, length_class: Int8, value_class: String,
86
+ aliases: {}, header_in_length: false, field_order: 'TLV', field_in_length: 'V')
87
+ Deprecation.deprecated_option(self, 'create', 'header_in_length', klass_method: true) if header_in_length
88
+ raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal?(AbstractTLV)
89
+
90
+ klass = Class.new(self)
91
+ klass.aliases = aliases
92
+ klass.header_in_length = header_in_length
93
+ klass.field_in_length = field_in_length
94
+
95
+ check_field_in_length(field_in_length)
96
+ check_field_order(field_order)
97
+ generate_fields(klass, field_order, type_class, length_class, value_class)
98
+
99
+ aliases.each do |al, orig|
100
+ klass.instance_eval do
101
+ alias_method al, orig if klass.method_defined?(orig)
102
+ alias_method :"#{al}=", :"#{orig}=" if klass.method_defined?(:"#{orig}=")
103
+ end
104
+ end
105
+
106
+ klass
90
107
  end
91
- klass.define_field :length, length_class
92
- klass.define_field :value, value_class
93
108
 
94
- aliases.each do |al, orig|
95
- klass.instance_eval do
96
- alias_method al, orig if klass.method_defined?(orig)
97
- alias_method :"#{al}=", :"#{orig}=" if klass.method_defined?(:"#{orig}=")
98
- end
109
+ # @!attribute type
110
+ # @abstract Type attribute for real TLV class
111
+ # @return [Integer]
112
+ # @!attribute length
113
+ # @abstract Length attribute for real TLV class
114
+ # @return [Integer]
115
+ # @!attribute value
116
+ # @abstract Value attribute for real TLV class
117
+ # @return [Object]
118
+
119
+ # @abstract Should only be called on real TLV classes, created by {.create}.
120
+ # Set enum hash for {#type} field.
121
+ # @param [Hash] hsh enum hash
122
+ # @return [void]
123
+ def define_type_enum(hsh)
124
+ field_defs[:type][:enum].clear
125
+ field_defs[:type][:enum].merge!(hsh)
99
126
  end
100
127
 
101
- klass
102
- end
103
- # @!attribute type
104
- # @abstract Type attribute for real TLV class
105
- # @return [Integer]
106
- # @!attribute length
107
- # @abstract Length attribute for real TLV class
108
- # @return [Integer]
109
- # @!attribute value
110
- # @abstract Value attribute for real TLV class
111
- # @return [Object]
128
+ private
112
129
 
113
- # @abstract Should only be called on real TLV classes, created by {.create}.
114
- # Set enum hash for {#type} field.
115
- # @param [Hash] hsh enum hash
116
- # @return [void]
117
- def self.define_type_enum(hsh)
118
- field_defs[:type][:enum].clear
119
- field_defs[:type][:enum].merge!(hsh)
130
+ def check_field_in_length(field_in_length)
131
+ return if /^[TLV]{1,3}$/.match?(field_in_length)
132
+
133
+ raise 'field_in_length must only contain T, L and/or V characters'
134
+ end
135
+
136
+ def check_field_order(field_order)
137
+ return if field_order.match(/^[TLV]{3,3}$/) && (field_order[0] != field_order[1]) && (field_order[0] != field_order[2]) && (field_order[1] != field_order[2])
138
+
139
+ raise 'field_order must contain all three letters TLV, each once'
140
+ end
141
+
142
+ def generate_fields(klass, field_order, type_class, length_class, value_class)
143
+ field_order.each_char do |field_type|
144
+ case field_type
145
+ when 'T'
146
+ if type_class < Enum
147
+ klass.define_field(:type, type_class, enum: {})
148
+ else
149
+ klass.define_field(:type, type_class)
150
+ end
151
+ when 'L'
152
+ klass.define_field(:length, length_class)
153
+ when 'V'
154
+ klass.define_field(:value, value_class)
155
+ end
156
+ end
157
+ end
120
158
  end
121
159
 
122
160
  # @abstract Should only be called on real TLV classes, created by {.create}.
@@ -126,6 +164,7 @@ module PacketGen
126
164
  # @option options [Object] :value
127
165
  def initialize(options={})
128
166
  @header_in_length = self.class.header_in_length
167
+ @field_in_length = self.class.field_in_length
129
168
  self.class.aliases.each do |al, orig|
130
169
  options[orig] = options[al] if options.key?(al)
131
170
  end
@@ -141,11 +180,13 @@ module PacketGen
141
180
  # @return [Fields] self
142
181
  def read(str)
143
182
  idx = 0
144
- self[:type].read str[idx, self[:type].sz]
145
- idx += self[:type].sz
146
- self[:length].read str[idx, self[:length].sz]
147
- idx += self[:length].sz
148
- self[:value].read str[idx, real_length]
183
+ fields.each do |field_name|
184
+ field = self[field_name]
185
+ length = field_name == :value ? real_length : field.sz
186
+ field.read(str[idx, length])
187
+ idx += field.sz
188
+ end
189
+
149
190
  self
150
191
  end
151
192
 
@@ -154,9 +195,17 @@ module PacketGen
154
195
  # @param [::String,Integer] val
155
196
  # @return [::String,Integer]
156
197
  def value=(val)
157
- self[:value].from_human val
158
- self.length = self[:value].sz
159
- self.length += self[:type].sz + self[:length].sz if @header_in_length
198
+ self[:value].from_human(val)
199
+
200
+ fil = @field_in_length
201
+ fil = 'TLV' if @header_in_length
202
+
203
+ length = 0
204
+ fil.each_char do |field_type|
205
+ length += self[FIELD_TYPES[field_type]].sz
206
+ end
207
+ self.length = length
208
+
160
209
  val
161
210
  end
162
211
 
@@ -180,7 +229,10 @@ module PacketGen
180
229
  if @header_in_length
181
230
  self.length - self[:type].sz - self[:length].sz
182
231
  else
183
- self.length
232
+ length = self.length
233
+ length -= self[:type].sz if @field_in_length.include?('T')
234
+ length -= self[:length].sz if @field_in_length.include?('L')
235
+ length
184
236
  end
185
237
  end
186
238
  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.
@@ -11,6 +11,7 @@ module PacketGen
11
11
  # Base integer class to handle binary integers
12
12
  # @abstract
13
13
  # @author Sylvain Daubert
14
+ # @since 3.3.1 support native endianess
14
15
  class Int
15
16
  include Fieldable
16
17
 
@@ -18,7 +19,8 @@ module PacketGen
18
19
  # @return [Integer]
19
20
  attr_accessor :value
20
21
  # Integer endianness
21
- # @return [:little,:big]
22
+ # @return [:little,:big,:native]
23
+ # @since 3.3.1 add :native
22
24
  attr_accessor :endian
23
25
  # Integer size, in bytes
24
26
  # @return [Integer]
@@ -128,10 +130,10 @@ module PacketGen
128
130
  # @author Sylvain Daubert
129
131
  class Int16 < Int
130
132
  # @param [Integer,nil] value
131
- # @param [:big, :little] endian
133
+ # @param [:big, :little, :native] endian
132
134
  def initialize(value=nil, endian=:big)
133
135
  super(value, endian, 2)
134
- @packstr = { big: 'n', little: 'v' }
136
+ @packstr = { big: 'n', little: 'v', native: 'S' }
135
137
  end
136
138
  end
137
139
 
@@ -153,6 +155,19 @@ module PacketGen
153
155
  end
154
156
  end
155
157
 
158
+ # native endian 2-byte unsigned integer
159
+ # @author Sylvain Daubert
160
+ # @since 3.3.1
161
+ class Int16n < Int16
162
+ # @param [Integer,nil] value
163
+ undef endian=
164
+
165
+ # @param [Integer, nil] value
166
+ def initialize(value=nil)
167
+ super(value, :native)
168
+ end
169
+ end
170
+
156
171
  # 2-byte signed integer
157
172
  # @author Sylvain Daubert
158
173
  # @since 2.8.2
@@ -161,7 +176,7 @@ module PacketGen
161
176
  # @param [:big, :little] endian
162
177
  def initialize(value=nil, endian=:big)
163
178
  super
164
- @packstr = { big: 's>', little: 's<' }
179
+ @packstr = { big: 's>', little: 's<', native: 's' }
165
180
  end
166
181
  end
167
182
 
@@ -185,13 +200,33 @@ module PacketGen
185
200
  end
186
201
  end
187
202
 
203
+ # native endian 2-byte signed integer
204
+ # @author Sylvain Daubert
205
+ # @since 3.3.1
206
+ class SInt16n < SInt16
207
+ # @param [Integer,nil] value
208
+ undef endian=
209
+
210
+ # @param [Integer, nil] value
211
+ def initialize(value=nil)
212
+ super(value, :native)
213
+ end
214
+ end
215
+
188
216
  # 3-byte unsigned integer
189
217
  # @author Sylvain Daubert
190
218
  # @since 2.1.4
191
219
  class Int24 < Int
192
220
  # @param [Integer,nil] value
193
- # @param [:big, :little] endian
221
+ # @param [:big, :little, :native] endian
194
222
  def initialize(value=nil, endian=:big)
223
+ if endian == :native
224
+ endian = if [1].pack('S').unpack1('n') == 1
225
+ :big
226
+ else
227
+ :little
228
+ end
229
+ end
195
230
  super(value, endian, 3)
196
231
  end
197
232
 
@@ -247,14 +282,27 @@ module PacketGen
247
282
  end
248
283
  end
249
284
 
285
+ # native endian 3-byte unsigned integer
286
+ # @author Sylvain Daubert
287
+ # @since 3.3.1
288
+ class Int24n < Int24
289
+ # @param [Integer,nil] value
290
+ undef endian=
291
+
292
+ # @param [Integer, nil] value
293
+ def initialize(value=nil)
294
+ super(value, :native)
295
+ end
296
+ end
297
+
250
298
  # 4-byte unsigned integer
251
299
  # @author Sylvain Daubert
252
300
  class Int32 < Int
253
301
  # @param [Integer,nil] value
254
- # @param [:big, :little] endian
302
+ # @param [:big, :little, :native] endian
255
303
  def initialize(value=nil, endian=:big)
256
304
  super(value, endian, 4)
257
- @packstr = { big: 'N', little: 'V' }
305
+ @packstr = { big: 'N', little: 'V', native: 'L' }
258
306
  end
259
307
  end
260
308
 
@@ -276,6 +324,19 @@ module PacketGen
276
324
  end
277
325
  end
278
326
 
327
+ # native endian 4-byte unsigned integer
328
+ # @author Sylvain Daubert
329
+ # @since 3.3.1
330
+ class Int32n < Int32
331
+ # @param [Integer,nil] value
332
+ undef endian=
333
+
334
+ # @param [Integer, nil] value
335
+ def initialize(value=nil)
336
+ super(value, :native)
337
+ end
338
+ end
339
+
279
340
  # 4-byte unsigned integer
280
341
  # @author Sylvain Daubert
281
342
  # @since 2.8.2
@@ -284,7 +345,7 @@ module PacketGen
284
345
  # @param [:big, :little] endian
285
346
  def initialize(value=nil, endian=:big)
286
347
  super
287
- @packstr = { big: 'l>', little: 'l<' }
348
+ @packstr = { big: 'l>', little: 'l<', native: 'l' }
288
349
  end
289
350
  end
290
351
 
@@ -308,14 +369,27 @@ module PacketGen
308
369
  end
309
370
  end
310
371
 
372
+ # native endian 4-byte unsigned integer
373
+ # @author Sylvain Daubert
374
+ # @since 3.3.1
375
+ class SInt32n < SInt32
376
+ # @param [Integer,nil] value
377
+ undef endian=
378
+
379
+ # @param [Integer, nil] value
380
+ def initialize(value=nil)
381
+ super(value, :native)
382
+ end
383
+ end
384
+
311
385
  # 8-byte unsigned integer
312
386
  # @author Sylvain Daubert
313
387
  class Int64 < Int
314
388
  # @param [Integer,nil] value
315
- # @param [:big, :little] endian
389
+ # @param [:big, :little, :native] endian
316
390
  def initialize(value=nil, endian=:big)
317
391
  super(value, endian, 8)
318
- @packstr = { big: 'Q>', little: 'Q<' }
392
+ @packstr = { big: 'Q>', little: 'Q<', native: 'Q' }
319
393
  end
320
394
  end
321
395
 
@@ -337,15 +411,28 @@ module PacketGen
337
411
  end
338
412
  end
339
413
 
414
+ # native endian 8-byte unsigned integer
415
+ # @author Sylvain Daubert
416
+ # @since 3.3.1
417
+ class Int64n < Int64
418
+ # @param [Integer,nil] value
419
+ undef endian=
420
+
421
+ # @param [Integer, nil] value
422
+ def initialize(value=nil)
423
+ super(value, :native)
424
+ end
425
+ end
426
+
340
427
  # 8-byte unsigned integer
341
428
  # @author Sylvain Daubert
342
429
  # @since 2.8.2
343
430
  class SInt64 < Int64
344
431
  # @param [Integer,nil] value
345
- # @param [:big, :little] endian
432
+ # @param [:big, :little, :native] endian
346
433
  def initialize(value=nil, endian=:big)
347
434
  super
348
- @packstr = { big: 'q>', little: 'q<' }
435
+ @packstr = { big: 'q>', little: 'q<', native: 'q' }
349
436
  end
350
437
  end
351
438
 
@@ -368,5 +455,18 @@ module PacketGen
368
455
  super(value, :little)
369
456
  end
370
457
  end
458
+
459
+ # native endian 8-byte unsigned integer
460
+ # @author Sylvain Daubert
461
+ # @since 3.3.1
462
+ class SInt64n < SInt64
463
+ # @param [Integer,nil] value
464
+ undef endian=
465
+
466
+ # @param [Integer, nil] value
467
+ def initialize(value=nil)
468
+ super(value, :native)
469
+ end
470
+ end
371
471
  end
372
472
  end
@@ -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.1'
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.1
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: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2024-01-04 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.
@@ -237,7 +189,7 @@ files:
237
189
  - lib/packetgen/utils.rb
238
190
  - lib/packetgen/utils/arp_spoofer.rb
239
191
  - lib/packetgen/version.rb
240
- homepage:
192
+ homepage:
241
193
  licenses:
242
194
  - MIT
243
195
  metadata:
@@ -246,7 +198,7 @@ metadata:
246
198
  bug_tracker_uri: https://github.com/sdaubert/packetgen/issues
247
199
  documentation_uri: https://www.rubydoc.info/gems/packetgen
248
200
  wiki_uri: https://github.com/sdaubert/packetgen/wiki
249
- post_install_message:
201
+ post_install_message:
250
202
  rdoc_options:
251
203
  - "--title"
252
204
  - PacketGen - network packet dissector
@@ -260,15 +212,15 @@ 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
  - - ">="
267
219
  - !ruby/object:Gem::Version
268
220
  version: '0'
269
221
  requirements: []
270
- rubygems_version: 3.2.5
271
- signing_key:
222
+ rubygems_version: 3.3.15
223
+ signing_key:
272
224
  specification_version: 4
273
225
  summary: Network packet generator and dissector
274
226
  test_files: []