packetgen 2.8.7 → 3.0.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/.rubocop.yml +0 -1
- data/README.md +5 -4
- data/lib/packetgen.rb +6 -12
- data/lib/packetgen/capture.rb +43 -39
- data/lib/packetgen/config.rb +0 -1
- data/lib/packetgen/deprecation.rb +1 -1
- data/lib/packetgen/header.rb +9 -9
- data/lib/packetgen/header/asn1_base.rb +10 -10
- data/lib/packetgen/header/base.rb +42 -101
- data/lib/packetgen/header/dhcp/option.rb +5 -11
- data/lib/packetgen/header/dhcpv6/duid.rb +2 -0
- data/lib/packetgen/header/dhcpv6/option.rb +2 -19
- data/lib/packetgen/header/dhcpv6/options.rb +7 -0
- data/lib/packetgen/header/dns.rb +5 -23
- data/lib/packetgen/header/dns/name.rb +1 -0
- data/lib/packetgen/header/dns/qdsection.rb +1 -0
- data/lib/packetgen/header/dns/question.rb +3 -7
- data/lib/packetgen/header/dns/rr.rb +3 -0
- data/lib/packetgen/header/dns/rrsection.rb +1 -0
- data/lib/packetgen/header/dot11.rb +1 -17
- data/lib/packetgen/header/dot1x.rb +1 -0
- data/lib/packetgen/header/eap.rb +4 -7
- data/lib/packetgen/header/eth.rb +2 -0
- data/lib/packetgen/header/http/headers.rb +3 -0
- data/lib/packetgen/header/http/request.rb +5 -4
- data/lib/packetgen/header/http/response.rb +5 -4
- data/lib/packetgen/header/icmp.rb +6 -0
- data/lib/packetgen/header/icmpv6.rb +6 -0
- data/lib/packetgen/header/igmpv3/mq.rb +2 -0
- data/lib/packetgen/header/ip.rb +32 -30
- data/lib/packetgen/header/ip/addr.rb +1 -0
- data/lib/packetgen/header/ip/option.rb +23 -20
- data/lib/packetgen/header/ip/options.rb +11 -24
- data/lib/packetgen/header/ipv6.rb +45 -34
- data/lib/packetgen/header/ipv6/addr.rb +2 -0
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +7 -31
- data/lib/packetgen/header/mdns.rb +1 -0
- data/lib/packetgen/header/mldv2/mlq.rb +2 -0
- data/lib/packetgen/header/ospfv2/lsa.rb +15 -25
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -1
- data/lib/packetgen/header/ospfv3/lsa.rb +8 -25
- data/lib/packetgen/header/snmp.rb +2 -0
- data/lib/packetgen/header/tcp.rb +23 -2
- data/lib/packetgen/header/tcp/option.rb +51 -52
- data/lib/packetgen/header/tcp/options.rb +17 -52
- data/lib/packetgen/header/tftp.rb +3 -0
- data/lib/packetgen/header/udp.rb +8 -0
- data/lib/packetgen/packet.rb +119 -102
- data/lib/packetgen/pcapng/block.rb +4 -10
- data/lib/packetgen/pcapng/epb.rb +4 -4
- data/lib/packetgen/pcapng/file.rb +7 -3
- data/lib/packetgen/pcapng/idb.rb +2 -2
- data/lib/packetgen/pcapng/shb.rb +3 -3
- data/lib/packetgen/pcapng/spb.rb +1 -8
- data/lib/packetgen/pcapng/unknown_block.rb +0 -7
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/array.rb +73 -71
- data/lib/packetgen/types/cstring.rb +1 -1
- data/lib/packetgen/types/enum.rb +3 -3
- data/lib/packetgen/types/fields.rb +66 -106
- data/lib/packetgen/types/int.rb +9 -5
- data/lib/packetgen/types/length_from.rb +45 -0
- data/lib/packetgen/types/oui.rb +2 -0
- data/lib/packetgen/types/string.rb +10 -16
- data/lib/packetgen/types/tlv.rb +7 -15
- data/lib/packetgen/utils.rb +8 -8
- data/lib/packetgen/utils/arp_spoofer.rb +1 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +3 -21
- data/lib/packetgen/header/crypto.rb +0 -62
- data/lib/packetgen/header/esp.rb +0 -413
- data/lib/packetgen/header/ike.rb +0 -243
- data/lib/packetgen/header/ike/auth.rb +0 -165
- data/lib/packetgen/header/ike/cert.rb +0 -76
- data/lib/packetgen/header/ike/certreq.rb +0 -66
- data/lib/packetgen/header/ike/id.rb +0 -99
- data/lib/packetgen/header/ike/ke.rb +0 -79
- data/lib/packetgen/header/ike/nonce.rb +0 -40
- data/lib/packetgen/header/ike/notify.rb +0 -176
- data/lib/packetgen/header/ike/payload.rb +0 -315
- data/lib/packetgen/header/ike/sa.rb +0 -561
- data/lib/packetgen/header/ike/sk.rb +0 -261
- data/lib/packetgen/header/ike/ts.rb +0 -270
- data/lib/packetgen/header/ike/vendor_id.rb +0 -39
- data/lib/packetgen/header/netbios.rb +0 -20
- data/lib/packetgen/header/netbios/datagram.rb +0 -105
- data/lib/packetgen/header/netbios/name.rb +0 -67
- data/lib/packetgen/header/netbios/session.rb +0 -64
@@ -74,6 +74,8 @@ module PacketGen
|
|
74
74
|
# @return [Integer]
|
75
75
|
define_bit_fields_on :u8, :resv, 4, :flag_s, :qrv, 3
|
76
76
|
|
77
|
+
undef qqic, qqic=
|
78
|
+
|
77
79
|
# Get QQIC value
|
78
80
|
# @note May return a different value from value previously set, as a
|
79
81
|
# float encoding is used to encode big values. See {IGMPv3.decode}.
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -9,6 +9,22 @@ require 'socket'
|
|
9
9
|
|
10
10
|
module PacketGen
|
11
11
|
module Header
|
12
|
+
# IP protocol ({https://tools.ietf.org/html/rfc791 RFC 791})
|
13
|
+
# 0 1 2 3
|
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
|
15
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
16
|
+
# |Version| IHL |Type of Service| Total Length |
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# | Identification |Flags| Fragment Offset |
|
19
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
+
# | Time to Live | Protocol | Header Checksum |
|
21
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
22
|
+
# | Source Address |
|
23
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
24
|
+
# | Destination Address |
|
25
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
# | Options | Padding |
|
27
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
12
28
|
# A IP header consists of:
|
13
29
|
# * a first byte ({#u8} of {Types::Int8} type) composed of:
|
14
30
|
# * a 4-bit {#version} field,
|
@@ -24,7 +40,7 @@ module PacketGen
|
|
24
40
|
# * a {#checksum} field (+Int16+),
|
25
41
|
# * a source IP address ({#src}, {Addr} type),
|
26
42
|
# * a destination IP address ({#dst}, +Addr+ type),
|
27
|
-
# * an optional {#options} field ({
|
43
|
+
# * an optional {#options} field ({Options} type),
|
28
44
|
# * and a {#body} ({Types::String} type).
|
29
45
|
#
|
30
46
|
# == Create a IP header
|
@@ -61,6 +77,14 @@ module PacketGen
|
|
61
77
|
# ip[:src] # => PacketGen::Header::IP::Addr
|
62
78
|
# ip.dst = '127.0.0.2'
|
63
79
|
# ip.body.read 'this is a body'
|
80
|
+
#
|
81
|
+
# == Add IP options
|
82
|
+
# IP has an {#options} attribute used to store datagram options.
|
83
|
+
# pkt = PacketGen.gen('IP')
|
84
|
+
# # add option from class
|
85
|
+
# pkt.ip.options << PacketGen::Header::IP::RA.new
|
86
|
+
# # or use a hash
|
87
|
+
# pkt.ip.options << { type: 'RR', data: ['192.168.16.4']}
|
64
88
|
# @author Sylvain Daubert
|
65
89
|
class IP < Base; end
|
66
90
|
|
@@ -84,7 +108,7 @@ module PacketGen
|
|
84
108
|
define_field :length, Types::Int16, default: 20
|
85
109
|
# @!attribute id
|
86
110
|
# @return [Integer] 16-bit ID
|
87
|
-
define_field :id, Types::Int16, default: ->(
|
111
|
+
define_field :id, Types::Int16, default: ->(_) { rand(65_535) }
|
88
112
|
# @!attribute frag
|
89
113
|
# @return [Integer] 16-bit frag word
|
90
114
|
define_field :frag, Types::Int16, default: 0
|
@@ -106,7 +130,8 @@ module PacketGen
|
|
106
130
|
# @!attribute options
|
107
131
|
# @since 2.2.0
|
108
132
|
# @return [Types::String]
|
109
|
-
define_field :options, Options, optional: ->(h) { h.ihl > 5 }
|
133
|
+
define_field :options, Options, optional: ->(h) { h.ihl > 5 },
|
134
|
+
builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }
|
110
135
|
# @!attribute body
|
111
136
|
# @return [Types::String,Header::Base]
|
112
137
|
define_field :body, Types::String
|
@@ -164,31 +189,6 @@ module PacketGen
|
|
164
189
|
checksum.zero? ? 0xffff : checksum
|
165
190
|
end
|
166
191
|
|
167
|
-
# Populate object from a binary string
|
168
|
-
# @param [String] str
|
169
|
-
# @return [Fields] self
|
170
|
-
def read(str)
|
171
|
-
return self if str.nil?
|
172
|
-
force_binary str
|
173
|
-
self[:u8].read str[0, 1]
|
174
|
-
self[:tos].read str[1, 1]
|
175
|
-
self[:length].read str[2, 2]
|
176
|
-
self[:id].read str[4, 2]
|
177
|
-
self[:frag].read str[6, 2]
|
178
|
-
self[:ttl].read str[8, 1]
|
179
|
-
self[:protocol].read str[9, 1]
|
180
|
-
self[:checksum].read str[10, 2]
|
181
|
-
self[:src].read str[12, 4]
|
182
|
-
self[:dst].read str[16, 4]
|
183
|
-
opt_size = 0
|
184
|
-
if self.ihl > 5
|
185
|
-
opt_size = (self.ihl - 5) * 4
|
186
|
-
self[:options].read str[20, opt_size]
|
187
|
-
end
|
188
|
-
self[:body].read str[20 + opt_size..-1]
|
189
|
-
self
|
190
|
-
end
|
191
|
-
|
192
192
|
# Compute checksum and set +checksum+ field
|
193
193
|
# @return [Integer]
|
194
194
|
def calc_checksum
|
@@ -207,10 +207,12 @@ module PacketGen
|
|
207
207
|
self[:checksum].value = IP.reduce_checksum(checksum)
|
208
208
|
end
|
209
209
|
|
210
|
-
# Compute
|
210
|
+
# Compute and set +length+ and +ihl+ field
|
211
211
|
# @return [Integer]
|
212
|
+
# @since 3.0.0 add +ihl+ calculation
|
212
213
|
def calc_length
|
213
214
|
Base.calculate_and_set_length self
|
215
|
+
self.ihl = 5 + self[:options].sz / 4
|
214
216
|
end
|
215
217
|
|
216
218
|
# Get IP part of pseudo header checksum.
|
@@ -265,7 +267,7 @@ module PacketGen
|
|
265
267
|
# Get binary string. Fixup IHL if needed (IP header has options, and IHL
|
266
268
|
# was not set by user).
|
267
269
|
def to_s
|
268
|
-
self.ihl = 5 + options.sz / 4 if self.ihl == 5
|
270
|
+
self.ihl = 5 + self[:options].sz / 4 if self.ihl == 5
|
269
271
|
super
|
270
272
|
end
|
271
273
|
|
@@ -70,15 +70,32 @@ module PacketGen
|
|
70
70
|
# @return [Hash]
|
71
71
|
def self.types
|
72
72
|
return @types if defined? @types
|
73
|
+
|
73
74
|
@types = {}
|
74
75
|
Option.constants.each do |cst|
|
75
76
|
next unless cst.to_s.end_with? '_TYPE'
|
77
|
+
|
76
78
|
optname = cst.to_s.sub(/_TYPE/, '')
|
77
|
-
@types[
|
79
|
+
@types[optname] = Option.const_get(cst)
|
78
80
|
end
|
79
81
|
@types
|
80
82
|
end
|
81
83
|
|
84
|
+
# Factory to build an option from its type
|
85
|
+
# @return [Option]
|
86
|
+
def Option.build(options={})
|
87
|
+
type = options.delete(:type)
|
88
|
+
klass = case type
|
89
|
+
when String
|
90
|
+
types.key?(type) ? IP.const_get(type) : self
|
91
|
+
when Integer
|
92
|
+
types.value?(type) ? IP.const_get(types.key(type)) : self
|
93
|
+
else
|
94
|
+
self
|
95
|
+
end
|
96
|
+
klass.new(options)
|
97
|
+
end
|
98
|
+
|
82
99
|
def initialize(options={})
|
83
100
|
unless options[:type]
|
84
101
|
opt_name = self.class.to_s.gsub(/.*::/, '')
|
@@ -87,6 +104,7 @@ module PacketGen
|
|
87
104
|
end
|
88
105
|
end
|
89
106
|
super
|
107
|
+
self.length = sz if respond_to?(:length) && options[:length].nil?
|
90
108
|
end
|
91
109
|
|
92
110
|
# Get binary string. Set {#length} field.
|
@@ -99,7 +117,7 @@ module PacketGen
|
|
99
117
|
# Get a human readable string
|
100
118
|
# @return [String]
|
101
119
|
def to_human
|
102
|
-
str = self.class == Option ? "unk-#{type}" : self.class.to_s.sub(/.*::/, '')
|
120
|
+
str = self.class == Option ? +"unk-#{type}" : self.class.to_s.sub(/.*::/, '')
|
103
121
|
if respond_to?(:length) && (length > 2) && !self[:data].to_s.empty?
|
104
122
|
str << ":#{self[:data].to_s.inspect}"
|
105
123
|
end
|
@@ -114,8 +132,7 @@ module PacketGen
|
|
114
132
|
end
|
115
133
|
|
116
134
|
# No OPeration IP option
|
117
|
-
class NOP < EOL
|
118
|
-
end
|
135
|
+
class NOP < EOL; end
|
119
136
|
|
120
137
|
# Loose Source and Record Route IP option
|
121
138
|
class LSRR < Option
|
@@ -124,25 +141,11 @@ module PacketGen
|
|
124
141
|
# @!attribute pointer
|
125
142
|
# 8-bit pointer on next address
|
126
143
|
# @return [Integer]
|
127
|
-
define_field :pointer, Types::Int8
|
144
|
+
define_field :pointer, Types::Int8, default: 4
|
128
145
|
# @!attribute data
|
129
146
|
# Array of IP addresses
|
130
147
|
# @return [Types::Array<IP::Addr>]
|
131
|
-
define_field :data, ArrayOfAddr,
|
132
|
-
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
133
|
-
|
134
|
-
# Populate object from a binary string
|
135
|
-
# @param [String] str
|
136
|
-
# @return [Fields] self
|
137
|
-
def read(str)
|
138
|
-
return self if str.nil?
|
139
|
-
force_binary str
|
140
|
-
self[:type].read str[0, 1]
|
141
|
-
self[:length].read str[1, 1]
|
142
|
-
self[:pointer].read str[2, 1]
|
143
|
-
self[:data].read str[3, length - 3]
|
144
|
-
self
|
145
|
-
end
|
148
|
+
define_field :data, ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - 3 }) }
|
146
149
|
|
147
150
|
# Get IP address pointer by {#pointer}
|
148
151
|
# @return [Addr]
|
@@ -15,30 +15,6 @@ module PacketGen
|
|
15
15
|
|
16
16
|
HUMAN_SEPARATOR = ';'
|
17
17
|
|
18
|
-
# Read IP header options from a string
|
19
|
-
# @param [String] str binary string
|
20
|
-
# @return [self]
|
21
|
-
def read(str)
|
22
|
-
clear
|
23
|
-
return self if str.nil?
|
24
|
-
PacketGen.force_binary str
|
25
|
-
|
26
|
-
i = 0
|
27
|
-
types = Option.types
|
28
|
-
while i < str.to_s.length
|
29
|
-
type = str[i, 1].unpack('C').first
|
30
|
-
this_option = if types[type].nil?
|
31
|
-
Option.new
|
32
|
-
else
|
33
|
-
types[type].new
|
34
|
-
end
|
35
|
-
this_option.read str[i, str.size]
|
36
|
-
self << this_option
|
37
|
-
i += this_option.sz
|
38
|
-
end
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
18
|
# Get binary string
|
43
19
|
# @return [String]
|
44
20
|
def to_s
|
@@ -48,6 +24,17 @@ module PacketGen
|
|
48
24
|
end
|
49
25
|
str
|
50
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def record_from_hash(hsh)
|
31
|
+
Option.build(hsh)
|
32
|
+
end
|
33
|
+
|
34
|
+
def real_type(opt)
|
35
|
+
types = Option.types
|
36
|
+
types.value?(opt.type) ? IP.const_get(types.key(opt.type)) : opt.class
|
37
|
+
end
|
51
38
|
end
|
52
39
|
end
|
53
40
|
end
|
@@ -10,8 +10,33 @@ require 'ipaddr'
|
|
10
10
|
|
11
11
|
module PacketGen
|
12
12
|
module Header
|
13
|
+
# IPv6 ({https://tools.ietf.org/html/rfc8200 RFC 8200})
|
14
|
+
# 0 1 2 3
|
15
|
+
# 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
|
16
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
17
|
+
# |Version| Traffic Class | Flow Label |
|
18
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
|
+
# | Payload Length | Next Header | Hop Limit |
|
20
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
21
|
+
# | |
|
22
|
+
# + +
|
23
|
+
# | |
|
24
|
+
# + Source Address +
|
25
|
+
# | |
|
26
|
+
# + +
|
27
|
+
# | |
|
28
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
29
|
+
# | |
|
30
|
+
# + +
|
31
|
+
# | |
|
32
|
+
# + Destination Address +
|
33
|
+
# | |
|
34
|
+
# + +
|
35
|
+
# | |
|
36
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
37
|
+
#
|
13
38
|
# A IPv6 header consists of:
|
14
|
-
# * a first 32-bit word ({#u32}, of {Types::Int32} type)
|
39
|
+
# * a first 32-bit word ({#u32}, of {Types::Int32} type) composed of:
|
15
40
|
# * a 4-bit {#version} field,
|
16
41
|
# * a 8-bit {#traffic_class} field,
|
17
42
|
# * a 20-bit {#flow_label} field,
|
@@ -20,6 +45,7 @@ module PacketGen
|
|
20
45
|
# * a hop-limit field ({#hop}, +Int8+ type),
|
21
46
|
# * a source address field ({#src}, {IPv6::Addr} type),
|
22
47
|
# * a destination address field ({#dst}, +IPv6::Addr+ type),
|
48
|
+
# * and a {#body} ({Types::String} type).
|
23
49
|
#
|
24
50
|
# == Create a IPv6 header
|
25
51
|
# # standalone
|
@@ -44,6 +70,18 @@ module PacketGen
|
|
44
70
|
# ipv6[:src] # => PacketGen::Header::IPv6::Addr
|
45
71
|
# ipv6.dst = '2001:1234:5678:abcd::123'
|
46
72
|
# ipv6.body.read 'this is a body'
|
73
|
+
#
|
74
|
+
# == Add IPv6 extensions
|
75
|
+
# In IPv6, optional extensions are encoded in separate headers that
|
76
|
+
# may be placed between the IPv6 header and the upper-layer header.
|
77
|
+
#
|
78
|
+
# In PacketGen, a IPv6 extension is processedf as a classical header:
|
79
|
+
# pkt = PacketGen.gen('IPv6')
|
80
|
+
# # Add a HopByHop extension
|
81
|
+
# pkt.add('IPv6::HopByHop')
|
82
|
+
# pkt.ipv6_hopbyhop.options << { type: 'router_alert', value: [0].pack('n') }
|
83
|
+
# # Add another header
|
84
|
+
# pkt.add('UDP')
|
47
85
|
# @author Sylvain Daubert
|
48
86
|
class IPv6 < Base; end
|
49
87
|
|
@@ -104,34 +142,14 @@ module PacketGen
|
|
104
142
|
sum
|
105
143
|
end
|
106
144
|
|
107
|
-
# Send IPv6 packet on wire.
|
108
|
-
#
|
109
|
-
# When sending packet at IPv6 level, +version+, +flow_label+ and +length+
|
110
|
-
# fields are set by kernel. Source address should be a unicast address
|
111
|
-
# assigned to the host. To set any of this fields, use {Eth#to_w}.
|
112
|
-
# @param [String] iface interface name
|
145
|
+
# Send IPv6 packet on wire. All fields may be set (even {#version}).
|
146
|
+
# @param [String] _iface interface name (not used)
|
113
147
|
# @return [void]
|
114
|
-
|
115
|
-
|
148
|
+
# @since 3.0.0 no more limitations on +flow_label+, +length+ and +src+ fields.
|
149
|
+
def to_w(_iface=nil)
|
150
|
+
sock = Socket.new(Socket::AF_INET6, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
|
116
151
|
sockaddrin = Socket.sockaddr_in(0, dst)
|
117
|
-
|
118
|
-
# IPv6 RAW sockets don't have IPHDRINCL option to send IPv6 header.
|
119
|
-
# So, header must be built using ancillary data.
|
120
|
-
# Only src address, traffic_class and hop_limit can be set this way.
|
121
|
-
hop_limit = Socket::AncillaryData.int(Socket::AF_INET6,
|
122
|
-
Socket::IPPROTO_IPV6,
|
123
|
-
Socket::IPV6_HOPLIMIT, hop)
|
124
|
-
tc = Socket::AncillaryData.int(Socket::AF_INET6,
|
125
|
-
Socket::IPPROTO_IPV6,
|
126
|
-
Socket::IPV6_TCLASS,
|
127
|
-
traffic_class)
|
128
|
-
|
129
|
-
# src address is set through PKT_INFO, which needs interface index.
|
130
|
-
ifaddr = Socket.getifaddrs.find { |ia| ia.name == iface }
|
131
|
-
raise WireError, "unknown #{iface} interface" if ifaddr.nil?
|
132
|
-
pkt_info = Socket::AncillaryData.ipv6_pktinfo(Addrinfo.ip(src), ifaddr.ifindex)
|
133
|
-
|
134
|
-
sock.sendmsg body.to_s, 0, sockaddrin, hop_limit, tc, pkt_info
|
152
|
+
sock.send to_s, 0, sockaddrin
|
135
153
|
sock.close
|
136
154
|
end
|
137
155
|
|
@@ -190,13 +208,6 @@ module PacketGen
|
|
190
208
|
klass.bind header_klass, args
|
191
209
|
end
|
192
210
|
end
|
193
|
-
# Bind a upper header to IPv6 and its defined extension headers.
|
194
|
-
# @see Base.bind_header
|
195
|
-
# @deprecated USe {bind}.
|
196
|
-
def bind_header(header_klass, args={})
|
197
|
-
Deprecation.deprecated(self, __method__, 'bind', klass_method: true)
|
198
|
-
bind header_klass, args
|
199
|
-
end
|
200
211
|
end
|
201
212
|
end
|
202
213
|
end
|
@@ -52,8 +52,10 @@ module PacketGen
|
|
52
52
|
# @return [self]
|
53
53
|
def from_human(str)
|
54
54
|
return self if str.nil?
|
55
|
+
|
55
56
|
addr = IPAddr.new(str)
|
56
57
|
raise ArgumentError, 'string is not a IPv6 address' unless addr.ipv6?
|
58
|
+
|
57
59
|
addri = addr.to_i
|
58
60
|
self.a1 = addri >> 112
|
59
61
|
self.a2 = addri >> 96 & 0xffff
|
@@ -46,23 +46,6 @@ module PacketGen
|
|
46
46
|
class Options < Types::Array
|
47
47
|
set_of Option
|
48
48
|
|
49
|
-
# Populate object from a binary string
|
50
|
-
# @param [String] str
|
51
|
-
# @return [self]
|
52
|
-
def read(str)
|
53
|
-
clear
|
54
|
-
return self if str.nil?
|
55
|
-
force_binary str
|
56
|
-
klass = self.class.class_eval { @klass }
|
57
|
-
until str.empty?
|
58
|
-
obj = klass.new.read(str)
|
59
|
-
obj = Pad1.new.read(str) if obj.type.zero?
|
60
|
-
self.push obj
|
61
|
-
str.slice!(0, obj.sz)
|
62
|
-
end
|
63
|
-
self
|
64
|
-
end
|
65
|
-
|
66
49
|
# Get options as a binary string. Add padding if needed.
|
67
50
|
# @return [String]
|
68
51
|
def to_s
|
@@ -83,6 +66,12 @@ module PacketGen
|
|
83
66
|
end
|
84
67
|
str
|
85
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def real_type(opt)
|
73
|
+
opt.type.zero? ? Pad1 : opt.class
|
74
|
+
end
|
86
75
|
end
|
87
76
|
|
88
77
|
# Hop-by-hop IPv6 extension
|
@@ -111,20 +100,7 @@ module PacketGen
|
|
111
100
|
# @!attribute options
|
112
101
|
# Specific options of extension header
|
113
102
|
# @return [Options]
|
114
|
-
define_field_before :body, :options, Options
|
115
|
-
|
116
|
-
# Populate object from a binary string
|
117
|
-
# @param [String] str
|
118
|
-
# @return [self]
|
119
|
-
def read(str)
|
120
|
-
return self if str.nil?
|
121
|
-
force_binary str
|
122
|
-
self[:next].read str[0, 1]
|
123
|
-
self[:length].read str[1, 1]
|
124
|
-
self[:options].read str[2, real_length - 2]
|
125
|
-
self[:body].read str[real_length..-1]
|
126
|
-
self
|
127
|
-
end
|
103
|
+
define_field_before :body, :options, Options, builder: ->(h, t) { t.new(length_from: -> { h.real_length - 2} ) }
|
128
104
|
end
|
129
105
|
end
|
130
106
|
|