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 +4 -4
- data/lib/packetgen/capture.rb +19 -8
- data/lib/packetgen/header/dns/name.rb +3 -3
- data/lib/packetgen/header/dns/rr.rb +2 -2
- data/lib/packetgen/header/dot11.rb +1 -1
- data/lib/packetgen/header/http/request.rb +1 -1
- data/lib/packetgen/header/http/response.rb +1 -1
- data/lib/packetgen/header/ip/option.rb +2 -2
- data/lib/packetgen/header/ipv6/addr.rb +1 -1
- data/lib/packetgen/header/ospfv2/lsa_header.rb +1 -1
- data/lib/packetgen/header/ospfv3/lsa_header.rb +1 -1
- data/lib/packetgen/header/tcp/options.rb +1 -1
- data/lib/packetgen/headerable.rb +1 -1
- data/lib/packetgen/inspect.rb +6 -3
- data/lib/packetgen/packet.rb +2 -0
- data/lib/packetgen/pcapng/file.rb +2 -2
- data/lib/packetgen/pcaprub_wrapper.rb +2 -2
- data/lib/packetgen/proto.rb +1 -1
- data/lib/packetgen/types/abstract_tlv.rb +109 -57
- data/lib/packetgen/types/fields.rb +4 -2
- data/lib/packetgen/types/int.rb +112 -12
- data/lib/packetgen/utils/arp_spoofer.rb +3 -1
- data/lib/packetgen/utils.rb +5 -5
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +3 -1
- metadata +12 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdbaefa45999efbdef944fd579a9657a4ce4cfbf247bab09a4a7692ac22f9126
|
4
|
+
data.tar.gz: 8bce62a68be0b6803eea0a1323009c0413c20e1b4628062f22bcb240909f93a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20246ef1684a643dc0f18ecb25558e78ae70197f141dfa059bbd5559806c87229436432816a7ca3c1008910f15c010842a08dca0de5e50499fad283566953f01
|
7
|
+
data.tar.gz: c8576c49901a2c49336b638f859d80446c0773701177e3aeb4d24324c264d00f58ec4fbe6a3c5a1dd71247385f0fcb421953e4b1865144119a9d07242c0d6f97
|
data/lib/packetgen/capture.rb
CHANGED
@@ -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 |
|
73
|
-
add_packet(
|
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(
|
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
|
70
|
+
label = add_label_from(str[start..])
|
71
71
|
start += label.sz
|
72
|
-
break if label.
|
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
|
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
|
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
|
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])
|
@@ -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
|
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
|
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 =
|
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(
|
80
|
+
optname = cst.to_s.sub('_TYPE', '')
|
81
81
|
@types[optname] = Option.const_get(cst)
|
82
82
|
end
|
83
83
|
@types
|
data/lib/packetgen/headerable.rb
CHANGED
@@ -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
|
data/lib/packetgen/inspect.rb
CHANGED
@@ -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)"
|
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)"
|
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)"
|
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
|
data/lib/packetgen/packet.rb
CHANGED
@@ -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') }.
|
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.
|
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
|
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.
|
55
|
+
pcap.each_packet(&block)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Inject given data onto wire
|
data/lib/packetgen/proto.rb
CHANGED
@@ -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
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
klass.
|
88
|
-
|
89
|
-
klass.
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
158
|
-
|
159
|
-
|
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
|
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.
|
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.
|
data/lib/packetgen/types/int.rb
CHANGED
@@ -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
|
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
|
data/lib/packetgen/utils.rb
CHANGED
@@ -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
|
-
'
|
24
|
-
'
|
25
|
-
'
|
26
|
-
'
|
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'
|
data/lib/packetgen/version.rb
CHANGED
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.
|
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:
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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: []
|