packetgen 3.3.2 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|