packetgen 3.1.5 → 3.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/pgconsole +1 -0
- data/lib/packetgen.rb +2 -2
- data/lib/packetgen/capture.rb +9 -0
- data/lib/packetgen/header/base.rb +68 -70
- data/lib/packetgen/header/dhcpv6/duid.rb +3 -1
- data/lib/packetgen/header/dhcpv6/option.rb +3 -1
- data/lib/packetgen/header/dns/name.rb +18 -7
- data/lib/packetgen/header/dns/question.rb +2 -0
- data/lib/packetgen/header/dot11.rb +23 -6
- data/lib/packetgen/header/dot11/data.rb +9 -5
- data/lib/packetgen/header/eap.rb +3 -2
- data/lib/packetgen/header/eth.rb +4 -8
- data/lib/packetgen/header/http/headers.rb +3 -4
- data/lib/packetgen/header/http/request.rb +32 -17
- data/lib/packetgen/header/http/response.rb +1 -1
- data/lib/packetgen/header/http/verbs.rb +1 -1
- data/lib/packetgen/header/igmpv3/group_record.rb +2 -0
- data/lib/packetgen/header/ip.rb +27 -26
- data/lib/packetgen/header/ip/addr.rb +2 -3
- data/lib/packetgen/header/ip/option.rb +4 -4
- data/lib/packetgen/header/ipv6/addr.rb +1 -2
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -0
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +6 -0
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -0
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -0
- data/lib/packetgen/header/ospfv3/lsa.rb +2 -0
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
- data/lib/packetgen/header/snmp.rb +3 -2
- data/lib/packetgen/header/tcp/option.rb +8 -6
- data/lib/packetgen/packet.rb +7 -3
- data/lib/packetgen/pcapng.rb +11 -11
- data/lib/packetgen/pcapng/block.rb +15 -2
- data/lib/packetgen/pcapng/epb.rb +22 -15
- data/lib/packetgen/pcapng/file.rb +164 -81
- data/lib/packetgen/pcapng/idb.rb +7 -9
- data/lib/packetgen/pcapng/shb.rb +35 -28
- data/lib/packetgen/pcapng/spb.rb +16 -12
- data/lib/packetgen/pcapng/unknown_block.rb +3 -11
- data/lib/packetgen/pcaprub_wrapper.rb +8 -8
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/abstract_tlv.rb +2 -3
- data/lib/packetgen/types/array.rb +15 -9
- data/lib/packetgen/types/cstring.rb +38 -17
- data/lib/packetgen/types/fieldable.rb +65 -0
- data/lib/packetgen/types/fields.rb +91 -56
- data/lib/packetgen/types/int.rb +2 -2
- data/lib/packetgen/types/int_string.rb +7 -2
- data/lib/packetgen/types/length_from.rb +18 -10
- data/lib/packetgen/types/oui.rb +1 -2
- data/lib/packetgen/types/string.rb +45 -8
- data/lib/packetgen/types/tlv.rb +1 -2
- data/lib/packetgen/utils.rb +2 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +13 -12
- data/lib/packetgen/inspectable.rb +0 -20
data/lib/packetgen/pcapng/idb.rb
CHANGED
@@ -60,7 +60,7 @@ module PacketGen
|
|
60
60
|
# @option options [Integer] :block_len2 block total length
|
61
61
|
def initialize(options={})
|
62
62
|
super
|
63
|
-
|
63
|
+
endianness(options[:endian] || :little)
|
64
64
|
@packets = []
|
65
65
|
@options_decoded = false
|
66
66
|
recalc_block_len
|
@@ -74,15 +74,12 @@ module PacketGen
|
|
74
74
|
io = to_io(str_or_io)
|
75
75
|
return self if io.eof?
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
self[:reserved].read io.read(2)
|
81
|
-
self[:snaplen].read io.read(4)
|
77
|
+
%i[type block_len link_type reserved snaplen].each do |attr|
|
78
|
+
self[attr].read io.read(self[attr].sz)
|
79
|
+
end
|
82
80
|
self[:options].read io.read(self.block_len - MIN_SIZE)
|
83
|
-
|
81
|
+
read_blocklen2_and_check(io)
|
84
82
|
|
85
|
-
check_len_coherency
|
86
83
|
self
|
87
84
|
end
|
88
85
|
|
@@ -91,6 +88,7 @@ module PacketGen
|
|
91
88
|
# @return [self]
|
92
89
|
def <<(xpb)
|
93
90
|
@packets << xpb
|
91
|
+
xpb.interface = self
|
94
92
|
self
|
95
93
|
end
|
96
94
|
|
@@ -133,7 +131,7 @@ module PacketGen
|
|
133
131
|
|
134
132
|
while idx < options.length
|
135
133
|
opt_code, opt_len = options[idx, 4].unpack("#{packstr}2")
|
136
|
-
return options[idx + 4, 1].
|
134
|
+
return options[idx + 4, 1].unpack1('C') if opt_code == OPTION_IF_TSRESOL && opt_len == 1
|
137
135
|
|
138
136
|
idx += 4 + opt_len
|
139
137
|
end
|
data/lib/packetgen/pcapng/shb.rb
CHANGED
@@ -80,7 +80,7 @@ module PacketGen
|
|
80
80
|
super
|
81
81
|
@interfaces = []
|
82
82
|
@unknown_blocks = []
|
83
|
-
|
83
|
+
endianness(options[:endian] || :little)
|
84
84
|
recalc_block_len
|
85
85
|
self.type = options[:type] || PcapNG::SHB_TYPE.to_i
|
86
86
|
end
|
@@ -92,29 +92,15 @@ module PacketGen
|
|
92
92
|
io = to_io(str_or_io)
|
93
93
|
return self if io.eof?
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
case magic_str
|
100
|
-
when MAGIC_LITTLE
|
101
|
-
force_endianness :little if @endian == :big
|
102
|
-
when MAGIC_BIG
|
103
|
-
force_endianness :big if @endian == :little
|
104
|
-
else
|
105
|
-
raise InvalidFileError, 'Incorrect magic for Section Header Block'
|
95
|
+
self[:type].read check_shb(io)
|
96
|
+
%i[block_len magic ver_major ver_minor section_len].each do |attr|
|
97
|
+
self[attr].read io.read(self[attr].sz)
|
106
98
|
end
|
99
|
+
handle_magic_and_check(self[:magic].to_s)
|
107
100
|
|
108
|
-
|
109
|
-
|
110
|
-
self[:magic].read magic_str
|
111
|
-
self[:ver_major].read io.read(2)
|
112
|
-
self[:ver_minor].read io.read(2)
|
113
|
-
self[:section_len].read io.read(8)
|
114
|
-
self[:options].read io.read(self.block_len - MIN_SIZE)
|
115
|
-
self[:block_len2].read io.read(4)
|
101
|
+
read_options(io)
|
102
|
+
read_blocklen2_and_check(io)
|
116
103
|
|
117
|
-
check_len_coherency
|
118
104
|
self
|
119
105
|
end
|
120
106
|
|
@@ -123,6 +109,7 @@ module PacketGen
|
|
123
109
|
# @return [self]
|
124
110
|
def <<(idb)
|
125
111
|
@interfaces << idb
|
112
|
+
idb.section = self
|
126
113
|
self
|
127
114
|
end
|
128
115
|
|
@@ -137,17 +124,22 @@ module PacketGen
|
|
137
124
|
super + body
|
138
125
|
end
|
139
126
|
|
127
|
+
def add_unknown_block(block)
|
128
|
+
self.unknown_blocks << block
|
129
|
+
block.section = self
|
130
|
+
end
|
131
|
+
|
140
132
|
private
|
141
133
|
|
142
134
|
def force_endianness(endian)
|
143
135
|
@endian = endian
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
self[:
|
136
|
+
%i[type block_len magic block_len2].each do |attr|
|
137
|
+
self[attr] = Types::Int32.new(0, endian).read(self[attr].to_s)
|
138
|
+
end
|
139
|
+
%i[ver_major ver_minor].each do |attr|
|
140
|
+
self[attr] = Types::Int16.new(0, endian).read(self[attr].to_s)
|
141
|
+
end
|
142
|
+
self[:section_len] = Types::Int64.new(0, endian).read(self[:section_len].to_s)
|
151
143
|
end
|
152
144
|
|
153
145
|
# Check io contains a SHB
|
@@ -160,6 +152,21 @@ module PacketGen
|
|
160
152
|
type = type_str.unpack('H*').join
|
161
153
|
raise InvalidFileError, "Incorrect type (#{type})for Section Header Block"
|
162
154
|
end
|
155
|
+
|
156
|
+
def handle_magic_and_check(magic_str)
|
157
|
+
case magic_str
|
158
|
+
when MAGIC_LITTLE
|
159
|
+
force_endianness :little if endian == :big
|
160
|
+
when MAGIC_BIG
|
161
|
+
force_endianness :big if endian == :little
|
162
|
+
else
|
163
|
+
raise InvalidFileError, 'Incorrect magic for Section Header Block'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def read_options(io)
|
168
|
+
self[:options].read io.read(self.block_len - MIN_SIZE)
|
169
|
+
end
|
163
170
|
end
|
164
171
|
end
|
165
172
|
end
|
data/lib/packetgen/pcapng/spb.rb
CHANGED
@@ -44,7 +44,7 @@ module PacketGen
|
|
44
44
|
# @option options [Integer] :block_len2 block total length
|
45
45
|
def initialize(options={})
|
46
46
|
super
|
47
|
-
|
47
|
+
endianness(options[:endian] || :little)
|
48
48
|
recalc_block_len
|
49
49
|
self.type = options[:type] || PcapNG::SPB_TYPE.to_i
|
50
50
|
end
|
@@ -66,19 +66,11 @@ module PacketGen
|
|
66
66
|
self[:type].read io.read(4)
|
67
67
|
self[:block_len].read io.read(4)
|
68
68
|
self[:orig_len].read io.read(4)
|
69
|
-
|
70
|
-
# CAUTION: snaplen == 0 -> no capture limit
|
71
|
-
data_len = if interface && interface.snaplen.to_i.positive?
|
72
|
-
[self[:orig_len].to_i, interface.snaplen.to_i].min
|
73
|
-
else
|
74
|
-
self[:orig_len].to_i
|
75
|
-
end
|
76
|
-
data_pad_len = (4 - (data_len % 4)) % 4
|
69
|
+
data_len = compute_data_len
|
77
70
|
self[:data].read io.read(data_len)
|
78
|
-
io
|
79
|
-
|
71
|
+
remove_padding(io, data_len)
|
72
|
+
read_blocklen2_and_check(io)
|
80
73
|
|
81
|
-
check_len_coherency
|
82
74
|
self.type ||= PcapNG::IDB_TYPE.to_i
|
83
75
|
self
|
84
76
|
end
|
@@ -90,6 +82,18 @@ module PacketGen
|
|
90
82
|
recalc_block_len
|
91
83
|
super
|
92
84
|
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Take care of IDB snaplen
|
89
|
+
# CAUTION: snaplen == 0 -> no capture limit
|
90
|
+
def compute_data_len
|
91
|
+
if interface && interface.snaplen.to_i.positive?
|
92
|
+
[self[:orig_len].to_i, interface.snaplen.to_i].min
|
93
|
+
else
|
94
|
+
self[:orig_len].to_i
|
95
|
+
end
|
96
|
+
end
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
@@ -29,7 +29,7 @@ module PacketGen
|
|
29
29
|
# @option options [Integer] :block_len2 block total length
|
30
30
|
def initialize(options={})
|
31
31
|
super
|
32
|
-
|
32
|
+
endianness(options[:endian] || :little)
|
33
33
|
recalc_block_len
|
34
34
|
end
|
35
35
|
|
@@ -44,21 +44,13 @@ module PacketGen
|
|
44
44
|
# @param [::String,IO] str_or_io
|
45
45
|
# @return [self]
|
46
46
|
def read(str_or_io)
|
47
|
-
io =
|
48
|
-
str_or_io
|
49
|
-
else
|
50
|
-
StringIO.new(force_binary(str_or_io.to_s))
|
51
|
-
end
|
47
|
+
io = to_io(str_or_io)
|
52
48
|
return self if io.eof?
|
53
49
|
|
54
50
|
self[:type].read io.read(4)
|
55
51
|
self[:block_len].read io.read(4)
|
56
52
|
self[:body].read io.read(self[:block_len].to_i - MIN_SIZE)
|
57
|
-
|
58
|
-
|
59
|
-
unless self[:block_len].to_i == self[:block_len2].to_i
|
60
|
-
raise InvalidFileError, 'Incoherency in Header Block'
|
61
|
-
end
|
53
|
+
read_blocklen2_and_check(io)
|
62
54
|
|
63
55
|
self
|
64
56
|
end
|
@@ -38,6 +38,8 @@ module PacketGen
|
|
38
38
|
pcap.activate
|
39
39
|
end
|
40
40
|
|
41
|
+
# rubocop:disable Metrics/ParameterLists
|
42
|
+
|
41
43
|
# Capture packets from a network interface
|
42
44
|
# @param [String] iface interface name
|
43
45
|
# @param [Integer] snaplen
|
@@ -49,14 +51,14 @@ module PacketGen
|
|
49
51
|
# @author Sylvain Daubert
|
50
52
|
# @author optix2000 - add support for setting monitor mode
|
51
53
|
# @since 3.1.5 add monitor argument
|
52
|
-
def self.capture(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, filter: nil, monitor: nil)
|
54
|
+
def self.capture(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, filter: nil, monitor: nil, &block)
|
53
55
|
pcap = self.open_iface(iface: iface, snaplen: snaplen, promisc: promisc, monitor: monitor)
|
54
56
|
pcap.setfilter filter unless filter.nil?
|
55
|
-
pcap.each
|
56
|
-
yield packet_data
|
57
|
-
end
|
57
|
+
pcap.each(&block)
|
58
58
|
end
|
59
59
|
|
60
|
+
# rubocop:enable Metrics/ParameterLists
|
61
|
+
|
60
62
|
# Inject given data onto wire
|
61
63
|
# @param [String] iface interface name
|
62
64
|
# @param [String] data to inject
|
@@ -72,10 +74,8 @@ module PacketGen
|
|
72
74
|
# @yieldparam [String] data binary packet data
|
73
75
|
# @return [void]
|
74
76
|
# @author Kent Gruber
|
75
|
-
def self.read_pcap(filename
|
76
|
-
PCAPRUB::Pcap.open_offline(filename).each_packet
|
77
|
-
yield packet
|
78
|
-
end
|
77
|
+
def self.read_pcap(filename:, &block)
|
78
|
+
PCAPRUB::Pcap.open_offline(filename).each_packet(&block)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
data/lib/packetgen/types.rb
CHANGED
@@ -58,7 +58,7 @@ module PacketGen
|
|
58
58
|
# @since 3.1.0
|
59
59
|
# @since 3.1.1 add +:aliases+ keyword to {#initialize}
|
60
60
|
class AbstractTLV < Types::Fields
|
61
|
-
include
|
61
|
+
include Fieldable
|
62
62
|
|
63
63
|
class <<self
|
64
64
|
# @return [Hash]
|
@@ -171,9 +171,8 @@ module PacketGen
|
|
171
171
|
# @return [String]
|
172
172
|
def to_human
|
173
173
|
my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human
|
174
|
-
|
174
|
+
'type:%s,length:%u,value:%s' % [human_type, length, my_value]
|
175
175
|
end
|
176
|
-
alias format_inspect to_human
|
177
176
|
|
178
177
|
private
|
179
178
|
|
@@ -27,8 +27,8 @@ module PacketGen
|
|
27
27
|
# @author Sylvain Daubert
|
28
28
|
class Array
|
29
29
|
extend Forwardable
|
30
|
-
include Inspectable
|
31
30
|
include Enumerable
|
31
|
+
include Fieldable
|
32
32
|
include LengthFrom
|
33
33
|
|
34
34
|
# @!method [](index)
|
@@ -163,11 +163,8 @@ module PacketGen
|
|
163
163
|
return self if @counter&.to_i&.zero?
|
164
164
|
|
165
165
|
str = read_with_length_from(str)
|
166
|
-
klass = self.class.set_of_klass
|
167
166
|
until str.empty?
|
168
|
-
obj =
|
169
|
-
real_klass = real_type(obj)
|
170
|
-
obj = real_klass.new.read(str) unless real_klass == klass
|
167
|
+
obj = create_object_from_str(str)
|
171
168
|
@array << obj
|
172
169
|
str.slice!(0, obj.sz)
|
173
170
|
break if @counter && self.size == @counter.to_i
|
@@ -198,15 +195,12 @@ module PacketGen
|
|
198
195
|
def to_human
|
199
196
|
@array.map(&:to_human).join(self.class::HUMAN_SEPARATOR)
|
200
197
|
end
|
201
|
-
alias format_inspect to_human
|
202
198
|
|
203
199
|
private
|
204
200
|
|
205
201
|
def record_from_hash(hsh)
|
206
202
|
obj_klass = self.class.set_of_klass
|
207
|
-
unless obj_klass
|
208
|
-
raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of'
|
209
|
-
end
|
203
|
+
raise NotImplementedError, 'class should define #record_from_hash or declare type of elements in set with .set_of' unless obj_klass
|
210
204
|
|
211
205
|
obj = obj_klass.new(hsh) if obj_klass
|
212
206
|
klass = real_type(obj)
|
@@ -216,6 +210,18 @@ module PacketGen
|
|
216
210
|
def real_type(obj)
|
217
211
|
obj.class
|
218
212
|
end
|
213
|
+
|
214
|
+
def create_object_from_str(str)
|
215
|
+
klass = self.class.set_of_klass
|
216
|
+
obj = klass.new.read(str)
|
217
|
+
real_klass = real_type(obj)
|
218
|
+
|
219
|
+
if real_klass == klass
|
220
|
+
obj
|
221
|
+
else
|
222
|
+
real_klass.new.read(str)
|
223
|
+
end
|
224
|
+
end
|
219
225
|
end
|
220
226
|
|
221
227
|
# Specialized array to handle serie of {Int8}.
|
@@ -6,17 +6,29 @@
|
|
6
6
|
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
7
7
|
# This program is published under MIT license.
|
8
8
|
|
9
|
+
require 'forwardable'
|
10
|
+
|
9
11
|
module PacketGen
|
10
12
|
module Types
|
11
13
|
# This class handles null-terminated strings (aka C strings).
|
12
14
|
# @author Sylvain Daubert
|
13
|
-
|
14
|
-
|
15
|
+
# @since 3.1.6 no more a subclass or regular String
|
16
|
+
class CString
|
17
|
+
extend Forwardable
|
18
|
+
include Fieldable
|
19
|
+
|
20
|
+
def_delegators :@string, :[], :length, :size, :inspect, :==, :<<,
|
21
|
+
:unpack, :force_encoding, :encoding, :index, :empty?
|
22
|
+
|
23
|
+
# @return [::String]
|
24
|
+
attr_reader :string
|
25
|
+
# @return [Integer]
|
26
|
+
attr_reader :static_length
|
15
27
|
|
16
28
|
# @param [Hash] options
|
17
29
|
# @option options [Integer] :static_length set a static length for this string
|
18
30
|
def initialize(options={})
|
19
|
-
|
31
|
+
register_internal_string ''
|
20
32
|
@static_length = options[:static_length]
|
21
33
|
end
|
22
34
|
|
@@ -24,38 +36,41 @@ module PacketGen
|
|
24
36
|
# @return [String] self
|
25
37
|
def read(str)
|
26
38
|
s = str.to_s
|
27
|
-
s = s[0,
|
39
|
+
s = s[0, static_length] if static_length?
|
28
40
|
idx = s.index(0.chr)
|
29
41
|
s = s[0, idx] unless idx.nil?
|
30
|
-
|
42
|
+
register_internal_string s
|
31
43
|
self
|
32
44
|
end
|
33
45
|
|
34
46
|
# get null-terminated string
|
35
47
|
# @return [String]
|
36
48
|
def to_s
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
s[-1] = "\x00".encode(s.encoding)
|
41
|
-
PacketGen.force_binary s
|
42
|
-
else
|
43
|
-
PacketGen.force_binary(self + "\0" * (@static_length - self.length))
|
44
|
-
end
|
49
|
+
if static_length?
|
50
|
+
s = string[0, static_length - 1]
|
51
|
+
s << "\x00" * (static_length - s.length)
|
45
52
|
else
|
46
|
-
|
53
|
+
s = "#{string}\x00"
|
47
54
|
end
|
55
|
+
PacketGen.force_binary(s)
|
48
56
|
end
|
49
57
|
|
50
58
|
# @return [Integer]
|
51
59
|
def sz
|
52
|
-
if
|
53
|
-
|
60
|
+
if static_length?
|
61
|
+
static_length
|
54
62
|
else
|
55
63
|
to_s.size
|
56
64
|
end
|
57
65
|
end
|
58
66
|
|
67
|
+
# Say if a static length is defined
|
68
|
+
# @return [Boolean]
|
69
|
+
# @since 3.1.6
|
70
|
+
def static_length?
|
71
|
+
!static_length.nil?
|
72
|
+
end
|
73
|
+
|
59
74
|
# Populate CString from a human readable string
|
60
75
|
# @param [String] str
|
61
76
|
# @return [self]
|
@@ -68,7 +83,13 @@ module PacketGen
|
|
68
83
|
idx = self.index(+"\x00".encode(self.encoding)) || self.sz
|
69
84
|
self[0, idx]
|
70
85
|
end
|
71
|
-
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def register_internal_string(str)
|
90
|
+
@string = str
|
91
|
+
PacketGen.force_binary(@string)
|
92
|
+
end
|
72
93
|
end
|
73
94
|
end
|
74
95
|
end
|