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
@@ -9,7 +9,6 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
class IKE
|
12
|
-
|
13
12
|
# Transform attribute.
|
14
13
|
# 1 2 3
|
15
14
|
# 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
|
@@ -24,7 +23,6 @@ module PacketGen
|
|
24
23
|
# or a TV format (AF=1).
|
25
24
|
# @author Sylvain Daubert
|
26
25
|
class Attribute < Types::Fields
|
27
|
-
|
28
26
|
TYPE_KEY_LENGTH = 14
|
29
27
|
|
30
28
|
# @!attribute type
|
@@ -82,8 +80,8 @@ module PacketGen
|
|
82
80
|
# Get a human readable string
|
83
81
|
# @return [String]
|
84
82
|
def to_human
|
85
|
-
name = self.class.constants.grep(/TYPE_/)
|
86
|
-
|
83
|
+
name = self.class.constants.grep(/TYPE_/)
|
84
|
+
.detect { |c| self.class.const_get(c) == (type & 0x7fff) } || "attr[#{type & 0x7fff}]"
|
87
85
|
name = name.to_s.sub(/TYPE_/, '')
|
88
86
|
"#{name}=#{value}"
|
89
87
|
end
|
@@ -127,7 +125,6 @@ module PacketGen
|
|
127
125
|
# trans.attributes << { type: 14, value: 128 }
|
128
126
|
# @author Sylvain Daubert
|
129
127
|
class Transform < Types::Fields
|
130
|
-
|
131
128
|
TYPES = {
|
132
129
|
'ENCR' => 1,
|
133
130
|
'PRF' => 2,
|
@@ -281,14 +278,14 @@ module PacketGen
|
|
281
278
|
# @return [String]
|
282
279
|
def to_human
|
283
280
|
h = "#{human_type}(#{human_id}".dup
|
284
|
-
h << ",#{attributes.to_human}"
|
281
|
+
h << ",#{attributes.to_human}" unless attributes.empty?
|
285
282
|
h << ')'
|
286
283
|
end
|
287
284
|
|
288
285
|
# Get human-readable type
|
289
286
|
# @return [String]
|
290
287
|
def human_type
|
291
|
-
if self[:type].enum.
|
288
|
+
if self[:type].enum.value? self.type
|
292
289
|
self[:type].to_human
|
293
290
|
else
|
294
291
|
"type[#{self.type}]"
|
@@ -298,9 +295,9 @@ module PacketGen
|
|
298
295
|
# Get human-readable ID
|
299
296
|
# @return [String]
|
300
297
|
def human_id
|
301
|
-
name = self.class.constants.grep(/#{human_type}_/)
|
302
|
-
|
303
|
-
|
298
|
+
name = self.class.constants.grep(/#{human_type}_/)
|
299
|
+
.detect { |c| self.class.const_get(c) == id } || "ID=#{id}"
|
300
|
+
name.to_s.sub(/#{human_type}_/, '')
|
304
301
|
end
|
305
302
|
|
306
303
|
# Say if this transform is the last one (from {#last} field)
|
@@ -311,8 +308,6 @@ module PacketGen
|
|
311
308
|
true
|
312
309
|
when 3
|
313
310
|
false
|
314
|
-
else
|
315
|
-
nil
|
316
311
|
end
|
317
312
|
end
|
318
313
|
end
|
@@ -360,7 +355,6 @@ module PacketGen
|
|
360
355
|
# proposal.transforms << { type: 'ENCR', id: '3DES' }
|
361
356
|
# @author Sylvain Daubert
|
362
357
|
class SAProposal < Types::Fields
|
363
|
-
|
364
358
|
# @!attribute last
|
365
359
|
# 8-bit last substructure. Specifies whether or not this is the
|
366
360
|
# last Proposal Substructure in the SA. This field has a value of 0
|
@@ -410,7 +404,7 @@ module PacketGen
|
|
410
404
|
define_field :transforms, Transforms, builder: ->(h, t) { t.new(counter: h[:num_trans]) }
|
411
405
|
|
412
406
|
def initialize(options={})
|
413
|
-
if options[:spi]
|
407
|
+
if options[:spi] && options[:spi_size].nil?
|
414
408
|
options[:spi_size] = options[:spi].size
|
415
409
|
end
|
416
410
|
super
|
@@ -423,12 +417,12 @@ module PacketGen
|
|
423
417
|
# @return [Integer]
|
424
418
|
def protocol=(value)
|
425
419
|
proto = case value
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
420
|
+
when Integer
|
421
|
+
value
|
422
|
+
else
|
423
|
+
c = IKE.constants.grep(/PROTO_#{value}/).first
|
424
|
+
c ? IKE.const_get(c) : nil
|
425
|
+
end
|
432
426
|
raise ArgumentError, "unknown protocol #{value.inspect}" unless proto
|
433
427
|
self[:protocol].value = proto
|
434
428
|
end
|
@@ -447,7 +441,7 @@ module PacketGen
|
|
447
441
|
# Compute length and set {#length} field
|
448
442
|
# @return [Integer] new length
|
449
443
|
def calc_length
|
450
|
-
transforms.each
|
444
|
+
transforms.each(&:calc_length)
|
451
445
|
Base.calculate_and_set_length self
|
452
446
|
end
|
453
447
|
|
@@ -457,9 +451,9 @@ module PacketGen
|
|
457
451
|
str = "##{num} #{human_protocol}".dup
|
458
452
|
case spi_size
|
459
453
|
when 4
|
460
|
-
str <<
|
454
|
+
str << '(spi:0x%08x)' % Types::Int32.new.read(spi).to_i
|
461
455
|
when 8
|
462
|
-
str <<
|
456
|
+
str << '(spi:0x%016x)' % Types::Int64.new.read(spi).to_i
|
463
457
|
end
|
464
458
|
str << ":#{transforms.to_human}"
|
465
459
|
end
|
@@ -467,8 +461,8 @@ module PacketGen
|
|
467
461
|
# Get protocol name
|
468
462
|
# @return [String]
|
469
463
|
def human_protocol
|
470
|
-
name = IKE.constants.grep(/PROTO/)
|
471
|
-
|
464
|
+
name = IKE.constants.grep(/PROTO/)
|
465
|
+
.detect { |c| IKE.const_get(c) == protocol } || "proto #{protocol}"
|
472
466
|
name.to_s.sub(/PROTO_/, '')
|
473
467
|
end
|
474
468
|
|
@@ -481,8 +475,6 @@ module PacketGen
|
|
481
475
|
true
|
482
476
|
when 2
|
483
477
|
false
|
484
|
-
else
|
485
|
-
nil
|
486
478
|
end
|
487
479
|
end
|
488
480
|
end
|
@@ -533,7 +525,6 @@ module PacketGen
|
|
533
525
|
# pkt.calc_length
|
534
526
|
# @author Sylvain Daubert
|
535
527
|
class SA < Payload
|
536
|
-
|
537
528
|
# Payload type number
|
538
529
|
PAYLOAD_TYPE = 33
|
539
530
|
|
@@ -553,14 +544,14 @@ module PacketGen
|
|
553
544
|
hlen = self.class.new.sz
|
554
545
|
plen = length - hlen
|
555
546
|
proposals.read str[hlen, plen]
|
556
|
-
body.read str[hlen+plen..-1]
|
547
|
+
body.read str[hlen + plen..-1]
|
557
548
|
self
|
558
549
|
end
|
559
550
|
|
560
551
|
# Compute length and set {#length} field
|
561
552
|
# @return [Integer] new length
|
562
553
|
def calc_length
|
563
|
-
proposals.each
|
554
|
+
proposals.each(&:calc_length)
|
564
555
|
super
|
565
556
|
end
|
566
557
|
end
|
@@ -9,7 +9,6 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
class IKE
|
12
|
-
|
13
12
|
# This class handles encrypted payloads, denoted SK.
|
14
13
|
#
|
15
14
|
# The encrypted payload contains other payloads in encrypted form.
|
@@ -114,15 +113,15 @@ module PacketGen
|
|
114
113
|
cipher.iv = real_iv
|
115
114
|
|
116
115
|
if authenticated?
|
117
|
-
if @icv_length
|
116
|
+
if @icv_length.zero?
|
118
117
|
@icv_length = opt[:icv_length].to_i if opt[:icv_length]
|
119
|
-
raise ParseError, 'unknown ICV size' if @icv_length
|
118
|
+
raise ParseError, 'unknown ICV size' if @icv_length.zero?
|
120
119
|
end
|
121
120
|
icv = self.content.slice!(-@icv_length, @icv_length)
|
122
121
|
end
|
123
122
|
|
124
|
-
authenticate_if_needed
|
125
|
-
private_decrypt
|
123
|
+
authenticate_if_needed iv, icv
|
124
|
+
private_decrypt opt
|
126
125
|
end
|
127
126
|
|
128
127
|
# Encrypt in-place SK payload.
|
@@ -151,14 +150,14 @@ module PacketGen
|
|
151
150
|
real_iv += [1].pack('N') if confidentiality_mode == 'ctr'
|
152
151
|
cipher.iv = real_iv
|
153
152
|
|
154
|
-
authenticate_if_needed
|
153
|
+
authenticate_if_needed iv
|
155
154
|
|
156
155
|
if opt[:pad_length]
|
157
156
|
pad_length = opt[:pad_length]
|
158
157
|
padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
|
159
158
|
else
|
160
159
|
pad_length = cipher.block_size
|
161
|
-
pad_length = 16 if cipher.block_size == 1
|
160
|
+
pad_length = 16 if cipher.block_size == 1 # Some AES mode returns 1...
|
162
161
|
pad_length -= (self.body.sz + iv.size + 1) % cipher.block_size
|
163
162
|
pad_length = 0 if pad_length == 16
|
164
163
|
padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
|
@@ -170,13 +169,13 @@ module PacketGen
|
|
170
169
|
|
171
170
|
if authenticated?
|
172
171
|
@icv_length = opt[:icv_length] if opt[:icv_length]
|
173
|
-
if @conf.authenticated?
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
172
|
+
encrypted_msg << if @conf.authenticated?
|
173
|
+
@conf.auth_tag[0, @icv_length]
|
174
|
+
else
|
175
|
+
@intg.digest[0, @icv_length]
|
176
|
+
end
|
178
177
|
end
|
179
|
-
self[:content].read
|
178
|
+
self[:content].read(iv + encrypted_msg)
|
180
179
|
|
181
180
|
# Remove plain payloads
|
182
181
|
self[:body] = Types::String.new
|
@@ -184,7 +183,7 @@ module PacketGen
|
|
184
183
|
# Remove enciphered payloads from packet
|
185
184
|
id = header_id(self)
|
186
185
|
if id < packet.headers.size - 1
|
187
|
-
(packet.headers.size-1).downto(id+1) do |index|
|
186
|
+
(packet.headers.size - 1).downto(id + 1) do |index|
|
188
187
|
packet.headers.delete_at index
|
189
188
|
end
|
190
189
|
end
|
@@ -195,7 +194,7 @@ module PacketGen
|
|
195
194
|
|
196
195
|
private
|
197
196
|
|
198
|
-
def authenticate_if_needed(
|
197
|
+
def authenticate_if_needed(iv, icv=nil)
|
199
198
|
if @conf.authenticated?
|
200
199
|
@conf.auth_tag = icv if icv
|
201
200
|
@conf.auth_data = get_ad
|
@@ -216,14 +215,14 @@ module PacketGen
|
|
216
215
|
def get_ad
|
217
216
|
str = packet.ike.to_s[0, IKE.new.sz]
|
218
217
|
current_payload = packet.ike.body
|
219
|
-
until current_payload.is_a? SK
|
218
|
+
until current_payload.is_a? SK
|
220
219
|
str << current_payload.to_s[0, current_payload.length]
|
221
220
|
current_payload = current_payload.body
|
222
221
|
end
|
223
222
|
str << self.to_s[0, SK.new.sz]
|
224
223
|
end
|
225
224
|
|
226
|
-
def private_decrypt(
|
225
|
+
def private_decrypt(options)
|
227
226
|
# decrypt
|
228
227
|
plain_msg = decipher(content.to_s)
|
229
228
|
# Remove cipher text
|
@@ -9,7 +9,6 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
class IKE
|
12
|
-
|
13
12
|
# TrafficSelector substructure, as defined in RFC 7296, §3.13.1:
|
14
13
|
# 1 2 3
|
15
14
|
# 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
|
@@ -52,7 +51,7 @@ module PacketGen
|
|
52
51
|
# @!attribute end_port
|
53
52
|
# 16-bit End port
|
54
53
|
# @return [Integer]
|
55
|
-
define_field :end_port, Types::Int16, default:
|
54
|
+
define_field :end_port, Types::Int16, default: 65_535
|
56
55
|
# @!attribute start_addr
|
57
56
|
# starting address
|
58
57
|
# @return [IP::Addr, IPv6::Addr]
|
@@ -74,10 +73,10 @@ module PacketGen
|
|
74
73
|
self[:length].value = sz unless options[:length]
|
75
74
|
self.type = options[:type] if options[:type]
|
76
75
|
self.protocol = options[:protocol] if options[:protocol]
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
76
|
+
|
77
|
+
return unless options[:ports]
|
78
|
+
self.start_port = options[:ports].begin
|
79
|
+
self.end_port = options[:ports].end
|
81
80
|
end
|
82
81
|
|
83
82
|
# Populate object from a string
|
@@ -94,12 +93,12 @@ module PacketGen
|
|
94
93
|
# @return [Integer]
|
95
94
|
def type=(value)
|
96
95
|
type = case value
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
96
|
+
when Integer
|
97
|
+
value
|
98
|
+
else
|
99
|
+
c = self.class.constants.grep(/TS_#{value.upcase}/).first
|
100
|
+
c ? self.class.const_get(c) : nil
|
101
|
+
end
|
103
102
|
raise ArgumentError, "unknown type #{value.inspect}" unless type
|
104
103
|
select_addr_from_type type
|
105
104
|
self[:type].value = type
|
@@ -110,11 +109,11 @@ module PacketGen
|
|
110
109
|
# @return [Integer]
|
111
110
|
def protocol=(value)
|
112
111
|
protocol = case value
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
112
|
+
when Integer
|
113
|
+
value
|
114
|
+
else
|
115
|
+
Proto.getprotobyname(value)
|
116
|
+
end
|
118
117
|
raise ArgumentError, "unknown protocol #{value.inspect}" unless protocol
|
119
118
|
self[:protocol].value = protocol
|
120
119
|
end
|
@@ -125,7 +124,7 @@ module PacketGen
|
|
125
124
|
h = start_addr << '-' << end_addr
|
126
125
|
unless human_protocol.empty?
|
127
126
|
h << "/#{human_protocol}"
|
128
|
-
h << "[#{start_port}-#{end_port}]" if (start_port..end_port) != (0..
|
127
|
+
h << "[#{start_port}-#{end_port}]" if (start_port..end_port) != (0..65_535)
|
129
128
|
end
|
130
129
|
h
|
131
130
|
end
|
@@ -134,10 +133,10 @@ module PacketGen
|
|
134
133
|
# is returned.
|
135
134
|
# @return [String]
|
136
135
|
def human_protocol
|
137
|
-
if protocol
|
136
|
+
if protocol.zero?
|
138
137
|
''
|
139
138
|
else
|
140
|
-
Proto.getprotobynumber(protocol) ||
|
139
|
+
Proto.getprotobynumber(protocol) || protocol.to_s
|
141
140
|
end
|
142
141
|
end
|
143
142
|
|
@@ -218,7 +217,6 @@ module PacketGen
|
|
218
217
|
# pkt.ike_tsi.traffic_selectors << { start_addr: '2001::1', end_addr: '200a:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
|
219
218
|
# @author Sylvain Daubert
|
220
219
|
class TSi < Payload
|
221
|
-
|
222
220
|
# Payload type number
|
223
221
|
PAYLOAD_TYPE = 44
|
224
222
|
|
@@ -239,7 +237,7 @@ module PacketGen
|
|
239
237
|
# @return {TrafficSelectors}
|
240
238
|
define_field_before :body, :traffic_selectors, TrafficSelectors,
|
241
239
|
builder: ->(h, t) { t.new(counter: h[:num_ts]) }
|
242
|
-
alias
|
240
|
+
alias selectors traffic_selectors
|
243
241
|
|
244
242
|
# Populate object from a string
|
245
243
|
# @param [String] str
|
@@ -249,14 +247,14 @@ module PacketGen
|
|
249
247
|
hlen = self.class.new.sz
|
250
248
|
tslen = length - hlen
|
251
249
|
selectors.read str[hlen, tslen]
|
252
|
-
body.read str[hlen+tslen..-1]
|
250
|
+
body.read str[hlen + tslen..-1]
|
253
251
|
self
|
254
252
|
end
|
255
253
|
|
256
254
|
# Compute length and set {#length} field
|
257
255
|
# @return [Integer] new length
|
258
256
|
def calc_length
|
259
|
-
selectors.each
|
257
|
+
selectors.each(&:calc_length)
|
260
258
|
super
|
261
259
|
end
|
262
260
|
end
|
@@ -9,7 +9,6 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
class IKE
|
12
|
-
|
13
12
|
# This class handles Vendor ID payloads, as defined in RFC 7296 §3.12.
|
14
13
|
#
|
15
14
|
# A Vendor ID payload contains a generic payload header (see {Payload})
|
@@ -30,7 +29,6 @@ module PacketGen
|
|
30
29
|
# pkt.add('IKE::VendorID', data: "abcdefgh")
|
31
30
|
# @author Sylvain Daubert
|
32
31
|
class VendorID < Payload
|
33
|
-
|
34
32
|
# Payload type number
|
35
33
|
PAYLOAD_TYPE = 43
|
36
34
|
end
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -4,11 +4,11 @@
|
|
4
4
|
# This program is published under MIT license.
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
7
|
+
|
7
8
|
require 'socket'
|
8
9
|
|
9
10
|
module PacketGen
|
10
11
|
module Header
|
11
|
-
|
12
12
|
# A IP header consists of:
|
13
13
|
# * a first byte ({#u8} of {Types::Int8} type) composed of:
|
14
14
|
# * a 4-bit {#version} field,
|
@@ -62,14 +62,13 @@ module PacketGen
|
|
62
62
|
# ip.dst = '127.0.0.2'
|
63
63
|
# ip.body.read 'this is a body'
|
64
64
|
# @author Sylvain Daubert
|
65
|
-
class IP < Base;end
|
65
|
+
class IP < Base; end
|
66
66
|
|
67
|
-
require_relative 'ip/addr'
|
68
|
-
require_relative 'ip/option'
|
69
|
-
require_relative 'ip/options'
|
67
|
+
require_relative 'ip/addr'
|
68
|
+
require_relative 'ip/option'
|
69
|
+
require_relative 'ip/options'
|
70
70
|
|
71
71
|
class IP
|
72
|
-
|
73
72
|
# IP Ether type
|
74
73
|
ETHERTYPE = 0x0800
|
75
74
|
|
@@ -85,7 +84,7 @@ require_relative 'ip/options'
|
|
85
84
|
define_field :length, Types::Int16, default: 20
|
86
85
|
# @!attribute id
|
87
86
|
# @return [Integer] 16-bit ID
|
88
|
-
define_field :id, Types::Int16, default: -> { rand(
|
87
|
+
define_field :id, Types::Int16, default: -> { rand(65_535) }
|
89
88
|
# @!attribute frag
|
90
89
|
# @return [Integer] 16-bit frag word
|
91
90
|
define_field :frag, Types::Int16, default: 0
|
@@ -111,7 +110,7 @@ require_relative 'ip/options'
|
|
111
110
|
# @!attribute body
|
112
111
|
# @return [Types::String,Header::Base]
|
113
112
|
define_field :body, Types::String
|
114
|
-
|
113
|
+
|
115
114
|
# @!attribute version
|
116
115
|
# @return [Integer] 4-bit version attribute
|
117
116
|
# @!attribute ihl
|
@@ -121,7 +120,7 @@ require_relative 'ip/options'
|
|
121
120
|
# @!attribute flag_rsv
|
122
121
|
# @return [Boolean] reserved bit from flags
|
123
122
|
# @!attribute flag_df
|
124
|
-
# @return [Boolean] Don't Fragment flag
|
123
|
+
# @return [Boolean] Don't Fragment flag
|
125
124
|
# @!attribute flag_mf
|
126
125
|
# @return [Boolean] More Fragment flags
|
127
126
|
# @!attribute fragment_offset
|
@@ -133,7 +132,7 @@ require_relative 'ip/options'
|
|
133
132
|
# @param [#to_s] hdr header or other object on which calculates a sum
|
134
133
|
# of 16-bit words.
|
135
134
|
# @return [Integer]
|
136
|
-
def
|
135
|
+
def self.sum16(hdr)
|
137
136
|
old_checksum = nil
|
138
137
|
if hdr.respond_to? :checksum=
|
139
138
|
old_checksum = hdr.checksum
|
@@ -141,11 +140,11 @@ require_relative 'ip/options'
|
|
141
140
|
end
|
142
141
|
|
143
142
|
data = hdr.to_s
|
144
|
-
data << "\x00" if data.size
|
143
|
+
data << "\x00" if data.size.odd?
|
145
144
|
sum = data.unpack('n*').reduce(:+)
|
146
145
|
|
147
146
|
hdr.checksum = old_checksum if old_checksum
|
148
|
-
|
147
|
+
|
149
148
|
sum
|
150
149
|
end
|
151
150
|
|
@@ -157,12 +156,12 @@ require_relative 'ip/options'
|
|
157
156
|
# * forces self[attr] to 0xffff if computed self[attr] is 0.
|
158
157
|
# @param [Integer] checksum checksum to reduce
|
159
158
|
# @return [Integer] reduced checksum
|
160
|
-
def
|
161
|
-
while checksum > 0xffff
|
159
|
+
def self.reduce_checksum(checksum)
|
160
|
+
while checksum > 0xffff
|
162
161
|
checksum = (checksum & 0xffff) + (checksum >> 16)
|
163
162
|
end
|
164
163
|
checksum = ~checksum & 0xffff
|
165
|
-
|
164
|
+
checksum.zero? ? 0xffff : checksum
|
166
165
|
end
|
167
166
|
|
168
167
|
# Populate object from a binary string
|
@@ -186,7 +185,7 @@ require_relative 'ip/options'
|
|
186
185
|
opt_size = (self.ihl - 5) * 4
|
187
186
|
self[:options].read str[20, opt_size]
|
188
187
|
end
|
189
|
-
self[:body].read str[20+opt_size..-1]
|
188
|
+
self[:body].read str[20 + opt_size..-1]
|
190
189
|
self
|
191
190
|
end
|
192
191
|
|
@@ -227,7 +226,7 @@ require_relative 'ip/options'
|
|
227
226
|
# kernel, so bad IP packets cannot be sent this way. To do so, use {Eth#to_w}.
|
228
227
|
# @param [String,nil] iface interface name. Not used
|
229
228
|
# @return [void]
|
230
|
-
def to_w(
|
229
|
+
def to_w(_iface=nil)
|
231
230
|
sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
|
232
231
|
sockaddrin = Socket.sockaddr_in(0, dst)
|
233
232
|
sock.send to_s, 0, sockaddrin
|
@@ -245,7 +244,7 @@ require_relative 'ip/options'
|
|
245
244
|
str << shift + Inspect::FMT_ATTR % ['', 'version', version]
|
246
245
|
str << shift + Inspect::FMT_ATTR % ['', 'ihl', ihl]
|
247
246
|
elsif attr == :frag
|
248
|
-
flags = flag_rsv? ? %w
|
247
|
+
flags = flag_rsv? ? %w[RSV] : []
|
249
248
|
flags << 'DF' if flag_df?
|
250
249
|
flags << 'MF' if flag_mf?
|
251
250
|
flags_str = flags.empty? ? 'none' : flags.join(',')
|
@@ -260,7 +259,7 @@ require_relative 'ip/options'
|
|
260
259
|
# Check version field
|
261
260
|
# @see [Base#parse?]
|
262
261
|
def parse?
|
263
|
-
version == 4
|
262
|
+
(version == 4) && (ihl >= 5)
|
264
263
|
end
|
265
264
|
|
266
265
|
# Get binary string. Fixup IHL if needed (IP header has options, and IHL
|
@@ -269,13 +268,21 @@ require_relative 'ip/options'
|
|
269
268
|
self.ihl = 5 + options.sz / 4 if self.ihl == 5
|
270
269
|
super
|
271
270
|
end
|
271
|
+
|
272
|
+
# Invert source and destination addresses
|
273
|
+
# @return [self]
|
274
|
+
# @since 2.7.0
|
275
|
+
def reply!
|
276
|
+
self[:src], self[:dst] = self[:dst], self[:src]
|
277
|
+
self
|
278
|
+
end
|
272
279
|
end
|
273
280
|
|
274
281
|
self.add_class IP
|
275
282
|
|
276
|
-
Eth.
|
277
|
-
SNAP.
|
278
|
-
Dot1q.
|
279
|
-
IP.
|
283
|
+
Eth.bind IP, ethertype: IP::ETHERTYPE
|
284
|
+
SNAP.bind IP, proto_id: IP::ETHERTYPE
|
285
|
+
Dot1q.bind IP, ethertype: IP::ETHERTYPE
|
286
|
+
IP.bind IP, protocol: 4
|
280
287
|
end
|
281
288
|
end
|