packetgen 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +28 -0
- data/Rakefile +6 -6
- data/bin/pgconsole +6 -6
- data/lib/packetgen.rb +4 -3
- data/lib/packetgen/capture.rb +5 -7
- data/lib/packetgen/config.rb +3 -3
- data/lib/packetgen/deprecation.rb +17 -0
- data/lib/packetgen/header.rb +40 -38
- data/lib/packetgen/header/arp.rb +46 -31
- data/lib/packetgen/header/asn1_base.rb +8 -8
- data/lib/packetgen/header/base.rb +108 -36
- data/lib/packetgen/header/bootp.rb +28 -19
- data/lib/packetgen/header/crypto.rb +6 -8
- data/lib/packetgen/header/dhcp.rb +4 -5
- data/lib/packetgen/header/dhcp/option.rb +46 -34
- data/lib/packetgen/header/dhcp/options.rb +0 -1
- data/lib/packetgen/header/dhcpv6.rb +10 -10
- data/lib/packetgen/header/dhcpv6/duid.rb +2 -3
- data/lib/packetgen/header/dhcpv6/option.rb +16 -21
- data/lib/packetgen/header/dhcpv6/relay.rb +6 -4
- data/lib/packetgen/header/dns.rb +13 -11
- data/lib/packetgen/header/dns/name.rb +4 -6
- data/lib/packetgen/header/dns/opt.rb +31 -31
- data/lib/packetgen/header/dns/option.rb +0 -2
- data/lib/packetgen/header/dns/qdsection.rb +1 -2
- data/lib/packetgen/header/dns/question.rb +19 -13
- data/lib/packetgen/header/dns/rr.rb +11 -14
- data/lib/packetgen/header/dns/rrsection.rb +5 -7
- data/lib/packetgen/header/dot11.rb +45 -29
- data/lib/packetgen/header/dot11/control.rb +3 -5
- data/lib/packetgen/header/dot11/data.rb +34 -6
- data/lib/packetgen/header/dot11/element.rb +0 -1
- data/lib/packetgen/header/dot11/management.rb +9 -5
- data/lib/packetgen/header/dot11/sub_mngt.rb +13 -14
- data/lib/packetgen/header/dot1q.rb +2 -2
- data/lib/packetgen/header/dot1x.rb +3 -4
- data/lib/packetgen/header/eap.rb +62 -53
- data/lib/packetgen/header/eap/fast.rb +0 -1
- data/lib/packetgen/header/eap/md5.rb +1 -2
- data/lib/packetgen/header/eap/tls.rb +9 -10
- data/lib/packetgen/header/eap/ttls.rb +9 -10
- data/lib/packetgen/header/esp.rb +33 -33
- data/lib/packetgen/header/eth.rb +11 -8
- data/lib/packetgen/header/gre.rb +5 -6
- data/lib/packetgen/header/http/headers.rb +11 -14
- data/lib/packetgen/header/http/request.rb +20 -20
- data/lib/packetgen/header/http/response.rb +16 -18
- data/lib/packetgen/header/http/verbs.rb +5 -5
- data/lib/packetgen/header/icmp.rb +1 -3
- data/lib/packetgen/header/icmpv6.rb +1 -3
- data/lib/packetgen/header/igmp.rb +5 -6
- data/lib/packetgen/header/igmpv3.rb +5 -9
- data/lib/packetgen/header/igmpv3/group_record.rb +4 -5
- data/lib/packetgen/header/igmpv3/mq.rb +2 -2
- data/lib/packetgen/header/igmpv3/mr.rb +4 -3
- data/lib/packetgen/header/ike.rb +33 -8
- data/lib/packetgen/header/ike/auth.rb +4 -6
- data/lib/packetgen/header/ike/cert.rb +0 -2
- data/lib/packetgen/header/ike/certreq.rb +1 -3
- data/lib/packetgen/header/ike/id.rb +1 -3
- data/lib/packetgen/header/ike/ke.rb +0 -2
- data/lib/packetgen/header/ike/nonce.rb +0 -2
- data/lib/packetgen/header/ike/notify.rb +22 -24
- data/lib/packetgen/header/ike/payload.rb +198 -199
- data/lib/packetgen/header/ike/sa.rb +21 -30
- data/lib/packetgen/header/ike/sk.rb +16 -17
- data/lib/packetgen/header/ike/ts.rb +22 -24
- data/lib/packetgen/header/ike/vendor_id.rb +0 -2
- data/lib/packetgen/header/ip.rb +30 -23
- data/lib/packetgen/header/ip/addr.rb +5 -6
- data/lib/packetgen/header/ip/option.rb +11 -15
- data/lib/packetgen/header/ip/options.rb +1 -2
- data/lib/packetgen/header/ipv6.rb +27 -12
- data/lib/packetgen/header/ipv6/addr.rb +2 -2
- data/lib/packetgen/header/ipv6/extension.rb +1 -1
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +11 -11
- data/lib/packetgen/header/llc.rb +4 -3
- data/lib/packetgen/header/mdns.rb +11 -5
- data/lib/packetgen/header/mld.rb +4 -4
- data/lib/packetgen/header/mldv2.rb +4 -3
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +3 -4
- data/lib/packetgen/header/mldv2/mlq.rb +3 -4
- data/lib/packetgen/header/mldv2/mlr.rb +4 -3
- data/lib/packetgen/header/netbios.rb +18 -5
- data/lib/packetgen/header/ospfv2.rb +6 -7
- data/lib/packetgen/header/ospfv2/db_description.rb +3 -4
- data/lib/packetgen/header/ospfv2/hello.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv2/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv2/lsa.rb +13 -14
- data/lib/packetgen/header/ospfv2/lsa_header.rb +4 -5
- data/lib/packetgen/header/ospfv3.rb +3 -4
- data/lib/packetgen/header/ospfv3/db_description.rb +3 -5
- data/lib/packetgen/header/ospfv3/hello.rb +2 -3
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +7 -8
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_request.rb +2 -3
- data/lib/packetgen/header/ospfv3/ls_update.rb +5 -6
- data/lib/packetgen/header/ospfv3/lsa.rb +10 -11
- data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -4
- data/lib/packetgen/header/snmp.rb +45 -32
- data/lib/packetgen/header/tcp.rb +13 -9
- data/lib/packetgen/header/tcp/option.rb +16 -11
- data/lib/packetgen/header/tcp/options.rb +3 -4
- data/lib/packetgen/header/tftp.rb +15 -17
- data/lib/packetgen/header/udp.rb +10 -4
- data/lib/packetgen/inspect.rb +7 -9
- data/lib/packetgen/packet.rb +44 -22
- data/lib/packetgen/pcapng.rb +1 -5
- data/lib/packetgen/pcapng/block.rb +17 -11
- data/lib/packetgen/pcapng/epb.rb +6 -11
- data/lib/packetgen/pcapng/file.rb +37 -44
- data/lib/packetgen/pcapng/idb.rb +17 -22
- data/lib/packetgen/pcapng/shb.rb +7 -10
- data/lib/packetgen/pcapng/spb.rb +21 -17
- data/lib/packetgen/pcapng/unknown_block.rb +17 -13
- data/lib/packetgen/proto.rb +1 -2
- data/lib/packetgen/types/array.rb +119 -34
- data/lib/packetgen/types/cstring.rb +1 -5
- data/lib/packetgen/types/enum.rb +8 -10
- data/lib/packetgen/types/fields.rb +34 -28
- data/lib/packetgen/types/int.rb +11 -13
- data/lib/packetgen/types/int_string.rb +6 -8
- data/lib/packetgen/types/oui.rb +3 -6
- data/lib/packetgen/types/string.rb +4 -6
- data/lib/packetgen/types/tlv.rb +11 -14
- data/lib/packetgen/utils.rb +15 -23
- data/lib/packetgen/utils/arp_spoofer.rb +12 -18
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +9 -8
- metadata +19 -17
@@ -8,8 +8,7 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class EAP
|
11
|
-
|
12
|
-
# Extensible Authentication Protocol (EAP) -
|
11
|
+
# Extensible Authentication Protocol (EAP) -
|
13
12
|
# {https://tools.ietf.org/html/rfc3748#section-5.4 MD5 challenge}
|
14
13
|
# @author Sylvain Daubert
|
15
14
|
# @since 2.1.4
|
@@ -8,7 +8,6 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class EAP
|
11
|
-
|
12
11
|
# Extensible Authentication Protocol (EAP) - TLS,
|
13
12
|
# {https://tools.ietf.org/html/rfc5216 RFC 5216}
|
14
13
|
#
|
@@ -22,7 +21,7 @@ module PacketGen
|
|
22
21
|
# @!attribute flags
|
23
22
|
# @return [Integer] 8-bit flags
|
24
23
|
define_field_before :body, :flags, Types::Int8
|
25
|
-
|
24
|
+
|
26
25
|
# @!attribute l
|
27
26
|
# Say if length field is included. Defined on {#flags} field.
|
28
27
|
# @return [Boolean]
|
@@ -33,17 +32,17 @@ module PacketGen
|
|
33
32
|
# If set, this message is a TLS-Start. Defined on {#flags} field.
|
34
33
|
# @return [Boolean]
|
35
34
|
define_bit_fields_on :flags, :l, :m, :s, :reserved, 5
|
36
|
-
alias
|
37
|
-
alias
|
38
|
-
alias
|
39
|
-
|
35
|
+
alias length_present? l?
|
36
|
+
alias more_fragments? m?
|
37
|
+
alias tls_start? s?
|
38
|
+
|
40
39
|
# @!attribute tls_length
|
41
40
|
# TLS message length. This field provides the total length of the
|
42
41
|
# TLS message or set of messages that is being fragmented. So, it
|
43
42
|
# cannot be automatically calculated (no +#calc_length+ method).
|
44
43
|
# @return [Integer] 32-bit TLS length
|
45
44
|
define_field_before :body, :tls_length, Types::Int32,
|
46
|
-
|
45
|
+
optional: ->(h) { h.l? }
|
47
46
|
|
48
47
|
# @return [EAP::TLS]
|
49
48
|
def initialize(options={})
|
@@ -58,11 +57,11 @@ module PacketGen
|
|
58
57
|
next unless is_present?(attr)
|
59
58
|
if attr == :flags
|
60
59
|
shift = Inspect.shift_level(2)
|
61
|
-
value = %i
|
60
|
+
value = %i[l m s].map { |f| send("#{f}?") ? f.to_s : '.' }.join
|
62
61
|
value = '%-10s (0x%02x)' % [value, self.flags]
|
63
|
-
str << shift
|
62
|
+
str << shift
|
64
63
|
str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
|
65
|
-
|
64
|
+
attr, value]
|
66
65
|
else
|
67
66
|
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
68
67
|
end
|
@@ -8,7 +8,6 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class EAP
|
11
|
-
|
12
11
|
# Extensible Authentication Protocol (EAP) - Tunneled-TLS,
|
13
12
|
# {https://tools.ietf.org/html/rfc5281 RFC 5281}
|
14
13
|
#
|
@@ -22,7 +21,7 @@ module PacketGen
|
|
22
21
|
# @!attribute flags
|
23
22
|
# @return [Integer] 8-bit flags
|
24
23
|
define_field_before :body, :flags, Types::Int8
|
25
|
-
|
24
|
+
|
26
25
|
# @!attribute l
|
27
26
|
# Say if length field is included. Defined on {#flags} field.
|
28
27
|
# @return [Boolean]
|
@@ -37,17 +36,17 @@ module PacketGen
|
|
37
36
|
# @!attribute version
|
38
37
|
# @return [Integer] 3-bit version
|
39
38
|
define_bit_fields_on :flags, :l, :m, :s, :reserved, 2, :version, 3
|
40
|
-
alias
|
41
|
-
alias
|
42
|
-
alias
|
43
|
-
|
39
|
+
alias length_present? l?
|
40
|
+
alias more_fragments? m?
|
41
|
+
alias tls_start? s?
|
42
|
+
|
44
43
|
# @!attribute message_length
|
45
44
|
# Message length. This field provides the total length of the
|
46
45
|
# raw data message sequence prior to fragmentation. So, it
|
47
46
|
# cannot be automatically calculated (no +#calc_length+ method).
|
48
47
|
# @return [Integer] 32-bit message length
|
49
48
|
define_field_before :body, :message_length, Types::Int32,
|
50
|
-
|
49
|
+
optional: ->(h) { h.l? }
|
51
50
|
|
52
51
|
# @return [EAP::TTLS]
|
53
52
|
def initialize(options={})
|
@@ -62,11 +61,11 @@ module PacketGen
|
|
62
61
|
next unless is_present?(attr)
|
63
62
|
if attr == :flags
|
64
63
|
shift = Inspect.shift_level(2)
|
65
|
-
value = %i
|
64
|
+
value = %i[l m s].map { |f| send("#{f}?") ? f.to_s : '.' }.join
|
66
65
|
value = '%-10s (0x%02x)' % [value, self.flags]
|
67
|
-
str << shift
|
66
|
+
str << shift
|
68
67
|
str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
|
69
|
-
|
68
|
+
attr, value]
|
70
69
|
str << Inspect::FMT_ATTR % ['', 'version', self.version]
|
71
70
|
else
|
72
71
|
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
data/lib/packetgen/header/esp.rb
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# A ESP header consists of:
|
12
11
|
# * a Security Parameters Index (#{spi}, {Types::Int32} type),
|
13
12
|
# * a Sequence Number ({#sn}, +Int32+ type),
|
@@ -49,7 +48,7 @@ module PacketGen
|
|
49
48
|
# esp.esp.icv_length = 16
|
50
49
|
# # encapsulate ICMP packet in ESP one
|
51
50
|
# esp.encapsulate icmp
|
52
|
-
#
|
51
|
+
#
|
53
52
|
# # encrypt ESP payload
|
54
53
|
# cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
55
54
|
# cipher.encrypt
|
@@ -61,11 +60,12 @@ module PacketGen
|
|
61
60
|
# cipher = OpenSSL::Cipher.new('aes-128-cbc')
|
62
61
|
# cipher.decrypt
|
63
62
|
# cipher.key = 16bytes_key
|
64
|
-
#
|
63
|
+
#
|
65
64
|
# hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
|
66
65
|
#
|
67
66
|
# pkt.esp.decrypt! cipher, intmode: hmac # => true if ICV check OK
|
68
67
|
# @author Sylvain Daubert
|
68
|
+
# @since 1.2.0
|
69
69
|
class ESP < Base
|
70
70
|
include Crypto
|
71
71
|
|
@@ -140,11 +140,11 @@ module PacketGen
|
|
140
140
|
force_binary str
|
141
141
|
self[:spi].read str[0, 4]
|
142
142
|
self[:sn].read str[4, 4]
|
143
|
-
self[:body].read str[8...-@icv_length-2]
|
143
|
+
self[:body].read str[8...-@icv_length - 2]
|
144
144
|
self[:tfc].read ''
|
145
145
|
self[:padding].read ''
|
146
|
-
self[:pad_length].read str[-@icv_length-2, 1]
|
147
|
-
self[:next].read str[-@icv_length-1, 1]
|
146
|
+
self[:pad_length].read str[-@icv_length - 2, 1]
|
147
|
+
self[:next].read str[-@icv_length - 1, 1]
|
148
148
|
self[:icv].read str[-@icv_length, @icv_length] if @icv_length
|
149
149
|
self
|
150
150
|
end
|
@@ -198,10 +198,10 @@ module PacketGen
|
|
198
198
|
|
199
199
|
if opt[:pad_length]
|
200
200
|
self.pad_length = opt[:pad_length]
|
201
|
-
padding = force_binary(opt[:padding] || (1..self.pad_length).to_a.pack(
|
201
|
+
padding = force_binary(opt[:padding] || (1..self.pad_length).to_a.pack('C*'))
|
202
202
|
self[:padding].read padding
|
203
203
|
else
|
204
|
-
padding = force_binary(opt[:padding] || (1..self.pad_length).to_a.pack(
|
204
|
+
padding = force_binary(opt[:padding] || (1..self.pad_length).to_a.pack('C*'))
|
205
205
|
self[:padding].read padding[0...self.pad_length]
|
206
206
|
end
|
207
207
|
|
@@ -209,12 +209,12 @@ module PacketGen
|
|
209
209
|
if opt[:tfc]
|
210
210
|
tfc_size = opt[:tfc_size] - body.sz
|
211
211
|
if tfc_size > 0
|
212
|
-
case confidentiality_mode
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
212
|
+
tfc_size = case confidentiality_mode
|
213
|
+
when 'cbc'
|
214
|
+
(tfc_size / 16) * 16
|
215
|
+
else
|
216
|
+
(tfc_size / 4) * 4
|
217
|
+
end
|
218
218
|
tfc = force_binary("\0" * tfc_size)
|
219
219
|
end
|
220
220
|
end
|
@@ -237,7 +237,7 @@ module PacketGen
|
|
237
237
|
# Remove enciphered headers from packet
|
238
238
|
id = header_id(self)
|
239
239
|
if id < packet.headers.size - 1
|
240
|
-
(packet.headers.size-1).downto(id+1) do |index|
|
240
|
+
(packet.headers.size - 1).downto(id + 1) do |index|
|
241
241
|
packet.headers.delete_at index
|
242
242
|
end
|
243
243
|
end
|
@@ -260,7 +260,7 @@ module PacketGen
|
|
260
260
|
# confidentiality-only cipher. Only HMAC are supported.
|
261
261
|
# @return [Boolean] +true+ if ESP packet is authenticated
|
262
262
|
def decrypt!(cipher, options={})
|
263
|
-
opt = { :
|
263
|
+
opt = { salt: '', parse: true }.merge(options)
|
264
264
|
|
265
265
|
set_crypto cipher, opt[:intmode]
|
266
266
|
|
@@ -279,7 +279,7 @@ module PacketGen
|
|
279
279
|
end
|
280
280
|
cipher.iv = real_iv
|
281
281
|
|
282
|
-
if authenticated?
|
282
|
+
if authenticated? && (@icv_length.zero? || opt[:icv_length])
|
283
283
|
raise ParseError, 'unknown ICV size' unless opt[:icv_length]
|
284
284
|
@icv_length = opt[:icv_length].to_i
|
285
285
|
# reread ESP to handle new ICV size
|
@@ -292,7 +292,7 @@ module PacketGen
|
|
292
292
|
end
|
293
293
|
|
294
294
|
authenticate_esp_header_if_needed options, iv, self[:icv]
|
295
|
-
private_decrypt
|
295
|
+
private_decrypt opt
|
296
296
|
end
|
297
297
|
|
298
298
|
private
|
@@ -329,7 +329,7 @@ module PacketGen
|
|
329
329
|
end
|
330
330
|
end
|
331
331
|
|
332
|
-
def private_decrypt(
|
332
|
+
def private_decrypt(options)
|
333
333
|
# decrypt
|
334
334
|
msg = self.body.to_s
|
335
335
|
msg += self[:padding].to_s + self[:pad_length].to_s + self[:next].to_s
|
@@ -356,8 +356,8 @@ module PacketGen
|
|
356
356
|
pkt = nil
|
357
357
|
case self.next
|
358
358
|
when 4 # IPv4
|
359
|
-
|
360
|
-
|
359
|
+
pkt = Packet.parse(body, first_header: 'IP')
|
360
|
+
encap_length = pkt.ip.length
|
361
361
|
when 41 # IPv6
|
362
362
|
pkt = Packet.parse(body, first_header: 'IPv6')
|
363
363
|
encap_length = pkt.ipv6.length + pkt.ipv6.sz
|
@@ -397,17 +397,17 @@ module PacketGen
|
|
397
397
|
|
398
398
|
self.add_class ESP
|
399
399
|
|
400
|
-
IP.
|
401
|
-
IPv6.
|
402
|
-
UDP.
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
ESP.
|
407
|
-
ESP.
|
408
|
-
ESP.
|
409
|
-
ESP.
|
410
|
-
ESP.
|
411
|
-
ESP.
|
400
|
+
IP.bind ESP, protocol: ESP::IP_PROTOCOL
|
401
|
+
IPv6.bind ESP, next: ESP::IP_PROTOCOL
|
402
|
+
UDP.bind ESP, procs: [->(f) { f.dport = f.sport = ESP::UDP_PORT },
|
403
|
+
->(f) { (f.dport == ESP::UDP_PORT ||
|
404
|
+
f.sport == ESP::UDP_PORT) &&
|
405
|
+
Types::Int32.new.read(f.body[0..3]).to_i > 0 }]
|
406
|
+
ESP.bind IP, next: 4
|
407
|
+
ESP.bind IPv6, next: 41
|
408
|
+
ESP.bind TCP, next: TCP::IP_PROTOCOL
|
409
|
+
ESP.bind UDP, next: TCP::IP_PROTOCOL
|
410
|
+
ESP.bind ICMP, next: ICMP::IP_PROTOCOL
|
411
|
+
ESP.bind ICMPv6, next: ICMPv6::IP_PROTOCOL
|
412
412
|
end
|
413
413
|
end
|
data/lib/packetgen/header/eth.rb
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# An Ethernet header consists of:
|
12
11
|
# * a destination MAC address ({MacAddr}),
|
13
12
|
# * a source MAC address (MacAddr),
|
@@ -31,7 +30,6 @@ module PacketGen
|
|
31
30
|
#
|
32
31
|
# @author Sylvain Daubert
|
33
32
|
class Eth < Base
|
34
|
-
|
35
33
|
# Ethernet MAC address, as a group of 6 bytes
|
36
34
|
# @author Sylvain Daubert
|
37
35
|
class MacAddr < Types::Fields
|
@@ -53,16 +51,14 @@ module PacketGen
|
|
53
51
|
# @!attribute a5
|
54
52
|
# @return [Integer] sixth byte from MacAddr
|
55
53
|
define_field :a5, Types::Int8
|
56
|
-
|
54
|
+
|
57
55
|
# Read a human-readable string to populate +MacAddr+
|
58
56
|
# @param [String] str
|
59
57
|
# @return [self]
|
60
58
|
def from_human(str)
|
61
59
|
return self if str.nil?
|
62
60
|
bytes = str.split(/:/)
|
63
|
-
unless bytes.size == 6
|
64
|
-
raise ArgumentError, 'not a MAC address'
|
65
|
-
end
|
61
|
+
raise ArgumentError, 'not a MAC address' unless bytes.size == 6
|
66
62
|
self[:a0].read(bytes[0].to_i(16))
|
67
63
|
self[:a1].read(bytes[1].to_i(16))
|
68
64
|
self[:a2].read(bytes[2].to_i(16))
|
@@ -75,7 +71,7 @@ module PacketGen
|
|
75
71
|
# +MacAddr+ in human readable form (colon format)
|
76
72
|
# @return [String]
|
77
73
|
def to_human
|
78
|
-
fields.map { |m|
|
74
|
+
fields.map { |m| '%02x' % self[m] }.join(':')
|
79
75
|
end
|
80
76
|
end
|
81
77
|
|
@@ -100,8 +96,15 @@ module PacketGen
|
|
100
96
|
pcap.inject self.to_s
|
101
97
|
pcap.close
|
102
98
|
end
|
103
|
-
end
|
104
99
|
|
100
|
+
# Invert destination and source addresses
|
101
|
+
# @return [self]
|
102
|
+
# @since 2.7.0
|
103
|
+
def reply!
|
104
|
+
self[:src], self[:dst] = self[:dst], self[:src]
|
105
|
+
self
|
106
|
+
end
|
107
|
+
end
|
105
108
|
self.add_class Eth
|
106
109
|
end
|
107
110
|
end
|
data/lib/packetgen/header/gre.rb
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# Generic Routing Encapsulation (RFC 2784 and 2890)
|
12
11
|
# 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
13
12
|
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
@@ -21,8 +20,8 @@ module PacketGen
|
|
21
20
|
# | Sequence Number (Optional) |
|
22
21
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
23
22
|
# @author Sylvain Daubert
|
23
|
+
# @since 2.1.0
|
24
24
|
class GRE < Base
|
25
|
-
|
26
25
|
# IP protocol number for GRE
|
27
26
|
IP_PROTOCOL = 47
|
28
27
|
|
@@ -76,10 +75,10 @@ module PacketGen
|
|
76
75
|
end
|
77
76
|
|
78
77
|
self.add_class GRE
|
79
|
-
IP.
|
80
|
-
IPv6.
|
78
|
+
IP.bind GRE, protocol: GRE::IP_PROTOCOL
|
79
|
+
IPv6.bind GRE, next: GRE::IP_PROTOCOL
|
81
80
|
|
82
|
-
GRE.
|
83
|
-
GRE.
|
81
|
+
GRE.bind IP, protocol_type: IP::ETHERTYPE
|
82
|
+
GRE.bind IPv6, protocol_type: IPv6::ETHERTYPE
|
84
83
|
end
|
85
84
|
end
|
@@ -7,12 +7,16 @@
|
|
7
7
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
|
-
|
11
10
|
# @since 2.2.0
|
12
|
-
module HTTP
|
11
|
+
module HTTP
|
13
12
|
# @abstract Base class for HTTP headers.
|
14
13
|
# @author Kent 'picat' Gruber
|
15
14
|
class Headers
|
15
|
+
# Underlying Headers data (or nil).
|
16
|
+
# @return [Hash, nil]
|
17
|
+
attr_reader :data
|
18
|
+
alias to_h data
|
19
|
+
|
16
20
|
def initialize
|
17
21
|
@data = nil
|
18
22
|
end
|
@@ -23,10 +27,10 @@ module PacketGen
|
|
23
27
|
def read(s_or_h)
|
24
28
|
case s_or_h
|
25
29
|
when String
|
26
|
-
@data = s_or_h.split("\n").map do |h|
|
27
|
-
next unless h.include?(
|
28
|
-
k, v = h.split(
|
29
|
-
[k, v.strip]
|
30
|
+
@data = s_or_h.split("\n").map do |h|
|
31
|
+
next unless h.include?(':')
|
32
|
+
k, v = h.split(':', 2)
|
33
|
+
[k, v.strip]
|
30
34
|
end.reject(&:nil?).to_h
|
31
35
|
when Hash
|
32
36
|
@data = s_or_h
|
@@ -40,7 +44,7 @@ module PacketGen
|
|
40
44
|
return "\r\n" if @data.nil? || @data.empty?
|
41
45
|
d = []
|
42
46
|
@data.map do |k, v|
|
43
|
-
d << k +
|
47
|
+
d << k + ': ' + v
|
44
48
|
end
|
45
49
|
d.join("\r\n") << "\r\n\r\n"
|
46
50
|
end
|
@@ -64,13 +68,6 @@ module PacketGen
|
|
64
68
|
return true unless @data.nil? || @data.empty?
|
65
69
|
false
|
66
70
|
end
|
67
|
-
|
68
|
-
# Shorcut to the underlying Headers data or nil.
|
69
|
-
# @return [Hash, nil]
|
70
|
-
def data
|
71
|
-
@data
|
72
|
-
end
|
73
|
-
alias to_h data
|
74
71
|
end
|
75
72
|
end
|
76
73
|
end
|
@@ -26,28 +26,28 @@ module PacketGen
|
|
26
26
|
# attributes of TCP header are not set.
|
27
27
|
#
|
28
28
|
# == HTTP Request attributes
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
29
|
+
# http_rqst.version = "HTTP/1.1"
|
30
|
+
# http_rqst.method = "GET"
|
31
|
+
# http_rqst.path = "/meow.html"
|
32
32
|
# http_rqst.headers = "Host: tcpdump.org" # string or
|
33
|
-
#
|
33
|
+
# http_rqst.headers = { "Host": "tcpdump.org" } # even a hash
|
34
34
|
#
|
35
35
|
# @author Kent 'picat' Gruber
|
36
36
|
class Request < Base
|
37
37
|
# @!attribute method
|
38
38
|
# @return [Types::String]
|
39
39
|
define_field :method, Types::String
|
40
|
-
# @!attribute path
|
40
|
+
# @!attribute path
|
41
41
|
# @return [Types::String]
|
42
42
|
define_field :path, Types::String
|
43
|
-
# @!attribute version
|
43
|
+
# @!attribute version
|
44
44
|
# @return [Types::String]
|
45
|
-
define_field :version, Types::String, default:
|
45
|
+
define_field :version, Types::String, default: 'HTTP/1.1'
|
46
46
|
# @!attribute headers
|
47
47
|
# associated http/1.1 headers
|
48
48
|
# @return [HTTP::Headers]
|
49
|
-
define_field :headers, HTTP::Headers
|
50
|
-
# @!attribute body
|
49
|
+
define_field :headers, HTTP::Headers
|
50
|
+
# @!attribute body
|
51
51
|
# @return [Types::String]
|
52
52
|
define_field :body, Types::String
|
53
53
|
|
@@ -61,7 +61,7 @@ module PacketGen
|
|
61
61
|
self.headers ||= options[:headers]
|
62
62
|
end
|
63
63
|
|
64
|
-
# Read in the HTTP portion of the packet, and parse it.
|
64
|
+
# Read in the HTTP portion of the packet, and parse it.
|
65
65
|
# @return [PacketGen::HTTP::Request]
|
66
66
|
def read(str)
|
67
67
|
str = str.bytes.map!(&:chr).join unless str.valid_encoding?
|
@@ -73,9 +73,9 @@ module PacketGen
|
|
73
73
|
self[:path] = first_line[1]
|
74
74
|
self[:version] = first_line[2]
|
75
75
|
# requests can sometimes have a payload
|
76
|
-
if data_index = str.find_index(
|
77
|
-
data = str[data_index+1..-1].join("\n")
|
78
|
-
headers = str[0..data_index-1].join("\n")
|
76
|
+
if (data_index = str.find_index(''))
|
77
|
+
data = str[data_index + 1..-1].join("\n")
|
78
|
+
headers = str[0..data_index - 1].join("\n")
|
79
79
|
else
|
80
80
|
headers = str.join("\n")
|
81
81
|
end
|
@@ -87,16 +87,16 @@ module PacketGen
|
|
87
87
|
# String representation of data.
|
88
88
|
# @return [String]
|
89
89
|
def to_s
|
90
|
-
raise FormatError,
|
91
|
-
raise FormatError,
|
92
|
-
raise FormatError,
|
93
|
-
str =
|
94
|
-
str << self[:method] <<
|
90
|
+
raise FormatError, 'Missing #method.' if self.method.empty?
|
91
|
+
raise FormatError, 'Missing #path.' if self.path.empty?
|
92
|
+
raise FormatError, 'Missing #version.' if self.version.empty?
|
93
|
+
str = ''.dup # build 'dat string
|
94
|
+
str << self[:method] << ' ' << self[:path] << ' ' << self[:version] << "\r\n" << self[:headers].to_s << self[:body]
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
self.add_class HTTP::Request
|
100
|
-
TCP.
|
99
|
+
self.add_class HTTP::Request
|
100
|
+
TCP.bind HTTP::Request, body: ->(b) { HTTP::REQUEST_REGEX =~ b.chars.select(&:valid_encoding?).join }
|
101
101
|
end
|
102
102
|
end
|