packetgen 3.2.2 → 3.3.1

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: 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: []