packetgen 3.3.3 → 4.1.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 +38 -22
- data/lib/packetgen/capture.rb +2 -2
- data/lib/packetgen/config.rb +0 -1
- data/lib/packetgen/deprecation.rb +14 -8
- data/lib/packetgen/header/arp.rb +17 -18
- data/lib/packetgen/header/asn1_base.rb +2 -1
- data/lib/packetgen/header/base.rb +42 -40
- data/lib/packetgen/header/bootp.rb +35 -37
- data/lib/packetgen/header/dhcp/option.rb +21 -21
- data/lib/packetgen/header/dhcp/options.rb +3 -3
- data/lib/packetgen/header/dhcp.rb +8 -9
- data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
- data/lib/packetgen/header/dhcpv6/option.rb +83 -61
- data/lib/packetgen/header/dhcpv6/options.rb +4 -4
- data/lib/packetgen/header/dhcpv6/relay.rb +6 -5
- data/lib/packetgen/header/dhcpv6.rb +17 -18
- data/lib/packetgen/header/dns/name.rb +21 -16
- data/lib/packetgen/header/dns/opt.rb +5 -2
- data/lib/packetgen/header/dns/option.rb +14 -14
- data/lib/packetgen/header/dns/qdsection.rb +3 -3
- data/lib/packetgen/header/dns/question.rb +7 -8
- data/lib/packetgen/header/dns/rr.rb +56 -43
- data/lib/packetgen/header/dns/rrsection.rb +6 -6
- data/lib/packetgen/header/dns.rb +103 -90
- data/lib/packetgen/header/dot11/control.rb +12 -12
- data/lib/packetgen/header/dot11/data.rb +25 -24
- data/lib/packetgen/header/dot11/element.rb +4 -4
- data/lib/packetgen/header/dot11/management.rb +21 -18
- data/lib/packetgen/header/dot11/sub_mngt.rb +40 -53
- data/lib/packetgen/header/dot11.rb +117 -122
- data/lib/packetgen/header/dot1q.rb +12 -13
- data/lib/packetgen/header/dot1x.rb +13 -13
- data/lib/packetgen/header/eap/fast.rb +4 -4
- data/lib/packetgen/header/eap/md5.rb +16 -8
- data/lib/packetgen/header/eap/tls.rb +18 -19
- data/lib/packetgen/header/eap/ttls.rb +22 -21
- data/lib/packetgen/header/eap.rb +73 -48
- data/lib/packetgen/header/eth.rb +41 -27
- data/lib/packetgen/header/gre.rb +33 -11
- data/lib/packetgen/header/http/headers.rb +7 -6
- data/lib/packetgen/header/http/request.rb +38 -29
- data/lib/packetgen/header/http/response.rb +35 -27
- data/lib/packetgen/header/http/verbs.rb +1 -3
- data/lib/packetgen/header/icmp.rb +14 -14
- data/lib/packetgen/header/icmpv6.rb +10 -9
- data/lib/packetgen/header/igmp.rb +26 -15
- data/lib/packetgen/header/igmpv3/group_record.rb +18 -13
- data/lib/packetgen/header/igmpv3/mq.rb +16 -18
- data/lib/packetgen/header/igmpv3/mr.rb +5 -5
- data/lib/packetgen/header/igmpv3.rb +12 -11
- data/lib/packetgen/header/ip/addr.rb +19 -15
- data/lib/packetgen/header/ip/option.rb +47 -36
- data/lib/packetgen/header/ip/options.rb +1 -1
- data/lib/packetgen/header/ip.rb +77 -95
- data/lib/packetgen/header/ipv6/addr.rb +28 -27
- data/lib/packetgen/header/ipv6/extension.rb +13 -11
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +32 -13
- data/lib/packetgen/header/ipv6.rb +42 -35
- data/lib/packetgen/header/llc.rb +28 -21
- data/lib/packetgen/header/mdns.rb +10 -3
- data/lib/packetgen/header/mld.rb +15 -13
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +17 -12
- data/lib/packetgen/header/mldv2/mlq.rb +22 -24
- data/lib/packetgen/header/mldv2/mlr.rb +8 -8
- data/lib/packetgen/header/mldv2.rb +1 -1
- data/lib/packetgen/header/ospfv2/db_description.rb +17 -18
- data/lib/packetgen/header/ospfv2/hello.rb +18 -17
- data/lib/packetgen/header/ospfv2/ls_ack.rb +6 -7
- data/lib/packetgen/header/ospfv2/ls_request.rb +14 -13
- data/lib/packetgen/header/ospfv2/ls_update.rb +9 -9
- data/lib/packetgen/header/ospfv2/lsa.rb +79 -60
- data/lib/packetgen/header/ospfv2/lsa_header.rb +12 -11
- data/lib/packetgen/header/ospfv2.rb +49 -46
- data/lib/packetgen/header/ospfv3/db_description.rb +20 -22
- data/lib/packetgen/header/ospfv3/hello.rb +17 -16
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +22 -20
- data/lib/packetgen/header/ospfv3/ls_ack.rb +7 -8
- data/lib/packetgen/header/ospfv3/ls_request.rb +18 -18
- data/lib/packetgen/header/ospfv3/ls_update.rb +10 -10
- data/lib/packetgen/header/ospfv3/lsa.rb +62 -51
- data/lib/packetgen/header/ospfv3/lsa_header.rb +12 -11
- data/lib/packetgen/header/ospfv3.rb +54 -52
- data/lib/packetgen/header/sctp/chunk.rb +80 -56
- data/lib/packetgen/header/sctp/error.rb +174 -202
- data/lib/packetgen/header/sctp/padded32.rb +3 -3
- data/lib/packetgen/header/sctp/parameter.rb +89 -136
- data/lib/packetgen/header/sctp.rb +19 -8
- data/lib/packetgen/header/snmp.rb +108 -7
- data/lib/packetgen/header/tcp/option.rb +52 -39
- data/lib/packetgen/header/tcp/options.rb +13 -5
- data/lib/packetgen/header/tcp.rb +83 -65
- data/lib/packetgen/header/tftp.rb +31 -25
- data/lib/packetgen/header/udp.rb +21 -19
- data/lib/packetgen/header.rb +23 -18
- data/lib/packetgen/headerable.rb +21 -5
- data/lib/packetgen/inspect.rb +3 -8
- data/lib/packetgen/packet.rb +146 -71
- data/lib/packetgen/pcap.rb +15 -4
- data/lib/packetgen/pcapng/block.rb +20 -18
- data/lib/packetgen/pcapng/epb.rb +13 -15
- data/lib/packetgen/pcapng/file.rb +44 -111
- data/lib/packetgen/pcapng/idb.rb +11 -12
- data/lib/packetgen/pcapng/shb.rb +15 -16
- data/lib/packetgen/pcapng/spb.rb +9 -11
- data/lib/packetgen/pcapng/unknown_block.rb +6 -17
- data/lib/packetgen/pcapng.rb +6 -4
- data/lib/packetgen/pcaprub_wrapper.rb +17 -1
- data/lib/packetgen/proto.rb +5 -1
- data/lib/packetgen/unknown_packet.rb +5 -5
- data/lib/packetgen/utils/arp_spoofer.rb +18 -19
- data/lib/packetgen/utils.rb +4 -3
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +12 -5
- metadata +29 -38
- 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
@@ -11,23 +11,27 @@ 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
|
18
18
|
# @param [String,Addr] addr
|
19
19
|
# @return [self]
|
20
|
+
# @example
|
21
|
+
# array = PacketGen::Header::IP::ArrayOfAddr.new
|
22
|
+
# # #<< uses #push internally
|
20
23
|
# array << '192.168.1.12'
|
24
|
+
# array.push(PacketGen::Header::IP::Addr.new.from_human('192.18.1.13'))
|
21
25
|
def push(addr)
|
22
26
|
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
23
|
-
super
|
27
|
+
super
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
# Base class for IP options
|
28
32
|
# @author Sylvain Daubert
|
29
|
-
class Option <
|
30
|
-
include
|
33
|
+
class Option < BinStruct::Struct
|
34
|
+
include BinStruct::Structable
|
31
35
|
|
32
36
|
# EOL option type
|
33
37
|
EOL_TYPE = 0x00
|
@@ -46,21 +50,10 @@ module PacketGen
|
|
46
50
|
|
47
51
|
# @!attribute type
|
48
52
|
# 8-bit option type
|
49
|
-
#
|
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
|
-
|
53
|
+
# @return [Integer]
|
61
54
|
# @!attribute copied
|
62
55
|
# 1-bit copied flag from {#type} field
|
63
|
-
# @return [
|
56
|
+
# @return [Integer]
|
64
57
|
# @!attribute option_class
|
65
58
|
# 2-bit option class (0: control, 2: debug and measurement, 1 and 3:
|
66
59
|
# reserved) from {#type} field
|
@@ -68,15 +61,26 @@ module PacketGen
|
|
68
61
|
# !@attribute number
|
69
62
|
# 5-bit option number from {#type} field
|
70
63
|
# @return [Integer]
|
71
|
-
|
64
|
+
define_bit_attr :type, copied: 1, option_class: 2, number: 5
|
65
|
+
# @!attribute length
|
66
|
+
# 8-bit option length. If 0, there is no +length+ field in option
|
67
|
+
# @return [Integer]
|
68
|
+
define_attr :length, BinStruct::Int8, default: 0, optional: ->(h) { h.type > 1 }
|
69
|
+
# @!attribute data
|
70
|
+
# option data
|
71
|
+
# @return [String]
|
72
|
+
define_attr :data, BinStruct::String, optional: ->(h) { h.length > 2 },
|
73
|
+
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
72
74
|
|
73
|
-
# @
|
75
|
+
# @private
|
76
|
+
# Return a cached hash associating type name to its value.
|
77
|
+
# @return [Hash{String => Integer}]
|
74
78
|
def self.types
|
75
79
|
return @types if defined? @types
|
76
80
|
|
77
81
|
@types = {}
|
78
82
|
Option.constants.each do |cst|
|
79
|
-
next unless cst.to_s.end_with?
|
83
|
+
next unless cst.to_s.end_with?('_TYPE')
|
80
84
|
|
81
85
|
optname = cst.to_s.sub('_TYPE', '')
|
82
86
|
@types[optname] = Option.const_get(cst)
|
@@ -85,6 +89,7 @@ module PacketGen
|
|
85
89
|
end
|
86
90
|
|
87
91
|
# Factory to build an option from its type
|
92
|
+
# @param [Hash] options
|
88
93
|
# @return [Option]
|
89
94
|
def self.build(options={})
|
90
95
|
type = options[:type]
|
@@ -98,6 +103,8 @@ module PacketGen
|
|
98
103
|
klass.new(options)
|
99
104
|
end
|
100
105
|
|
106
|
+
# Force type value for subclasses, if not specified
|
107
|
+
# @return [Option]
|
101
108
|
def initialize(options={})
|
102
109
|
options[:type] = class2type unless options[:type]
|
103
110
|
|
@@ -109,14 +116,14 @@ module PacketGen
|
|
109
116
|
# Get binary string. Set {#length} field.
|
110
117
|
# @return [String]
|
111
118
|
def to_s
|
112
|
-
self.length = super.size if respond_to?
|
119
|
+
self.length = super.size if respond_to?(:length)
|
113
120
|
super
|
114
121
|
end
|
115
122
|
|
116
123
|
# Get a human readable string
|
117
124
|
# @return [String]
|
118
125
|
def to_human
|
119
|
-
str = self.instance_of?(Option) ?
|
126
|
+
str = self.instance_of?(Option) ? "unk-#{type}" : self.class.to_s.sub(/.*::/, '')
|
120
127
|
str << ":#{self[:data].to_s.inspect}" if respond_to?(:length) && (length > 2) && !self[:data].to_s.empty?
|
121
128
|
str
|
122
129
|
end
|
@@ -124,8 +131,8 @@ module PacketGen
|
|
124
131
|
private
|
125
132
|
|
126
133
|
def class2type
|
127
|
-
|
128
|
-
Option.const_get(
|
134
|
+
opt_sym = :"#{self.class.to_s.gsub(/.*::/, '')}_TYPE"
|
135
|
+
Option.const_get(opt_sym) if Option.const_defined?(opt_sym)
|
129
136
|
end
|
130
137
|
|
131
138
|
def initialize_length_if_needed(options)
|
@@ -133,7 +140,7 @@ module PacketGen
|
|
133
140
|
end
|
134
141
|
|
135
142
|
def initialize_data_if_needed(options)
|
136
|
-
return unless
|
143
|
+
return unless attributes.include?(:data) && self[:data].respond_to?(:from_human) && options.key?(:data)
|
137
144
|
|
138
145
|
# Force data if data is set in options but not length
|
139
146
|
self.length += options[:data].size
|
@@ -143,8 +150,8 @@ module PacketGen
|
|
143
150
|
|
144
151
|
# End-of-option-List IP option
|
145
152
|
class EOL < Option
|
146
|
-
|
147
|
-
|
153
|
+
remove_attr :length
|
154
|
+
remove_attr :data
|
148
155
|
end
|
149
156
|
|
150
157
|
# No OPeration IP option
|
@@ -152,16 +159,16 @@ module PacketGen
|
|
152
159
|
|
153
160
|
# Loose Source and Record Route IP option
|
154
161
|
class LSRR < Option
|
155
|
-
|
162
|
+
remove_attr :data
|
156
163
|
|
157
164
|
# @!attribute pointer
|
158
|
-
# 8-bit
|
165
|
+
# 8-bit po+++inter on next address
|
159
166
|
# @return [Integer]
|
160
|
-
|
167
|
+
define_attr :pointer, BinStruct::Int8, default: 4
|
161
168
|
# @!attribute data
|
162
169
|
# Array of IP addresses
|
163
|
-
# @return [
|
164
|
-
|
170
|
+
# @return [BinStruct::Array<IP::Addr>]
|
171
|
+
define_attr :data, ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - 3 }) }
|
165
172
|
|
166
173
|
# Get IP address pointer by {#pointer}
|
167
174
|
# @return [Addr]
|
@@ -185,13 +192,15 @@ module PacketGen
|
|
185
192
|
|
186
193
|
# Stream Identifier IP option
|
187
194
|
class SI < Option
|
188
|
-
|
195
|
+
remove_attr :data
|
189
196
|
|
190
197
|
# @!attribute id
|
191
198
|
# 16-bit stream ID
|
192
199
|
# @return [Integer]
|
193
|
-
|
200
|
+
define_attr :id, BinStruct::Int16
|
194
201
|
|
202
|
+
# Return a human-readable string
|
203
|
+
# @return [String]
|
195
204
|
def to_human
|
196
205
|
super << ":#{self.id}"
|
197
206
|
end
|
@@ -199,13 +208,15 @@ module PacketGen
|
|
199
208
|
|
200
209
|
# Router Alert IP option
|
201
210
|
class RA < Option
|
202
|
-
|
211
|
+
remove_attr :data
|
203
212
|
|
204
213
|
# @!attribute value
|
205
214
|
# 16-bit value. Should be 0.
|
206
215
|
# @return [Integer]
|
207
|
-
|
216
|
+
define_attr :value, BinStruct::Int16, default: 0
|
208
217
|
|
218
|
+
# Return a human-readable string
|
219
|
+
# @return [String]
|
209
220
|
def to_human
|
210
221
|
super << ":#{self.value}"
|
211
222
|
end
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -27,32 +27,33 @@ 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},
|
35
|
-
# * a ID ({#id}, +Int16+ type),
|
36
|
-
# * a {#frag} worg (+Int16+) composed of:
|
33
|
+
# * a Type of Service field ({#tos}, +BinStruct::Int8+ type),
|
34
|
+
# * a total length ({#length}, +BinStruct::Int16+ type),
|
35
|
+
# * a ID ({#id}, +BinStruct::Int16+ type),
|
36
|
+
# * a {#frag} worg (+BinStruct::Int16+) composed of:
|
37
37
|
# * 3 1-bit flags ({#flag_rsv}, {#flag_df} and {#flag_mf}),
|
38
38
|
# * a 13-bit {#fragment_offset} field,
|
39
39
|
# * a Time-to-Live ({#ttl}) field (+Int8+),
|
40
|
-
# * a {#protocol} field (+Int8+),
|
41
|
-
# * a {#checksum} field (+Int16+),
|
40
|
+
# * a {#protocol} field (+BinStruct::Int8+),
|
41
|
+
# * a {#checksum} field (+BinStruct::Int16+),
|
42
42
|
# * a source IP address ({#src}, {Addr} type),
|
43
|
-
# * a destination IP address ({#dst},
|
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
|
+
# @example Create a IP header
|
48
48
|
# # standalone
|
49
49
|
# ip = PacketGen::Header::IP.new
|
50
50
|
# # in a packet
|
51
51
|
# pkt = PacketGen.gen('IP')
|
52
52
|
# # access to IP header
|
53
|
-
# pkt.ip # => PacketGen::Header::IP
|
53
|
+
# pkt.ip.class # => PacketGen::Header::IP
|
54
54
|
#
|
55
|
-
#
|
55
|
+
# @example IP attributes
|
56
|
+
# ip = PacketGen::Header::IP.new
|
56
57
|
# ip.u8 = 0x45
|
57
58
|
# # the same as
|
58
59
|
# ip.version = 4
|
@@ -66,21 +67,20 @@ module PacketGen
|
|
66
67
|
# ip.flag_mf = true
|
67
68
|
# ip.fragment_offset = 0x31
|
68
69
|
#
|
69
|
-
# ip.flag_rsv? # =>
|
70
|
-
# ip.flag_df? # =>
|
71
|
-
# ip.flag_mf? # =>
|
70
|
+
# ip.flag_rsv? # => false
|
71
|
+
# ip.flag_df? # => false
|
72
|
+
# ip.flag_mf? # => true
|
72
73
|
#
|
73
74
|
# ip.ttl = 0x40
|
74
75
|
# ip.protocol = 6
|
75
76
|
# ip.checksum = 0xffff
|
76
77
|
# ip.src = '127.0.0.1'
|
77
78
|
# ip.src # => "127.0.0.1"
|
78
|
-
# ip[:src]
|
79
|
+
# ip[:src].class # => PacketGen::Header::IP::Addr
|
79
80
|
# ip.dst = '127.0.0.2'
|
80
|
-
# ip.body
|
81
|
+
# ip.body = 'this is a body'
|
81
82
|
#
|
82
|
-
#
|
83
|
-
# IP has an {#options} attribute used to store datagram options.
|
83
|
+
# @example Add IP options
|
84
84
|
# pkt = PacketGen.gen('IP')
|
85
85
|
# # add option from class
|
86
86
|
# pkt.ip.options << PacketGen::Header::IP::RA.new
|
@@ -100,58 +100,70 @@ 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
|
+
# 4-bit version attribute
|
105
|
+
# @return [Integer]
|
106
|
+
# @!attribute ihl
|
107
|
+
# 4-bit IP header length attribute, as 32-bit word count.
|
108
|
+
# Default to 5 (IP header without option).
|
109
|
+
# @return [Integer]
|
110
|
+
define_bit_attr :u8, default: 0x45, version: 4, ihl: 4
|
104
111
|
# @!attribute tos
|
105
112
|
# @return [Integer] 8-bit Type of Service self[attr]
|
106
|
-
|
113
|
+
define_attr :tos, BinStruct::Int8, default: 0
|
107
114
|
# @!attribute length
|
108
|
-
#
|
109
|
-
|
115
|
+
# 16-bit IP total length, including this header.
|
116
|
+
# @return [Integer]
|
117
|
+
define_attr :length, BinStruct::Int16, default: 20
|
110
118
|
# @!attribute id
|
111
119
|
# @return [Integer] 16-bit ID
|
112
|
-
|
120
|
+
define_attr :id, BinStruct::Int16, default: ->(_) { rand(65_535) }
|
113
121
|
# @!attribute frag
|
114
|
-
#
|
115
|
-
|
122
|
+
# 16-bit frag word
|
123
|
+
# @return [Integer]
|
124
|
+
# @!attribute flag_rsv
|
125
|
+
# reserved bit from flags
|
126
|
+
# @return [Boolean]
|
127
|
+
# @!attribute flag_df
|
128
|
+
# Don't Fragment flag
|
129
|
+
# @return [Boolean]
|
130
|
+
# @!attribute flag_mf
|
131
|
+
# More Fragment flags
|
132
|
+
# @return [Boolean]
|
133
|
+
# @!attribute fragment_offset
|
134
|
+
# 13-bit fragment offset
|
135
|
+
# @return [Integer]
|
136
|
+
define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13
|
116
137
|
# @!attribute ttl
|
117
|
-
#
|
118
|
-
|
138
|
+
# 8-bit Time To Live
|
139
|
+
# @return [Integer]
|
140
|
+
define_attr :ttl, BinStruct::Int8, default: 64
|
119
141
|
# @!attribute protocol
|
120
|
-
#
|
121
|
-
|
142
|
+
# 8-bit upper protocol
|
143
|
+
# @return [Integer]
|
144
|
+
define_attr :protocol, BinStruct::Int8
|
122
145
|
# @!attribute checksum
|
123
|
-
#
|
124
|
-
|
146
|
+
# 16-bit IP header checksum
|
147
|
+
# @return [Integer]
|
148
|
+
define_attr :checksum, BinStruct::Int16, default: 0
|
125
149
|
# @!attribute src
|
126
|
-
#
|
127
|
-
|
150
|
+
# source IP address
|
151
|
+
# @return [Addr]
|
152
|
+
define_attr :src, Addr, default: '127.0.0.1'
|
128
153
|
# @!attribute dst
|
129
|
-
#
|
130
|
-
|
154
|
+
# destination IP address
|
155
|
+
# @return [Addr]
|
156
|
+
define_attr :dst, Addr, default: '127.0.0.1'
|
131
157
|
# @!attribute options
|
158
|
+
# IP options
|
132
159
|
# @since 2.2.0
|
133
|
-
# @return [
|
134
|
-
|
135
|
-
|
160
|
+
# @return [Options]
|
161
|
+
define_attr :options, Options, optional: ->(h) { h.ihl > 5 },
|
162
|
+
builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }
|
136
163
|
# @!attribute body
|
137
|
-
#
|
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
|
164
|
+
# IP body
|
165
|
+
# @return [BinStruct::String,Headerable]
|
166
|
+
define_attr :body, BinStruct::String
|
155
167
|
|
156
168
|
# Helper method to compute sum of 16-bit words. Used to compute IP-style
|
157
169
|
# checksums.
|
@@ -160,7 +172,7 @@ module PacketGen
|
|
160
172
|
# @return [Integer]
|
161
173
|
def self.sum16(hdr)
|
162
174
|
old_checksum = nil
|
163
|
-
if hdr.respond_to?
|
175
|
+
if hdr.respond_to?(:checksum)
|
164
176
|
old_checksum = hdr.checksum
|
165
177
|
hdr.checksum = 0
|
166
178
|
end
|
@@ -178,8 +190,8 @@ module PacketGen
|
|
178
190
|
# This method:
|
179
191
|
# * checks a checksum is not greater than 0xffff. If it is,
|
180
192
|
# reduces it.
|
181
|
-
# * inverts reduced
|
182
|
-
# * forces
|
193
|
+
# * inverts reduced checksum.
|
194
|
+
# * forces checksum to 0xffff if computed checksum is 0.
|
183
195
|
# @param [Integer] checksum checksum to reduce
|
184
196
|
# @return [Integer] reduced checksum
|
185
197
|
def self.reduce_checksum(checksum)
|
@@ -203,7 +215,7 @@ module PacketGen
|
|
203
215
|
# @return [Integer]
|
204
216
|
# @since 3.0.0 add +ihl+ calculation
|
205
217
|
def calc_length
|
206
|
-
Base.calculate_and_set_length
|
218
|
+
Base.calculate_and_set_length(self)
|
207
219
|
self.ihl = 5 + self[:options].sz / 4
|
208
220
|
end
|
209
221
|
|
@@ -216,31 +228,20 @@ module PacketGen
|
|
216
228
|
|
217
229
|
# Send IP packet on wire.
|
218
230
|
#
|
219
|
-
# When sending packet at IP level, +checksum+ and +length+
|
231
|
+
# When sending packet at IP level, +checksum+ and +length+ attributes are set by
|
220
232
|
# kernel, so bad IP packets cannot be sent this way. To do so, use {Eth#to_w}.
|
221
233
|
# @param [String,nil] _iface interface name. Not used
|
222
234
|
# @return [void]
|
223
235
|
def to_w(_iface=nil)
|
224
236
|
sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
|
225
237
|
sockaddrin = Socket.sockaddr_in(0, dst)
|
226
|
-
sock.send
|
238
|
+
sock.send(to_s, 0, sockaddrin)
|
227
239
|
sock.close
|
228
240
|
end
|
229
241
|
|
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
242
|
# Check version field
|
243
|
-
# @see
|
243
|
+
# @see Base#parse?
|
244
|
+
# @return [Boolean]
|
244
245
|
def parse?
|
245
246
|
(version == 4) && (ihl >= 5)
|
246
247
|
end
|
@@ -259,25 +260,6 @@ module PacketGen
|
|
259
260
|
self[:src], self[:dst] = self[:dst], self[:src]
|
260
261
|
self
|
261
262
|
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
263
|
end
|
282
264
|
|
283
265
|
self.add_class IP
|
@@ -14,47 +14,47 @@ module PacketGen
|
|
14
14
|
class IPv6
|
15
15
|
# IPv6 address, as a group of 8 2-byte words
|
16
16
|
# @author Sylvain Daubert
|
17
|
-
|
18
|
-
|
17
|
+
# @author LemonTree55
|
18
|
+
class Addr < BinStruct::Struct
|
19
|
+
include BinStruct::Structable
|
19
20
|
|
20
21
|
# @!attribute a1
|
21
22
|
# 1st 2-byte word of IPv6 address
|
22
23
|
# @return [Integer]
|
23
|
-
|
24
|
+
define_attr :a1, BinStruct::Int16
|
24
25
|
# @!attribute a2
|
25
26
|
# 2nd 2-byte word of IPv6 address
|
26
27
|
# @return [Integer]
|
27
|
-
|
28
|
+
define_attr :a2, BinStruct::Int16
|
28
29
|
# @!attribute a3
|
29
30
|
# 3rd 2-byte word of IPv6 address
|
30
31
|
# @return [Integer]
|
31
|
-
|
32
|
+
define_attr :a3, BinStruct::Int16
|
32
33
|
# @!attribute a4
|
33
34
|
# 4th 2-byte word of IPv6 address
|
34
35
|
# @return [Integer]
|
35
|
-
|
36
|
+
define_attr :a4, BinStruct::Int16
|
36
37
|
# @!attribute a5
|
37
38
|
# 5th 2-byte word of IPv6 address
|
38
39
|
# @return [Integer]
|
39
|
-
|
40
|
+
define_attr :a5, BinStruct::Int16
|
40
41
|
# @!attribute a6
|
41
42
|
# 6th 2-byte word of IPv6 address
|
42
43
|
# @return [Integer]
|
43
|
-
|
44
|
+
define_attr :a6, BinStruct::Int16
|
44
45
|
# @!attribute a7
|
45
46
|
# 7th 2-byte word of IPv6 address
|
46
47
|
# @return [Integer]
|
47
|
-
|
48
|
+
define_attr :a7, BinStruct::Int16
|
48
49
|
# @!attribute a8
|
49
50
|
# 8th 2-byte word of IPv6 address
|
50
51
|
# @return [Integer]
|
51
|
-
|
52
|
-
|
53
|
-
# rubocop:disable Metrics/AbcSize
|
52
|
+
define_attr :a8, BinStruct::Int16
|
54
53
|
|
55
54
|
# Read a colon-delimited address
|
56
55
|
# @param [String] str
|
57
56
|
# @return [self]
|
57
|
+
# @raise [ArgumentError] not a colon-delimited IPv6 address
|
58
58
|
def from_human(str)
|
59
59
|
return self if str.nil?
|
60
60
|
|
@@ -62,19 +62,13 @@ module PacketGen
|
|
62
62
|
raise ArgumentError, 'string is not a IPv6 address' unless addr.ipv6?
|
63
63
|
|
64
64
|
addri = addr.to_i
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
self.a4 = addri >> 64 & 0xffff
|
69
|
-
self.a5 = addri >> 48 & 0xffff
|
70
|
-
self.a6 = addri >> 32 & 0xffff
|
71
|
-
self.a7 = addri >> 16 & 0xffff
|
72
|
-
self.a8 = addri & 0xffff
|
65
|
+
8.times do |i|
|
66
|
+
self.send(:"a#{i + 1}=", addri >> (16 * (7 - i)) & 0xffff)
|
67
|
+
end
|
73
68
|
self
|
74
69
|
end
|
75
|
-
# rubocop:enable Metrics/AbcSize
|
76
70
|
|
77
|
-
#
|
71
|
+
# Return IPv6 address in human readable form (colon-delimited hex string)
|
78
72
|
# @return [String]
|
79
73
|
def to_human
|
80
74
|
IPAddr.new(to_a.map { |a| a.to_i.to_s(16) }.join(':')).to_s
|
@@ -83,7 +77,7 @@ module PacketGen
|
|
83
77
|
# Return an array of address 16-bit words
|
84
78
|
# @return [Array<Integer>]
|
85
79
|
def to_a
|
86
|
-
@
|
80
|
+
@attributes.values
|
87
81
|
end
|
88
82
|
|
89
83
|
# Return true if this address is a multicast one
|
@@ -92,24 +86,31 @@ module PacketGen
|
|
92
86
|
self.a1 & 0xff00 == 0xff00
|
93
87
|
end
|
94
88
|
|
89
|
+
# Check equaliy to +other+.
|
90
|
+
# Equal if other has the same class, and all attributes are equal
|
91
|
+
# @return [Boolean]
|
95
92
|
def ==(other)
|
96
93
|
other.is_a?(self.class) &&
|
97
|
-
|
94
|
+
attributes.all? { |attr| self[attr].value == other[attr].value }
|
98
95
|
end
|
99
96
|
end
|
100
97
|
|
101
98
|
# Class to handle series of IPv6 addresses
|
102
99
|
# @author Sylvain Daubert
|
103
|
-
class ArrayOfAddr <
|
100
|
+
class ArrayOfAddr < BinStruct::Array
|
104
101
|
set_of IPv6::Addr
|
105
102
|
|
106
103
|
# Push a IPv6 address to the array
|
107
104
|
# @param [String,Addr] addr
|
108
105
|
# @return [self]
|
109
|
-
#
|
106
|
+
# @example
|
107
|
+
# array = PacketGen::Header::IPv6::ArrayOfAddr.new
|
108
|
+
# # #<< uses #push internally
|
109
|
+
# array << '2001::1'
|
110
|
+
# array.push(PacketGen::Header::IPv6::Addr.new.from_human('1:2:3:abcd::1'))
|
110
111
|
def push(addr)
|
111
112
|
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
112
|
-
super
|
113
|
+
super
|
113
114
|
end
|
114
115
|
end
|
115
116
|
end
|
@@ -9,7 +9,7 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
class IPv6
|
12
|
-
# Base class to handle IPv6 extensions
|
12
|
+
# Base class to handle IPv6 extensions.
|
13
13
|
# @abstract You should not use this class but its subclasses.
|
14
14
|
# A IPv6 extension header has the following format:
|
15
15
|
# 0 1 2 3
|
@@ -25,29 +25,31 @@ 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
|
+
# @since 2.4.0
|
33
34
|
class Extension < Base
|
34
35
|
# @!attribute next
|
35
36
|
# 8-bit Next header field
|
36
37
|
# @return [Integer]
|
37
|
-
|
38
|
+
define_attr :next, BinStruct::Int8
|
38
39
|
# @!attribute length
|
39
40
|
# 8-bit extension length, in 8-octets units, not including the
|
40
41
|
# first 8 octets.
|
41
42
|
# @return [Integer]
|
42
|
-
|
43
|
+
define_attr :length, BinStruct::Int8
|
43
44
|
# @!attribute options
|
44
45
|
# Specific options of extension header
|
45
46
|
# @return [String]
|
46
|
-
|
47
|
-
|
47
|
+
define_attr :options, BinStruct::String,
|
48
|
+
builder: ->(h, t) { t.new(length_from: -> { h.real_length - 2}) }
|
48
49
|
# @!attribute body
|
49
|
-
#
|
50
|
-
|
50
|
+
# Next header in IPv6 packet
|
51
|
+
# @return [String,Headerable]
|
52
|
+
define_attr :body, BinStruct::String
|
51
53
|
|
52
54
|
# Get real extension header length
|
53
55
|
# @return [Integer]
|
@@ -55,7 +57,7 @@ module PacketGen
|
|
55
57
|
(length + 1) * 8
|
56
58
|
end
|
57
59
|
|
58
|
-
# Compute length and set +
|
60
|
+
# Compute length and set {#length}+ attribute
|
59
61
|
# @return [Integer]
|
60
62
|
def calc_length
|
61
63
|
self.length = (options.sz + 2) / 8 - 1
|