packetgen 3.3.2 → 4.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/README.md +37 -21
- data/lib/packetgen/capture.rb +2 -2
- data/lib/packetgen/config.rb +0 -1
- data/lib/packetgen/deprecation.rb +7 -7
- data/lib/packetgen/header/arp.rb +13 -13
- data/lib/packetgen/header/asn1_base.rb +1 -1
- data/lib/packetgen/header/base.rb +17 -18
- data/lib/packetgen/header/bootp.rb +32 -34
- data/lib/packetgen/header/dhcp/option.rb +19 -19
- data/lib/packetgen/header/dhcp/options.rb +1 -1
- data/lib/packetgen/header/dhcp.rb +3 -3
- data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
- data/lib/packetgen/header/dhcpv6/option.rb +53 -53
- data/lib/packetgen/header/dhcpv6/options.rb +1 -1
- data/lib/packetgen/header/dhcpv6/relay.rb +5 -5
- data/lib/packetgen/header/dhcpv6.rb +6 -6
- data/lib/packetgen/header/dns/name.rb +14 -10
- data/lib/packetgen/header/dns/opt.rb +2 -2
- data/lib/packetgen/header/dns/option.rb +11 -11
- data/lib/packetgen/header/dns/qdsection.rb +1 -1
- data/lib/packetgen/header/dns/question.rb +6 -8
- data/lib/packetgen/header/dns/rr.rb +56 -43
- data/lib/packetgen/header/dns/rrsection.rb +4 -4
- data/lib/packetgen/header/dns.rb +27 -30
- data/lib/packetgen/header/dot11/control.rb +11 -11
- data/lib/packetgen/header/dot11/data.rb +20 -20
- data/lib/packetgen/header/dot11/element.rb +4 -4
- data/lib/packetgen/header/dot11/management.rb +8 -8
- data/lib/packetgen/header/dot11/sub_mngt.rb +39 -53
- data/lib/packetgen/header/dot11.rb +88 -93
- data/lib/packetgen/header/dot1q.rb +10 -12
- data/lib/packetgen/header/dot1x.rb +9 -9
- data/lib/packetgen/header/eap/fast.rb +4 -4
- data/lib/packetgen/header/eap/md5.rb +6 -6
- data/lib/packetgen/header/eap/tls.rb +13 -15
- data/lib/packetgen/header/eap/ttls.rb +13 -15
- data/lib/packetgen/header/eap.rb +22 -22
- data/lib/packetgen/header/eth.rb +18 -18
- data/lib/packetgen/header/gre.rb +8 -10
- data/lib/packetgen/header/http/headers.rb +2 -2
- data/lib/packetgen/header/http/request.rb +17 -16
- data/lib/packetgen/header/http/response.rb +18 -17
- data/lib/packetgen/header/http/verbs.rb +1 -3
- data/lib/packetgen/header/icmp.rb +8 -8
- data/lib/packetgen/header/icmpv6.rb +3 -3
- data/lib/packetgen/header/igmp.rb +8 -8
- data/lib/packetgen/header/igmpv3/group_record.rb +12 -12
- data/lib/packetgen/header/igmpv3/mq.rb +16 -18
- data/lib/packetgen/header/igmpv3/mr.rb +4 -4
- data/lib/packetgen/header/igmpv3.rb +7 -7
- data/lib/packetgen/header/ip/addr.rb +13 -13
- data/lib/packetgen/header/ip/option.rb +31 -33
- data/lib/packetgen/header/ip/options.rb +1 -1
- data/lib/packetgen/header/ip.rb +37 -72
- data/lib/packetgen/header/ipv6/addr.rb +14 -14
- data/lib/packetgen/header/ipv6/extension.rb +8 -8
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +9 -9
- data/lib/packetgen/header/ipv6.rb +20 -22
- data/lib/packetgen/header/llc.rb +17 -17
- data/lib/packetgen/header/mdns.rb +1 -1
- data/lib/packetgen/header/mld.rb +6 -6
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +11 -11
- data/lib/packetgen/header/mldv2/mlq.rb +21 -23
- data/lib/packetgen/header/mldv2/mlr.rb +8 -8
- data/lib/packetgen/header/ospfv2/db_description.rb +11 -12
- data/lib/packetgen/header/ospfv2/hello.rb +11 -11
- data/lib/packetgen/header/ospfv2/ls_ack.rb +1 -1
- data/lib/packetgen/header/ospfv2/ls_request.rb +9 -9
- data/lib/packetgen/header/ospfv2/ls_update.rb +3 -3
- data/lib/packetgen/header/ospfv2/lsa.rb +54 -58
- data/lib/packetgen/header/ospfv2/lsa_header.rb +9 -9
- data/lib/packetgen/header/ospfv2.rb +27 -29
- data/lib/packetgen/header/ospfv3/db_description.rb +13 -14
- data/lib/packetgen/header/ospfv3/hello.rb +12 -12
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +17 -19
- data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -2
- data/lib/packetgen/header/ospfv3/ls_request.rb +9 -9
- data/lib/packetgen/header/ospfv3/ls_update.rb +4 -4
- data/lib/packetgen/header/ospfv3/lsa.rb +48 -51
- data/lib/packetgen/header/ospfv3/lsa_header.rb +9 -9
- data/lib/packetgen/header/ospfv3.rb +25 -27
- data/lib/packetgen/header/sctp/chunk.rb +44 -41
- data/lib/packetgen/header/sctp/error.rb +52 -52
- data/lib/packetgen/header/sctp/parameter.rb +38 -38
- data/lib/packetgen/header/sctp.rb +5 -5
- data/lib/packetgen/header/snmp.rb +2 -2
- data/lib/packetgen/header/tcp/option.rb +45 -39
- data/lib/packetgen/header/tcp/options.rb +2 -2
- data/lib/packetgen/header/tcp.rb +55 -44
- data/lib/packetgen/header/tftp.rb +16 -16
- data/lib/packetgen/header/udp.rb +8 -8
- data/lib/packetgen/header.rb +9 -10
- data/lib/packetgen/headerable.rb +13 -3
- data/lib/packetgen/inspect.rb +2 -2
- data/lib/packetgen/packet.rb +54 -37
- data/lib/packetgen/pcap.rb +15 -4
- data/lib/packetgen/pcapng/block.rb +18 -17
- data/lib/packetgen/pcapng/epb.rb +13 -15
- data/lib/packetgen/pcapng/file.rb +3 -97
- data/lib/packetgen/pcapng/idb.rb +9 -11
- data/lib/packetgen/pcapng/shb.rb +13 -15
- data/lib/packetgen/pcapng/spb.rb +8 -10
- data/lib/packetgen/pcapng/unknown_block.rb +6 -17
- data/lib/packetgen/pcapng.rb +4 -4
- data/lib/packetgen/pcaprub_wrapper.rb +17 -1
- data/lib/packetgen/proto.rb +1 -1
- data/lib/packetgen/unknown_packet.rb +2 -2
- data/lib/packetgen/utils/arp_spoofer.rb +18 -19
- data/lib/packetgen/utils.rb +2 -2
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +4 -3
- metadata +34 -29
- data/lib/packetgen/types/abstract_tlv.rb +0 -278
- data/lib/packetgen/types/array.rb +0 -287
- data/lib/packetgen/types/cstring.rb +0 -109
- data/lib/packetgen/types/enum.rb +0 -171
- data/lib/packetgen/types/fieldable.rb +0 -66
- data/lib/packetgen/types/fields.rb +0 -622
- data/lib/packetgen/types/int.rb +0 -473
- data/lib/packetgen/types/int_string.rb +0 -102
- data/lib/packetgen/types/length_from.rb +0 -54
- data/lib/packetgen/types/oui.rb +0 -52
- data/lib/packetgen/types/string.rb +0 -97
- data/lib/packetgen/types/tlv.rb +0 -161
- data/lib/packetgen/types.rb +0 -26
@@ -18,12 +18,12 @@ module PacketGen
|
|
18
18
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
19
|
#
|
20
20
|
# A IGMP header consists of:
|
21
|
-
# * a {#type} field ({
|
22
|
-
# * a {#max_resp_time} field ({
|
23
|
-
# * a {#checksum} field ({
|
21
|
+
# * a {#type} field ({BinStruct::Int8Enum} type),
|
22
|
+
# * a {#max_resp_time} field ({BinStruct::Int8} type),
|
23
|
+
# * a {#checksum} field ({BinStruct::Int16} type),
|
24
24
|
# * and a {#body}, containing more fields (see below).
|
25
25
|
#
|
26
|
-
# A IGMPv3 header may have additionnal fields. These
|
26
|
+
# A IGMPv3 header may have additionnal fields. These attributes.are handled by
|
27
27
|
# additional headers (see {IGMPv3::MQ}).
|
28
28
|
#
|
29
29
|
# == Create a IGMPv3 header
|
@@ -50,14 +50,14 @@ module PacketGen
|
|
50
50
|
# igmp.max_resp_code #=> 9728 error due to encoding as a floating point value
|
51
51
|
#
|
52
52
|
# === IGMPv3 Membership Query
|
53
|
-
# With IGMPv3, a Membership Query packet has more
|
53
|
+
# With IGMPv3, a Membership Query packet has more attributes.than with IGMPv2. To
|
54
54
|
# handle those fields, an additional header should be used:
|
55
55
|
# pkt = PacketGen.gen('IP').add('IGMPv3', type: 'MembershipQuery').add('IGMPv3::MQ')
|
56
56
|
# pkt.igmpv3 #=> PacketGen::Header::IGMPv3
|
57
57
|
# pkt.igmpv3_mq #=> PacketGen::Header::IGMPv3::MQ
|
58
58
|
#
|
59
59
|
# === IGMPv3 Membership Report
|
60
|
-
# With IGMPv3, a Membership Report packet has more
|
60
|
+
# With IGMPv3, a Membership Report packet has more attributes.than with IGMPv2. To
|
61
61
|
# handle those fields, an additional header should be used:
|
62
62
|
# pkt = PacketGen.gen('IP').add('IGMPv3', type: 'MembershipQuery').add('IGMPv3::MR')
|
63
63
|
# pkt.igmpv3 #=> PacketGen::Header::IGMPv3
|
@@ -71,7 +71,7 @@ module PacketGen
|
|
71
71
|
'MembershipReport' => 0x22,
|
72
72
|
}.freeze
|
73
73
|
|
74
|
-
|
74
|
+
remove_attr :group_addr
|
75
75
|
|
76
76
|
# Encode value for IGMPv3 Max Resp Code and QQIC.
|
77
77
|
# Value may be encoded as a float, so some error may occur.
|
@@ -11,23 +11,23 @@ module PacketGen
|
|
11
11
|
class IP
|
12
12
|
# IP address, as a group of 4 bytes
|
13
13
|
# @author Sylvain Daubert
|
14
|
-
class Addr <
|
15
|
-
include
|
14
|
+
class Addr < BinStruct::Struct
|
15
|
+
include BinStruct::Structable
|
16
16
|
|
17
17
|
# @!attribute a1
|
18
18
|
# @return [Integer] IP address first byte
|
19
|
-
|
19
|
+
define_attr :a1, BinStruct::Int8
|
20
20
|
# @!attribute a2
|
21
21
|
# @return [Integer] IP address seconf byte
|
22
|
-
|
22
|
+
define_attr :a2, BinStruct::Int8
|
23
23
|
# @!attribute a3
|
24
24
|
# @return [Integer] IP address third byte
|
25
|
-
|
25
|
+
define_attr :a3, BinStruct::Int8
|
26
26
|
# @!attribute a4
|
27
27
|
# @return [Integer] IP address fourth byte
|
28
|
-
|
28
|
+
define_attr :a4, BinStruct::Int8
|
29
29
|
|
30
|
-
IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})
|
30
|
+
IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
|
31
31
|
|
32
32
|
# Read a dotted address
|
33
33
|
# @param [String] str
|
@@ -37,10 +37,10 @@ module PacketGen
|
|
37
37
|
|
38
38
|
m = str.match(IPV4_ADDR_REGEX)
|
39
39
|
if m
|
40
|
-
self[:a1].
|
41
|
-
self[:a2].
|
42
|
-
self[:a3].
|
43
|
-
self[:a4].
|
40
|
+
self[:a1].from_human(m[1].to_i)
|
41
|
+
self[:a2].from_human(m[2].to_i)
|
42
|
+
self[:a3].from_human(m[3].to_i)
|
43
|
+
self[:a4].from_human(m[4].to_i)
|
44
44
|
end
|
45
45
|
self
|
46
46
|
end
|
@@ -48,7 +48,7 @@ module PacketGen
|
|
48
48
|
# Addr in human readable form (dotted format)
|
49
49
|
# @return [String]
|
50
50
|
def to_human
|
51
|
-
|
51
|
+
attributes.map { |f| self[f].to_i.to_s }.join('.')
|
52
52
|
end
|
53
53
|
|
54
54
|
# Addr as an integer
|
@@ -66,7 +66,7 @@ module PacketGen
|
|
66
66
|
|
67
67
|
def ==(other)
|
68
68
|
other.is_a?(self.class) &&
|
69
|
-
|
69
|
+
attributes.all? { |attr| self[attr].value == other[attr].value }
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -11,7 +11,7 @@ module PacketGen
|
|
11
11
|
class IP
|
12
12
|
# Class to handle series of IP addresses
|
13
13
|
# @author Sylvain Daubert
|
14
|
-
class ArrayOfAddr <
|
14
|
+
class ArrayOfAddr < BinStruct::Array
|
15
15
|
set_of IP::Addr
|
16
16
|
|
17
17
|
# Push a IP address to the array
|
@@ -20,14 +20,14 @@ module PacketGen
|
|
20
20
|
# array << '192.168.1.12'
|
21
21
|
def push(addr)
|
22
22
|
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
23
|
-
super
|
23
|
+
super
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
# Base class for IP options
|
28
28
|
# @author Sylvain Daubert
|
29
|
-
class Option <
|
30
|
-
include
|
29
|
+
class Option < BinStruct::Struct
|
30
|
+
include BinStruct::Structable
|
31
31
|
|
32
32
|
# EOL option type
|
33
33
|
EOL_TYPE = 0x00
|
@@ -47,20 +47,9 @@ module PacketGen
|
|
47
47
|
# @!attribute type
|
48
48
|
# 8-bit option type
|
49
49
|
# @return [Integer]
|
50
|
-
define_field :type, Types::Int8
|
51
|
-
# @!attribute length
|
52
|
-
# 8-bit option length. If 0, there is no +length+ field in option
|
53
|
-
# @return [Integer]
|
54
|
-
define_field :length, Types::Int8, default: 0, optional: ->(h) { h.type > 1 }
|
55
|
-
# @!attribute data
|
56
|
-
# option data
|
57
|
-
# @return [String]
|
58
|
-
define_field :data, Types::String, optional: ->(h) { h.length > 2 },
|
59
|
-
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
60
|
-
|
61
50
|
# @!attribute copied
|
62
51
|
# 1-bit copied flag from {#type} field
|
63
|
-
# @return [
|
52
|
+
# @return [Integer]
|
64
53
|
# @!attribute option_class
|
65
54
|
# 2-bit option class (0: control, 2: debug and measurement, 1 and 3:
|
66
55
|
# reserved) from {#type} field
|
@@ -68,7 +57,16 @@ module PacketGen
|
|
68
57
|
# !@attribute number
|
69
58
|
# 5-bit option number from {#type} field
|
70
59
|
# @return [Integer]
|
71
|
-
|
60
|
+
define_bit_attr :type, copied: 1, option_class: 2, number: 5
|
61
|
+
# @!attribute length
|
62
|
+
# 8-bit option length. If 0, there is no +length+ field in option
|
63
|
+
# @return [Integer]
|
64
|
+
define_attr :length, BinStruct::Int8, default: 0, optional: ->(h) { h.type > 1 }
|
65
|
+
# @!attribute data
|
66
|
+
# option data
|
67
|
+
# @return [String]
|
68
|
+
define_attr :data, BinStruct::String, optional: ->(h) { h.length > 2 },
|
69
|
+
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
72
70
|
|
73
71
|
# @return [Hash]
|
74
72
|
def self.types
|
@@ -76,7 +74,7 @@ module PacketGen
|
|
76
74
|
|
77
75
|
@types = {}
|
78
76
|
Option.constants.each do |cst|
|
79
|
-
next unless cst.to_s.end_with?
|
77
|
+
next unless cst.to_s.end_with?('_TYPE')
|
80
78
|
|
81
79
|
optname = cst.to_s.sub('_TYPE', '')
|
82
80
|
@types[optname] = Option.const_get(cst)
|
@@ -109,14 +107,14 @@ module PacketGen
|
|
109
107
|
# Get binary string. Set {#length} field.
|
110
108
|
# @return [String]
|
111
109
|
def to_s
|
112
|
-
self.length = super.size if respond_to?
|
110
|
+
self.length = super.size if respond_to?(:length)
|
113
111
|
super
|
114
112
|
end
|
115
113
|
|
116
114
|
# Get a human readable string
|
117
115
|
# @return [String]
|
118
116
|
def to_human
|
119
|
-
str = self.instance_of?(Option) ?
|
117
|
+
str = self.instance_of?(Option) ? "unk-#{type}" : self.class.to_s.sub(/.*::/, '')
|
120
118
|
str << ":#{self[:data].to_s.inspect}" if respond_to?(:length) && (length > 2) && !self[:data].to_s.empty?
|
121
119
|
str
|
122
120
|
end
|
@@ -124,8 +122,8 @@ module PacketGen
|
|
124
122
|
private
|
125
123
|
|
126
124
|
def class2type
|
127
|
-
|
128
|
-
Option.const_get(
|
125
|
+
opt_sym = :"#{self.class.to_s.gsub(/.*::/, '')}_TYPE"
|
126
|
+
Option.const_get(opt_sym) if Option.const_defined?(opt_sym)
|
129
127
|
end
|
130
128
|
|
131
129
|
def initialize_length_if_needed(options)
|
@@ -133,7 +131,7 @@ module PacketGen
|
|
133
131
|
end
|
134
132
|
|
135
133
|
def initialize_data_if_needed(options)
|
136
|
-
return unless
|
134
|
+
return unless attributes.include?(:data) && self[:data].respond_to?(:from_human) && options.key?(:data)
|
137
135
|
|
138
136
|
# Force data if data is set in options but not length
|
139
137
|
self.length += options[:data].size
|
@@ -143,8 +141,8 @@ module PacketGen
|
|
143
141
|
|
144
142
|
# End-of-option-List IP option
|
145
143
|
class EOL < Option
|
146
|
-
|
147
|
-
|
144
|
+
remove_attr :length
|
145
|
+
remove_attr :data
|
148
146
|
end
|
149
147
|
|
150
148
|
# No OPeration IP option
|
@@ -152,16 +150,16 @@ module PacketGen
|
|
152
150
|
|
153
151
|
# Loose Source and Record Route IP option
|
154
152
|
class LSRR < Option
|
155
|
-
|
153
|
+
remove_attr :data
|
156
154
|
|
157
155
|
# @!attribute pointer
|
158
156
|
# 8-bit pointer on next address
|
159
157
|
# @return [Integer]
|
160
|
-
|
158
|
+
define_attr :pointer, BinStruct::Int8, default: 4
|
161
159
|
# @!attribute data
|
162
160
|
# Array of IP addresses
|
163
|
-
# @return [
|
164
|
-
|
161
|
+
# @return [BinStruct::Array<IP::Addr>]
|
162
|
+
define_attr :data, ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - 3 }) }
|
165
163
|
|
166
164
|
# Get IP address pointer by {#pointer}
|
167
165
|
# @return [Addr]
|
@@ -185,12 +183,12 @@ module PacketGen
|
|
185
183
|
|
186
184
|
# Stream Identifier IP option
|
187
185
|
class SI < Option
|
188
|
-
|
186
|
+
remove_attr :data
|
189
187
|
|
190
188
|
# @!attribute id
|
191
189
|
# 16-bit stream ID
|
192
190
|
# @return [Integer]
|
193
|
-
|
191
|
+
define_attr :id, BinStruct::Int16
|
194
192
|
|
195
193
|
def to_human
|
196
194
|
super << ":#{self.id}"
|
@@ -199,12 +197,12 @@ module PacketGen
|
|
199
197
|
|
200
198
|
# Router Alert IP option
|
201
199
|
class RA < Option
|
202
|
-
|
200
|
+
remove_attr :data
|
203
201
|
|
204
202
|
# @!attribute value
|
205
203
|
# 16-bit value. Should be 0.
|
206
204
|
# @return [Integer]
|
207
|
-
|
205
|
+
define_attr :value, BinStruct::Int16, default: 0
|
208
206
|
|
209
207
|
def to_human
|
210
208
|
super << ":#{self.value}"
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -27,11 +27,11 @@ module PacketGen
|
|
27
27
|
# | Options | Padding |
|
28
28
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
29
29
|
# A IP header consists of:
|
30
|
-
# * a first byte ({#u8} of {
|
30
|
+
# * a first byte ({#u8} of {BinStruct::Int8} type) composed of:
|
31
31
|
# * a 4-bit {#version} field,
|
32
32
|
# * a 4-bit IP header length ({#ihl}) field,
|
33
|
-
# * a Type of Service field ({#tos}, {
|
34
|
-
# * a total length ({#length}, {
|
33
|
+
# * a Type of Service field ({#tos}, {BinStruct::Int8} type),
|
34
|
+
# * a total length ({#length}, {BinStruct::Int16} type),
|
35
35
|
# * a ID ({#id}, +Int16+ type),
|
36
36
|
# * a {#frag} worg (+Int16+) composed of:
|
37
37
|
# * 3 1-bit flags ({#flag_rsv}, {#flag_df} and {#flag_mf}),
|
@@ -42,7 +42,7 @@ module PacketGen
|
|
42
42
|
# * a source IP address ({#src}, {Addr} type),
|
43
43
|
# * a destination IP address ({#dst}, +Addr+ type),
|
44
44
|
# * an optional {#options} field ({Options} type),
|
45
|
-
# * and a {#body} ({
|
45
|
+
# * and a {#body} ({BinStruct::String} type).
|
46
46
|
#
|
47
47
|
# == Create a IP header
|
48
48
|
# # standalone
|
@@ -100,58 +100,54 @@ module PacketGen
|
|
100
100
|
# @!attribute u8
|
101
101
|
# First byte of IP header. May be accessed through {#version} and {#ihl}.
|
102
102
|
# @return [Integer] first byte of IP header.
|
103
|
-
|
103
|
+
# @!attribute version
|
104
|
+
# @return [Integer] 4-bit version attribute
|
105
|
+
# @!attribute ihl
|
106
|
+
# @return [Integer] 4-bit IP header length attribute
|
107
|
+
define_bit_attr :u8, default: 0x45, version: 4, ihl: 4
|
104
108
|
# @!attribute tos
|
105
109
|
# @return [Integer] 8-bit Type of Service self[attr]
|
106
|
-
|
110
|
+
define_attr :tos, BinStruct::Int8, default: 0
|
107
111
|
# @!attribute length
|
108
112
|
# @return [Integer] 16-bit IP total length
|
109
|
-
|
113
|
+
define_attr :length, BinStruct::Int16, default: 20
|
110
114
|
# @!attribute id
|
111
115
|
# @return [Integer] 16-bit ID
|
112
|
-
|
116
|
+
define_attr :id, BinStruct::Int16, default: ->(_) { rand(65_535) }
|
113
117
|
# @!attribute frag
|
114
118
|
# @return [Integer] 16-bit frag word
|
115
|
-
|
119
|
+
# @!attribute flag_rsv
|
120
|
+
# @return [Boolean] reserved bit from flags
|
121
|
+
# @!attribute flag_df
|
122
|
+
# @return [Boolean] Don't Fragment flag
|
123
|
+
# @!attribute flag_mf
|
124
|
+
# @return [Boolean] More Fragment flags
|
125
|
+
# @!attribute fragment_offset
|
126
|
+
# @return [Integer] 13-bit fragment offset
|
127
|
+
define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13
|
116
128
|
# @!attribute ttl
|
117
129
|
# @return [Integer] 8-bit Time To Live self[attr]
|
118
|
-
|
130
|
+
define_attr :ttl, BinStruct::Int8, default: 64
|
119
131
|
# @!attribute protocol
|
120
132
|
# @return [Integer] 8-bit upper protocol self[attr]
|
121
|
-
|
133
|
+
define_attr :protocol, BinStruct::Int8
|
122
134
|
# @!attribute checksum
|
123
135
|
# @return [Integer] 16-bit IP header checksum
|
124
|
-
|
136
|
+
define_attr :checksum, BinStruct::Int16, default: 0
|
125
137
|
# @!attribute src
|
126
138
|
# @return [Addr] source IP address
|
127
|
-
|
139
|
+
define_attr :src, Addr, default: '127.0.0.1'
|
128
140
|
# @!attribute dst
|
129
141
|
# @return [Addr] destination IP address
|
130
|
-
|
142
|
+
define_attr :dst, Addr, default: '127.0.0.1'
|
131
143
|
# @!attribute options
|
132
144
|
# @since 2.2.0
|
133
|
-
# @return [
|
134
|
-
|
135
|
-
|
145
|
+
# @return [BinStruct::String]
|
146
|
+
define_attr :options, Options, optional: ->(h) { h.ihl > 5 },
|
147
|
+
builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }
|
136
148
|
# @!attribute body
|
137
|
-
# @return [
|
138
|
-
|
139
|
-
|
140
|
-
# @!attribute version
|
141
|
-
# @return [Integer] 4-bit version attribute
|
142
|
-
# @!attribute ihl
|
143
|
-
# @return [Integer] 4-bit IP header length attribute
|
144
|
-
define_bit_fields_on :u8, :version, 4, :ihl, 4
|
145
|
-
|
146
|
-
# @!attribute flag_rsv
|
147
|
-
# @return [Boolean] reserved bit from flags
|
148
|
-
# @!attribute flag_df
|
149
|
-
# @return [Boolean] Don't Fragment flag
|
150
|
-
# @!attribute flag_mf
|
151
|
-
# @return [Boolean] More Fragment flags
|
152
|
-
# @!attribute fragment_offset
|
153
|
-
# @return [Integer] 13-bit fragment offset
|
154
|
-
define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13
|
149
|
+
# @return [BinStruct::String,Header::Base]
|
150
|
+
define_attr :body, BinStruct::String
|
155
151
|
|
156
152
|
# Helper method to compute sum of 16-bit words. Used to compute IP-style
|
157
153
|
# checksums.
|
@@ -160,7 +156,7 @@ module PacketGen
|
|
160
156
|
# @return [Integer]
|
161
157
|
def self.sum16(hdr)
|
162
158
|
old_checksum = nil
|
163
|
-
if hdr.respond_to?
|
159
|
+
if hdr.respond_to?(:checksum)
|
164
160
|
old_checksum = hdr.checksum
|
165
161
|
hdr.checksum = 0
|
166
162
|
end
|
@@ -178,8 +174,8 @@ module PacketGen
|
|
178
174
|
# This method:
|
179
175
|
# * checks a checksum is not greater than 0xffff. If it is,
|
180
176
|
# reduces it.
|
181
|
-
# * inverts reduced
|
182
|
-
# * forces
|
177
|
+
# * inverts reduced checksum.
|
178
|
+
# * forces checksum to 0xffff if computed checksum is 0.
|
183
179
|
# @param [Integer] checksum checksum to reduce
|
184
180
|
# @return [Integer] reduced checksum
|
185
181
|
def self.reduce_checksum(checksum)
|
@@ -203,7 +199,7 @@ module PacketGen
|
|
203
199
|
# @return [Integer]
|
204
200
|
# @since 3.0.0 add +ihl+ calculation
|
205
201
|
def calc_length
|
206
|
-
Base.calculate_and_set_length
|
202
|
+
Base.calculate_and_set_length(self)
|
207
203
|
self.ihl = 5 + self[:options].sz / 4
|
208
204
|
end
|
209
205
|
|
@@ -216,29 +212,17 @@ module PacketGen
|
|
216
212
|
|
217
213
|
# Send IP packet on wire.
|
218
214
|
#
|
219
|
-
# When sending packet at IP level, +checksum+ and +length+
|
215
|
+
# When sending packet at IP level, +checksum+ and +length+ attributes are set by
|
220
216
|
# kernel, so bad IP packets cannot be sent this way. To do so, use {Eth#to_w}.
|
221
217
|
# @param [String,nil] _iface interface name. Not used
|
222
218
|
# @return [void]
|
223
219
|
def to_w(_iface=nil)
|
224
220
|
sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
|
225
221
|
sockaddrin = Socket.sockaddr_in(0, dst)
|
226
|
-
sock.send
|
222
|
+
sock.send(to_s, 0, sockaddrin)
|
227
223
|
sock.close
|
228
224
|
end
|
229
225
|
|
230
|
-
# @return [String]
|
231
|
-
def inspect
|
232
|
-
super do |attr|
|
233
|
-
case attr
|
234
|
-
when :u8
|
235
|
-
inspect_u8
|
236
|
-
when :frag
|
237
|
-
inspect_frag
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
226
|
# Check version field
|
243
227
|
# @see [Base#parse?]
|
244
228
|
def parse?
|
@@ -259,25 +243,6 @@ module PacketGen
|
|
259
243
|
self[:src], self[:dst] = self[:dst], self[:src]
|
260
244
|
self
|
261
245
|
end
|
262
|
-
|
263
|
-
private
|
264
|
-
|
265
|
-
def inspect_u8
|
266
|
-
shift = Inspect.shift_level
|
267
|
-
str = Inspect.inspect_attribute(:u8, self[:u8])
|
268
|
-
str << shift << Inspect::FMT_ATTR % ['', 'version', version]
|
269
|
-
str << shift << Inspect::FMT_ATTR % ['', 'ihl', ihl]
|
270
|
-
end
|
271
|
-
|
272
|
-
def inspect_frag
|
273
|
-
shift = Inspect.shift_level
|
274
|
-
str = Inspect.inspect_attribute(:frag, self[:frag])
|
275
|
-
flags = %i[rsv df mf].select { |flag| send(:"flag_#{flag}?") }.map(&:upcase)
|
276
|
-
flags_str = flags.empty? ? 'none' : flags.join(',')
|
277
|
-
str << shift << Inspect::FMT_ATTR % ['', 'flags', flags_str]
|
278
|
-
foff = Inspect.int_dec_hex(fragment_offset, 4)
|
279
|
-
str << shift << Inspect::FMT_ATTR % ['', 'frag_offset', foff]
|
280
|
-
end
|
281
246
|
end
|
282
247
|
|
283
248
|
self.add_class IP
|
@@ -14,41 +14,41 @@ module PacketGen
|
|
14
14
|
class IPv6
|
15
15
|
# IPv6 address, as a group of 8 2-byte words
|
16
16
|
# @author Sylvain Daubert
|
17
|
-
class Addr <
|
18
|
-
include
|
17
|
+
class Addr < BinStruct::Struct
|
18
|
+
include BinStruct::Structable
|
19
19
|
|
20
20
|
# @!attribute a1
|
21
21
|
# 1st 2-byte word of IPv6 address
|
22
22
|
# @return [Integer]
|
23
|
-
|
23
|
+
define_attr :a1, BinStruct::Int16
|
24
24
|
# @!attribute a2
|
25
25
|
# 2nd 2-byte word of IPv6 address
|
26
26
|
# @return [Integer]
|
27
|
-
|
27
|
+
define_attr :a2, BinStruct::Int16
|
28
28
|
# @!attribute a3
|
29
29
|
# 3rd 2-byte word of IPv6 address
|
30
30
|
# @return [Integer]
|
31
|
-
|
31
|
+
define_attr :a3, BinStruct::Int16
|
32
32
|
# @!attribute a4
|
33
33
|
# 4th 2-byte word of IPv6 address
|
34
34
|
# @return [Integer]
|
35
|
-
|
35
|
+
define_attr :a4, BinStruct::Int16
|
36
36
|
# @!attribute a5
|
37
37
|
# 5th 2-byte word of IPv6 address
|
38
38
|
# @return [Integer]
|
39
|
-
|
39
|
+
define_attr :a5, BinStruct::Int16
|
40
40
|
# @!attribute a6
|
41
41
|
# 6th 2-byte word of IPv6 address
|
42
42
|
# @return [Integer]
|
43
|
-
|
43
|
+
define_attr :a6, BinStruct::Int16
|
44
44
|
# @!attribute a7
|
45
45
|
# 7th 2-byte word of IPv6 address
|
46
46
|
# @return [Integer]
|
47
|
-
|
47
|
+
define_attr :a7, BinStruct::Int16
|
48
48
|
# @!attribute a8
|
49
49
|
# 8th 2-byte word of IPv6 address
|
50
50
|
# @return [Integer]
|
51
|
-
|
51
|
+
define_attr :a8, BinStruct::Int16
|
52
52
|
|
53
53
|
# rubocop:disable Metrics/AbcSize
|
54
54
|
|
@@ -83,7 +83,7 @@ module PacketGen
|
|
83
83
|
# Return an array of address 16-bit words
|
84
84
|
# @return [Array<Integer>]
|
85
85
|
def to_a
|
86
|
-
@
|
86
|
+
@attributes.values
|
87
87
|
end
|
88
88
|
|
89
89
|
# Return true if this address is a multicast one
|
@@ -94,13 +94,13 @@ module PacketGen
|
|
94
94
|
|
95
95
|
def ==(other)
|
96
96
|
other.is_a?(self.class) &&
|
97
|
-
|
97
|
+
attributes.all? { |attr| self[attr].value == other[attr].value }
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
# Class to handle series of IPv6 addresses
|
102
102
|
# @author Sylvain Daubert
|
103
|
-
class ArrayOfAddr <
|
103
|
+
class ArrayOfAddr < BinStruct::Array
|
104
104
|
set_of IPv6::Addr
|
105
105
|
|
106
106
|
# Push a IPv6 address to the array
|
@@ -109,7 +109,7 @@ module PacketGen
|
|
109
109
|
# array << '2001:1234::125'
|
110
110
|
def push(addr)
|
111
111
|
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
112
|
-
super
|
112
|
+
super
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
@@ -25,29 +25,29 @@ module PacketGen
|
|
25
25
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
26
|
#
|
27
27
|
# Such a header consists of:
|
28
|
-
# * a {#next} header field ({
|
29
|
-
# * a {#length} field ({
|
30
|
-
# * an {#options} field ({
|
28
|
+
# * a {#next} header field ({BinStruct::Int8}),
|
29
|
+
# * a {#length} field ({BinStruct::Int8}),
|
30
|
+
# * an {#options} field ({BinStruct::String}),
|
31
31
|
# * and a {#body}, containing next header.
|
32
32
|
# @author Sylvain Daubert
|
33
33
|
class Extension < Base
|
34
34
|
# @!attribute next
|
35
35
|
# 8-bit Next header field
|
36
36
|
# @return [Integer]
|
37
|
-
|
37
|
+
define_attr :next, BinStruct::Int8
|
38
38
|
# @!attribute length
|
39
39
|
# 8-bit extension length, in 8-octets units, not including the
|
40
40
|
# first 8 octets.
|
41
41
|
# @return [Integer]
|
42
|
-
|
42
|
+
define_attr :length, BinStruct::Int8
|
43
43
|
# @!attribute options
|
44
44
|
# Specific options of extension header
|
45
45
|
# @return [String]
|
46
|
-
|
47
|
-
|
46
|
+
define_attr :options, BinStruct::String,
|
47
|
+
builder: ->(h, t) { t.new(length_from: -> { h.real_length }) }
|
48
48
|
# @!attribute body
|
49
49
|
# @return [String,Base]
|
50
|
-
|
50
|
+
define_attr :body, BinStruct::String
|
51
51
|
|
52
52
|
# Get real extension header length
|
53
53
|
# @return [Integer]
|
@@ -11,10 +11,10 @@ module PacketGen
|
|
11
11
|
class IPv6
|
12
12
|
# @!parse
|
13
13
|
# # Option for {HopByHop} IPv6 extension header.
|
14
|
-
# # @since 3.1.0 subclass of {
|
14
|
+
# # @since 3.1.0 subclass of {BinStruct::AbstractTLV}
|
15
15
|
# class Option <AbstractTLV; end
|
16
16
|
# @private
|
17
|
-
Option =
|
17
|
+
Option = BinStruct::AbstractTLV.create
|
18
18
|
|
19
19
|
class Option
|
20
20
|
# Known option types
|
@@ -37,10 +37,10 @@ module PacketGen
|
|
37
37
|
|
38
38
|
# Special option pad1, for {HopByHop} IPv6 extension header
|
39
39
|
# @author Sylvain Daubert
|
40
|
-
class Pad1 <
|
40
|
+
class Pad1 < BinStruct::Struct
|
41
41
|
# @!attribute pad
|
42
42
|
# @return [Integer]
|
43
|
-
|
43
|
+
define_attr :pad, BinStruct::Int8, default: 0
|
44
44
|
|
45
45
|
# @return [String]
|
46
46
|
def to_human
|
@@ -50,7 +50,7 @@ module PacketGen
|
|
50
50
|
|
51
51
|
# Array of {Option}, for {HopByHop} IPv6 extension header
|
52
52
|
# @author Sylvain Daubert
|
53
|
-
class Options <
|
53
|
+
class Options < BinStruct::Array
|
54
54
|
set_of Option
|
55
55
|
|
56
56
|
# Get options as a binary string. Add padding if needed.
|
@@ -96,18 +96,18 @@ module PacketGen
|
|
96
96
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
97
97
|
#
|
98
98
|
# Hop-by-hop IPv6 extension header consists of:
|
99
|
-
# * a {#next} header field ({
|
100
|
-
# * a {#length} field ({
|
99
|
+
# * a {#next} header field ({BinStruct::Int8}),
|
100
|
+
# * a {#length} field ({BinStruct::Int8}),
|
101
101
|
# * an {#options} field ({Options}),
|
102
102
|
# * and a {#body}, containing next header.
|
103
103
|
# @author Sylvain Daubert
|
104
104
|
class HopByHop < Extension
|
105
105
|
# redefine options field
|
106
|
-
|
106
|
+
remove_attr :options
|
107
107
|
# @!attribute options
|
108
108
|
# Specific options of extension header
|
109
109
|
# @return [Options]
|
110
|
-
|
110
|
+
define_attr_before :body, :options, Options, builder: ->(h, t) { t.new(length_from: -> { h.real_length - 2 }) }
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|