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,8 +11,8 @@ module PacketGen
|
|
11
11
|
class TCP
|
12
12
|
# Base class to describe a TCP option
|
13
13
|
# @author Sylvain Daubert
|
14
|
-
class Option <
|
15
|
-
include
|
14
|
+
class Option < BinStruct::Struct
|
15
|
+
include BinStruct::Structable
|
16
16
|
|
17
17
|
# EOL option value
|
18
18
|
EOL_KIND = 0
|
@@ -36,15 +36,15 @@ module PacketGen
|
|
36
36
|
# @!attribute kind
|
37
37
|
# Option kind
|
38
38
|
# @return [Integer] 8-bit option kind
|
39
|
-
|
39
|
+
define_attr :kind, BinStruct::Int8
|
40
40
|
# @!attribute length
|
41
41
|
# Option length
|
42
42
|
# @return [Integer] 8-bit option length
|
43
|
-
|
43
|
+
define_attr :length, BinStruct::Int8, optional: lambda(&:length?)
|
44
44
|
# @!attribute value
|
45
45
|
# @return [Integer,String] option value
|
46
|
-
|
47
|
-
|
46
|
+
define_attr :value, BinStruct::String, optional: ->(h) { h.length? && h.length > 2 },
|
47
|
+
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
48
48
|
|
49
49
|
# @param [hash] options
|
50
50
|
# @option options [Integer] :kind
|
@@ -55,18 +55,18 @@ module PacketGen
|
|
55
55
|
case options[:value]
|
56
56
|
when Integer
|
57
57
|
klass = case self[:length].to_i
|
58
|
-
when 3 then
|
59
|
-
when 4 then
|
60
|
-
when 6 then
|
58
|
+
when 3 then BinStruct::Int8
|
59
|
+
when 4 then BinStruct::Int16
|
60
|
+
when 6 then BinStruct::Int32
|
61
61
|
else
|
62
62
|
raise ArgumentError, 'impossible length'
|
63
63
|
end
|
64
|
-
self[:value] = klass.new(options[:value])
|
64
|
+
self[:value] = klass.new(value: options[:value])
|
65
65
|
when NilClass
|
66
66
|
# Nothing to do
|
67
67
|
else
|
68
|
-
self[:value] =
|
69
|
-
self[:length].
|
68
|
+
self[:value] = BinStruct::String.new.read(options[:value])
|
69
|
+
self[:length].from_human(self[:value].sz + 2) unless options[:length]
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -83,25 +83,33 @@ module PacketGen
|
|
83
83
|
# @return [String, Integer]
|
84
84
|
def value
|
85
85
|
case self[:value]
|
86
|
-
when
|
86
|
+
when BinStruct::Int
|
87
87
|
self[:value].to_i
|
88
88
|
else
|
89
89
|
self[:value].to_s
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
# @private
|
93
94
|
alias old_set_value value=
|
95
|
+
|
94
96
|
# Setter for value attribute
|
95
|
-
# @param[String,Integer]
|
97
|
+
# @param[String,Integer] val
|
96
98
|
# @return [String, Integer]
|
97
99
|
def value=(val)
|
98
100
|
case self[:value]
|
99
|
-
when
|
101
|
+
when BinStruct::Int
|
100
102
|
self.length = 2 + self[:value].sz
|
101
|
-
when
|
102
|
-
self.length = 2 +
|
103
|
+
when BinStruct::String
|
104
|
+
self.length = 2 + BinStruct::String.new.read(val).sz
|
105
|
+
end
|
106
|
+
|
107
|
+
case val
|
108
|
+
when Integer
|
109
|
+
self[:value].from_human(val)
|
110
|
+
else
|
111
|
+
self[:value].read(val)
|
103
112
|
end
|
104
|
-
self[:value].read val
|
105
113
|
val
|
106
114
|
end
|
107
115
|
|
@@ -115,14 +123,14 @@ module PacketGen
|
|
115
123
|
# Get option as a human readable string
|
116
124
|
# @return [String]
|
117
125
|
def to_human
|
118
|
-
str = self.instance_of?(Option) ?
|
126
|
+
str = self.instance_of?(Option) ? "unk-#{kind}" : self.class.to_s.sub(/.*::/, '')
|
119
127
|
str << ":#{self[:value].to_s.inspect}" if (length > 2) && !self[:value].to_s.empty?
|
120
128
|
str
|
121
129
|
end
|
122
130
|
|
123
131
|
# @return [String]
|
124
132
|
def inspect
|
125
|
-
str =
|
133
|
+
str = "#<#{self.class} kind=#{self[:kind].value.inspect} "
|
126
134
|
str << "length=#{self[:length].value.inspect} " if self[:length].value
|
127
135
|
str << "value=#{self[:value].inspect}>"
|
128
136
|
end
|
@@ -131,28 +139,29 @@ module PacketGen
|
|
131
139
|
# End Of Option TCP option
|
132
140
|
# @author Sylvain Daubert
|
133
141
|
class EOL < Option
|
134
|
-
|
142
|
+
update_attr :kind, default: EOL_KIND
|
135
143
|
end
|
136
144
|
|
137
145
|
# No OPeration TCP option
|
138
146
|
# @author Sylvain Daubert
|
139
147
|
class NOP < Option
|
140
148
|
# @see Option#initialize
|
141
|
-
|
149
|
+
update_attr :kind, default: NOP_KIND
|
142
150
|
end
|
143
151
|
|
144
152
|
# Maximum Segment Size TCP option
|
145
153
|
# @author Sylvain Daubert
|
146
154
|
class MSS < Option
|
147
|
-
|
148
|
-
|
155
|
+
update_attr :kind, default: MSS_KIND
|
156
|
+
update_attr :length, default: 4
|
149
157
|
|
150
158
|
# @see Option#initialize
|
151
159
|
def initialize(options={})
|
152
160
|
super
|
153
|
-
self[:value] =
|
161
|
+
self[:value] = BinStruct::Int16.new(value: options[:value])
|
154
162
|
end
|
155
163
|
|
164
|
+
# Get human-readable description
|
156
165
|
# @return [String]
|
157
166
|
def to_human
|
158
167
|
"MSS:#{value}"
|
@@ -162,15 +171,16 @@ module PacketGen
|
|
162
171
|
# Window Size TCP option
|
163
172
|
# @author Sylvain Daubert
|
164
173
|
class WS < Option
|
165
|
-
|
166
|
-
|
174
|
+
update_attr :kind, default: WS_KIND
|
175
|
+
update_attr :length, default: 3
|
167
176
|
|
168
177
|
# @see Option#initialize
|
169
178
|
def initialize(options={})
|
170
179
|
super
|
171
|
-
self[:value] =
|
180
|
+
self[:value] = BinStruct::Int8.new(value: options[:value])
|
172
181
|
end
|
173
182
|
|
183
|
+
# Get human-readable description
|
174
184
|
# @return [String]
|
175
185
|
def to_human
|
176
186
|
"WS:#{value}"
|
@@ -180,28 +190,29 @@ module PacketGen
|
|
180
190
|
# Selective Acknowledgment OK TCP option
|
181
191
|
# @author Sylvain Daubert
|
182
192
|
class SACKOK < Option
|
183
|
-
|
184
|
-
|
193
|
+
update_attr :kind, default: SACKOK_KIND
|
194
|
+
update_attr :length, default: 2
|
185
195
|
end
|
186
196
|
|
187
197
|
# Selective Acknowledgment TCP option
|
188
198
|
# @author Sylvain Daubert
|
189
199
|
class SACK < Option
|
190
|
-
|
200
|
+
update_attr :kind, default: SACK_KIND
|
191
201
|
end
|
192
202
|
|
193
203
|
# Echo TCP option
|
194
204
|
# @author Sylvain Daubert
|
195
205
|
class ECHO < Option
|
196
|
-
|
197
|
-
|
206
|
+
update_attr :kind, default: ECHO_KIND
|
207
|
+
update_attr :length, default: 6
|
198
208
|
|
199
209
|
# @see Option#initialize
|
200
210
|
def initialize(options={})
|
201
211
|
super
|
202
|
-
self[:value] =
|
212
|
+
self[:value] = BinStruct::Int32.new(value: options[:value])
|
203
213
|
end
|
204
214
|
|
215
|
+
# Get human-readable description
|
205
216
|
# @return [String]
|
206
217
|
def to_human
|
207
218
|
"WS:#{value}"
|
@@ -211,15 +222,16 @@ module PacketGen
|
|
211
222
|
# Echo Reply TCP option
|
212
223
|
# @author Sylvain Daubert
|
213
224
|
class ECHOREPLY < Option
|
214
|
-
|
215
|
-
|
225
|
+
update_attr :kind, default: ECHOREPLY_KIND
|
226
|
+
update_attr :length, default: 6
|
216
227
|
|
217
228
|
# @see Option#initialize
|
218
229
|
def initialize(options={})
|
219
230
|
super
|
220
|
-
self[:value] =
|
231
|
+
self[:value] = BinStruct::Int32.new(value: options[:value])
|
221
232
|
end
|
222
233
|
|
234
|
+
# Get human-readable description
|
223
235
|
# @return [String]
|
224
236
|
def to_human
|
225
237
|
"WS:#{value}"
|
@@ -229,8 +241,8 @@ module PacketGen
|
|
229
241
|
# Timestamp TCP option
|
230
242
|
# @author Sylvain Daubert
|
231
243
|
class TS < Option
|
232
|
-
|
233
|
-
|
244
|
+
update_attr :kind, default: TS_KIND
|
245
|
+
update_attr :length, default: 10
|
234
246
|
|
235
247
|
# @see Option#initialize
|
236
248
|
def initialize(options={})
|
@@ -238,6 +250,7 @@ module PacketGen
|
|
238
250
|
self[:value].read(options[:value] || "\0" * 8)
|
239
251
|
end
|
240
252
|
|
253
|
+
# Get human-readable description
|
241
254
|
# @return [String]
|
242
255
|
def to_human
|
243
256
|
value, echo_reply = self[:value].unpack('NN')
|
@@ -11,9 +11,17 @@ require_relative 'option'
|
|
11
11
|
module PacketGen
|
12
12
|
module Header
|
13
13
|
class TCP
|
14
|
-
# Container for TCP options in {TCP TCP header}.
|
14
|
+
# Container for TCP {Option options} in {TCP TCP header}.
|
15
15
|
# @author Sylvain Daubert
|
16
|
-
|
16
|
+
# @since 1.0.0
|
17
|
+
# @since 4.1.0 +#<<+ accepts +:kind+ parameter in hash
|
18
|
+
# @example Add an option from a hash
|
19
|
+
# opts = PacketGen::Header::TCP::Options.new
|
20
|
+
# # Option kind may be set using :opt
|
21
|
+
# opts << { opt: 'MSS', value: 1250 }
|
22
|
+
# # It may aldo be set using :kind
|
23
|
+
# opts << { kind: 'EOL' }
|
24
|
+
class Options < BinStruct::Array
|
17
25
|
set_of Option
|
18
26
|
|
19
27
|
# Get {Option} subclasses
|
@@ -23,7 +31,7 @@ module PacketGen
|
|
23
31
|
|
24
32
|
@klasses = []
|
25
33
|
Option.constants.each do |cst|
|
26
|
-
next unless cst.to_s.end_with?
|
34
|
+
next unless cst.to_s.end_with?('_KIND')
|
27
35
|
|
28
36
|
optname = cst.to_s.sub('_KIND', '')
|
29
37
|
@klasses[Option.const_get(cst)] = TCP.const_get(optname)
|
@@ -34,8 +42,8 @@ module PacketGen
|
|
34
42
|
private
|
35
43
|
|
36
44
|
def record_from_hash(hsh)
|
37
|
-
if hsh.key? :
|
38
|
-
klassname = hsh.delete(:opt)
|
45
|
+
if hsh.key?(:opt) || hsh.key?(:kind)
|
46
|
+
klassname = hsh.delete(:opt) || hsh.delete(:kind)
|
39
47
|
raise ArgumentError, 'opt should be a TCP::Option subclass' unless TCP.const_defined?(klassname)
|
40
48
|
|
41
49
|
klass = TCP.const_get(klassname)
|
data/lib/packetgen/header/tcp.rb
CHANGED
@@ -29,56 +29,62 @@ module PacketGen
|
|
29
29
|
# | data |
|
30
30
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
31
31
|
# A TCP header consists of:
|
32
|
-
# * a source port ({#sport},
|
33
|
-
# * a destination port ({#dport}, +Int16+ type),
|
34
|
-
# * a sequence number ({#seqnum},
|
35
|
-
# * an acknownledge number ({#acknum}, +Int32+ type),
|
36
|
-
# * a 16-bit field ({#u16}, +Int16+ type) composed of:
|
37
|
-
# * a 4-bit {#data_offset}
|
32
|
+
# * a source port ({#sport}, +BinStruct::Int16+ type),
|
33
|
+
# * a destination port ({#dport}, +BinStruct::Int16+ type),
|
34
|
+
# * a sequence number ({#seqnum}, +BinStruct::Int32+ type),
|
35
|
+
# * an acknownledge number ({#acknum}, +BinStruct::Int32+ type),
|
36
|
+
# * a 16-bit field ({#u16}, +BinStruct::Int16+ type) composed of:
|
37
|
+
# * a 4-bit {#data_offset},
|
38
38
|
# * a 3-bit {#reserved} field,
|
39
39
|
# * a 9-bit {#flags} field,
|
40
|
-
# * a {#window} field (+Int16+ type),
|
41
|
-
# * a {#checksum} field (+Int16+ type),
|
42
|
-
# * a urgent pointer ({#urg_pointer}, +Int16+ type),
|
40
|
+
# * a {#window} field (+BinStruct::Int16+ type),
|
41
|
+
# * a {#checksum} field (+BinStruct::Int16+ type),
|
42
|
+
# * a urgent pointer ({#urg_pointer}, +BinStruct::Int16+ type),
|
43
43
|
# * an optional {#options} field ({Options} type),
|
44
|
-
# * and a {#body} (
|
44
|
+
# * and a {#body} (+BinStruct::String+ type).
|
45
45
|
#
|
46
|
-
#
|
46
|
+
# @example Create a TCP header
|
47
47
|
# # standalone
|
48
48
|
# tcph = PacketGen::Header::TCP.new
|
49
49
|
# # in a IP packet
|
50
50
|
# pkt = PacketGen.gen('IP').add('TCP')
|
51
51
|
# # access to TCP header
|
52
|
-
# pkt.tcp # => PacketGen::Header::TCP
|
52
|
+
# pkt.tcp.class # => PacketGen::Header::TCP
|
53
53
|
#
|
54
|
-
#
|
54
|
+
# @example TCP attributes
|
55
|
+
# tcph = PacketGen::Header::TCP.new
|
55
56
|
# tcph.sport = 4500
|
56
57
|
# tcph.dport = 80
|
57
58
|
# tcph.seqnum = 43
|
58
59
|
# tcph.acknum = 0x45678925
|
59
60
|
# tcph.wsize = 0x240
|
60
61
|
# tcph.urg_pointer = 0x40
|
61
|
-
# tcph.body
|
62
|
+
# tcph.body = 'this is a body'
|
62
63
|
#
|
63
|
-
#
|
64
|
-
# TCP
|
64
|
+
# @example TCP Flags
|
65
|
+
# tcph = PacketGen::Header::TCP.new
|
66
|
+
# # TCP flags may be accesed as a 9-bit integer:
|
65
67
|
# tcph.flags = 0x1002
|
66
|
-
# Each flag may be accessed independently:
|
67
|
-
# tcph.flag_syn? # =>
|
68
|
+
# # Each flag may be accessed independently:
|
69
|
+
# tcph.flag_syn? # => true
|
68
70
|
# tcph.flag_rst = true
|
69
71
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
# tcph.options <<
|
72
|
+
# @example TCP Options
|
73
|
+
# tcph = PacketGen::Header::TCP.new
|
74
|
+
# # options TCP attribute is a PacketGen::Header::TCP::Options.
|
75
|
+
# # PacketGen::Header::TCP::Option may added to it:
|
76
|
+
# tcph.options << PacketGen::Header::TCP::MSS.new(value: 1250)
|
77
|
+
# # or
|
78
|
+
# tcph.options << { kind: 'MSS', value: 1250 }
|
79
|
+
# tcph.options.last.class #=> PacketGen::Header::TCP::MSS
|
75
80
|
# @author Sylvain Daubert
|
81
|
+
# @author LemonTree55
|
76
82
|
class TCP < Base
|
77
83
|
end
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
81
|
-
# Need to load Options now, as this is used through
|
87
|
+
# Need to load Options now, as this is used through define_bit_attr,
|
82
88
|
# which make a call to TCP.new, which needs Options
|
83
89
|
require_relative 'tcp/options'
|
84
90
|
|
@@ -91,41 +97,69 @@ module PacketGen
|
|
91
97
|
# @!attribute sport
|
92
98
|
# 16-bit TCP source port
|
93
99
|
# @return [Integer]
|
94
|
-
|
100
|
+
define_attr :sport, BinStruct::Int16
|
95
101
|
# @!attribute dport
|
96
102
|
# 16-bit TCP destination port
|
97
103
|
# @return [Integer]
|
98
|
-
|
104
|
+
define_attr :dport, BinStruct::Int16
|
99
105
|
# @!attribute seqnum
|
100
106
|
# 32-bit TCP sequence number
|
101
107
|
# @return [Integer]
|
102
|
-
|
108
|
+
define_attr :seqnum, BinStruct::Int32, default: ->(_) { rand(2**32) }
|
103
109
|
# @!attribute acknum
|
104
110
|
# 32-bit TCP acknowledgement number
|
105
111
|
# @return [Integer]
|
106
|
-
|
112
|
+
define_attr :acknum, BinStruct::Int32
|
107
113
|
# @!attribute u16
|
108
114
|
# @return [Integer] 16-bit word used by flags and bit fields
|
109
|
-
|
115
|
+
# @!attribute data_offset
|
116
|
+
# @return [Integer] 4-bit data offset from {#u16}
|
117
|
+
# @!attribute reserved
|
118
|
+
# @return [Integer] 3-bit reserved from {#u16}
|
119
|
+
# @!attribute flags
|
120
|
+
# @return [Integer] 9-bit flags from {#u16}
|
121
|
+
# @!attribute flag_ns
|
122
|
+
# @return [Integer] 1-bit NS flag
|
123
|
+
# @!attribute flag_cwr
|
124
|
+
# @return [Integer] 1-bit CWR flag
|
125
|
+
# @!attribute flag_ece
|
126
|
+
# @return [Integer] 1-bit ECE flag
|
127
|
+
# @!attribute flag_urg
|
128
|
+
# @return [Integer] 1-bit URG flag
|
129
|
+
# @!attribute flag_ack
|
130
|
+
# @return [Integer] 1-bit ACK flag
|
131
|
+
# @!attribute flag_psh
|
132
|
+
# @return [Integer] 1-bit PSH flag
|
133
|
+
# @!attribute flag_rst
|
134
|
+
# @return [Integer] 1-bit RST flag
|
135
|
+
# @!attribute flag_syn
|
136
|
+
# @return [Integer] 1-bit SYN flag
|
137
|
+
# @!attribute flag_fin
|
138
|
+
# @return [Integer] 1-bit FIN flag
|
139
|
+
define_bit_attr :u16, data_offset: 4, reserved: 3, flag_ns: 1, flag_cwr: 1, flag_ece: 1, flag_urg: 1, flag_ack: 1, flag_psh: 1,
|
140
|
+
flag_rst: 1, flag_syn: 1, flag_fin: 1
|
141
|
+
alias hlen data_offset
|
142
|
+
alias hlen= data_offset=
|
110
143
|
# @!attribute window
|
111
144
|
# 16-bit TCP window size
|
112
145
|
# @return [Integer]
|
113
|
-
|
146
|
+
define_attr :window, BinStruct::Int16
|
114
147
|
# @!attribute checksum
|
115
148
|
# 16-bit TCP checksum
|
116
149
|
# @return [Integer]
|
117
|
-
|
150
|
+
define_attr :checksum, BinStruct::Int16
|
118
151
|
# @!attribute urg_pointer
|
119
152
|
# 16-bit TCP urgent data pointer
|
120
153
|
# @return [Integer]
|
121
|
-
|
154
|
+
define_attr :urg_pointer, BinStruct::Int16
|
122
155
|
# @!attribute options
|
123
156
|
# TCP options
|
124
157
|
# @return [Options]
|
125
|
-
|
158
|
+
define_attr :options, TCP::Options, builder: ->(h, t) { t.new(length_from: -> { h.data_offset > 5 ? (h.data_offset - 5) * 4 : 0 }) }
|
126
159
|
# @!attribute body
|
127
|
-
#
|
128
|
-
|
160
|
+
# TCP body
|
161
|
+
# @return [BinStruct::String,Headerable]
|
162
|
+
define_attr :body, BinStruct::String
|
129
163
|
|
130
164
|
alias source_port sport
|
131
165
|
alias source_port= sport=
|
@@ -154,42 +188,26 @@ module PacketGen
|
|
154
188
|
# @option options [Integer] :window
|
155
189
|
# @option options [Integer] :checksum
|
156
190
|
# @option options [Integer] :urg_pointer
|
157
|
-
# @option options [String] :body
|
191
|
+
# @option options [String, Headerable] :body
|
158
192
|
def initialize(options={})
|
159
193
|
opts = { data_offset: 5 }.merge!(options)
|
160
194
|
super(opts)
|
195
|
+
self.flags = opts[:flags] if opts.key?(:flags)
|
161
196
|
end
|
162
197
|
|
163
|
-
#
|
164
|
-
#
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
# @return [Integer] 9-bit flags from {#u16}
|
169
|
-
define_bit_fields_on :u16, :data_offset, 4, :reserved, 3, :flags, 9
|
170
|
-
alias hlen data_offset
|
171
|
-
alias hlen= data_offset=
|
198
|
+
# Get all flags value from [#u16]
|
199
|
+
# @return [Integer]
|
200
|
+
def flags
|
201
|
+
self.u16 & 0x1ff
|
202
|
+
end
|
172
203
|
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
# @return [Boolean] 1-bit URG flag
|
181
|
-
# @!attribute flag_ack
|
182
|
-
# @return [Boolean] 1-bit ACK flag
|
183
|
-
# @!attribute flag_psh
|
184
|
-
# @return [Boolean] 1-bit PSH flag
|
185
|
-
# @!attribute flag_rst
|
186
|
-
# @return [Boolean] 1-bit RST flag
|
187
|
-
# @!attribute flag_syn
|
188
|
-
# @return [Boolean] 1-bit SYN flag
|
189
|
-
# @!attribute flag_fin
|
190
|
-
# @return [Boolean] 1-bit FIN flag
|
191
|
-
define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
|
192
|
-
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin
|
204
|
+
# Set all flags at once
|
205
|
+
# @param [Integer] value
|
206
|
+
# @return [Integer]
|
207
|
+
def flags=(value)
|
208
|
+
new_u16 = (self.u16 & 0xfe00) | (value & 0x1ff)
|
209
|
+
self[:u16].from_human(new_u16)
|
210
|
+
end
|
193
211
|
|
194
212
|
# Compute checksum and set +checksum+ field
|
195
213
|
# @return [Integer]
|
@@ -10,25 +10,26 @@ module PacketGen
|
|
10
10
|
module Header
|
11
11
|
# A TFTP (Trivial File Transfer Protocol,
|
12
12
|
# {https://tools.ietf.org/html/rfc1350 RFC 1350}) header consists of:
|
13
|
-
# *
|
13
|
+
# * an {#opcode} (+BinStruct::Int16Enum+),
|
14
14
|
# * and a body. Its content depends on opcode.
|
15
15
|
#
|
16
16
|
# Specialized subclasses exists to handle {TFTP::RRQ Read Request},
|
17
17
|
# {TFTP::WRQ Write Request}, {TFTP::DATA DATA}, {TFTP::ACK ACK} and
|
18
18
|
# {TFTP::ERROR ERROR} packets.
|
19
19
|
#
|
20
|
-
#
|
20
|
+
# @example Create a TFTP header
|
21
21
|
# # standalone
|
22
22
|
# tftp = PacketGen::Header::TFTP.new
|
23
23
|
# # in a packet
|
24
24
|
# pkt = PacketGen.gen('IP').add('UDP').add('TFTP')
|
25
25
|
# # access to TFTP header
|
26
|
-
# pkt.tftp # => PacketGen::Header::TFTP
|
26
|
+
# pkt.tftp.class # => PacketGen::Header::TFTP
|
27
27
|
#
|
28
|
-
#
|
28
|
+
# @example TFTP attributes
|
29
|
+
# tftp = PacketGen::Header::TFTP.new
|
29
30
|
# tftp.opcode = 'RRQ'
|
30
31
|
# tftp.opcode = 1
|
31
|
-
# tftp.body
|
32
|
+
# tftp.body = 'this is a body'
|
32
33
|
#
|
33
34
|
# == TFTP parsing
|
34
35
|
# When parsing, only first packet (read or write request) should be decoded
|
@@ -46,6 +47,7 @@ module PacketGen
|
|
46
47
|
# packets[0].tftp.decode!(packets[1..-1])
|
47
48
|
# packets.map { |pkt| pkt.headers.last.class.to_s }.join(',') # => TFTP::RRQ,TFTP::DATA,UDP,TFTP::ACK
|
48
49
|
# @author Sylvain Daubert
|
50
|
+
# @author LemonTree55
|
49
51
|
# @since 2.3.0
|
50
52
|
class TFTP < Base
|
51
53
|
# Known opcodes
|
@@ -60,11 +62,12 @@ module PacketGen
|
|
60
62
|
# @!attribute opcode
|
61
63
|
# 16-bit operation code
|
62
64
|
# @return [Integer]
|
63
|
-
|
65
|
+
define_attr :opcode, BinStruct::Int16Enum, enum: OPCODES
|
64
66
|
|
65
67
|
# @!attribute body
|
66
|
-
#
|
67
|
-
|
68
|
+
# TFTP body, if opcode is unknown
|
69
|
+
# @return [String,Headerable]
|
70
|
+
define_attr :body, BinStruct::String
|
68
71
|
|
69
72
|
def initialize(options={})
|
70
73
|
type = protocol_name.sub(/^.*::/, '')
|
@@ -85,13 +88,13 @@ module PacketGen
|
|
85
88
|
def read(str)
|
86
89
|
if self.instance_of? TFTP
|
87
90
|
super
|
88
|
-
if OPCODES.value?
|
89
|
-
TFTP.const_get(human_opcode).new.read
|
91
|
+
if OPCODES.value?(opcode)
|
92
|
+
TFTP.const_get(human_opcode).new.read(str)
|
90
93
|
else
|
91
94
|
self
|
92
95
|
end
|
93
96
|
else
|
94
|
-
old_read
|
97
|
+
old_read(str)
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
@@ -130,7 +133,7 @@ module PacketGen
|
|
130
133
|
# @param [Packet] packet
|
131
134
|
# @return [void]
|
132
135
|
def added_to_packet(packet)
|
133
|
-
return if packet.respond_to?
|
136
|
+
return if packet.respond_to?(:tftp)
|
134
137
|
|
135
138
|
packet.instance_eval("def tftp(arg=nil); header(#{self.class}, arg); end") # def tftp(arg=nil); header(TFTP, arg); end
|
136
139
|
end
|
@@ -140,24 +143,25 @@ module PacketGen
|
|
140
143
|
def decode_tftp_packet(pkt)
|
141
144
|
tftp = Packet.parse(pkt.body, first_header: 'TFTP')
|
142
145
|
udp_dport = pkt.udp.dport
|
143
|
-
pkt.encapsulate
|
146
|
+
pkt.encapsulate(tftp)
|
144
147
|
# need to fix it as #encapsulate force it to 69
|
145
148
|
pkt.udp.dport = udp_dport
|
146
149
|
end
|
147
150
|
|
148
|
-
# TFTP Read Request header
|
151
|
+
# TFTP Read Request header.
|
152
|
+
# This header remove {#body} attribute and repalces it with {#filename} and {#mode}.
|
149
153
|
class RRQ < TFTP
|
150
|
-
|
154
|
+
remove_attr :body
|
151
155
|
|
152
156
|
# @!attribute filename
|
153
157
|
# Filename to access
|
154
158
|
# @return [String]
|
155
|
-
|
159
|
+
define_attr :filename, BinStruct::CString
|
156
160
|
|
157
161
|
# @!attribute mode
|
158
162
|
# Mode used. Should be +netascii+, +octet+ or +mail+
|
159
163
|
# @return [String]
|
160
|
-
|
164
|
+
define_attr :mode, BinStruct::CString
|
161
165
|
end
|
162
166
|
|
163
167
|
# TFTP Write Request header
|
@@ -168,32 +172,34 @@ module PacketGen
|
|
168
172
|
# @!attribute block_num
|
169
173
|
# 16-bit block number
|
170
174
|
# @return [Integer]
|
171
|
-
|
175
|
+
define_attr_before :body, :block_num, BinStruct::Int16
|
172
176
|
end
|
173
177
|
|
174
|
-
# TFTP ACK header
|
178
|
+
# TFTP ACK header.
|
179
|
+
# This header remove {#body} attribute and repalces it with {#block_num}.
|
175
180
|
class ACK < TFTP
|
176
|
-
|
181
|
+
remove_attr :body
|
177
182
|
|
178
183
|
# @!attribute block_num
|
179
184
|
# 16-bit block number
|
180
185
|
# @return [Integer]
|
181
|
-
|
186
|
+
define_attr :block_num, BinStruct::Int16
|
182
187
|
end
|
183
188
|
|
184
|
-
# TFTP ERROR header
|
189
|
+
# TFTP ERROR header.
|
190
|
+
# This header remove {#body} attribute and repalces it with {#error_code} and {#error_msg}.
|
185
191
|
class ERROR < TFTP
|
186
|
-
|
192
|
+
remove_attr :body
|
187
193
|
|
188
194
|
# @!attribute error_code
|
189
195
|
# 16-bit error code
|
190
196
|
# @return [Integer]
|
191
|
-
|
197
|
+
define_attr :error_code, BinStruct::Int16
|
192
198
|
|
193
199
|
# @!attribute error_msg
|
194
200
|
# Error message
|
195
201
|
# @return [String]
|
196
|
-
|
202
|
+
define_attr :error_msg, BinStruct::CString
|
197
203
|
alias error_message error_msg
|
198
204
|
end
|
199
205
|
end
|