packetfu 1.1.8 → 1.1.9
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.
- data/README.rdoc +11 -12
- data/bench/octets.rb +9 -9
- data/examples/100kpackets.rb +13 -12
- data/examples/ackscan.rb +17 -16
- data/examples/arp.rb +36 -35
- data/examples/arphood.rb +37 -36
- data/examples/dissect_thinger.rb +7 -6
- data/examples/ethernet.rb +1 -0
- data/examples/examples.rb +1 -0
- data/examples/ifconfig.rb +1 -0
- data/examples/new-simple-stats.rb +24 -23
- data/examples/packetfu-shell.rb +26 -25
- data/examples/simple-sniffer.rb +10 -9
- data/examples/simple-stats.rb +24 -23
- data/examples/slammer.rb +4 -3
- data/lib/packetfu.rb +128 -127
- data/lib/packetfu/capture.rb +170 -169
- data/lib/packetfu/config.rb +53 -52
- data/lib/packetfu/inject.rb +57 -56
- data/lib/packetfu/packet.rb +529 -528
- data/lib/packetfu/pcap.rb +580 -579
- data/lib/packetfu/protos/arp.rb +91 -90
- data/lib/packetfu/protos/arp/header.rb +159 -158
- data/lib/packetfu/protos/arp/mixin.rb +37 -36
- data/lib/packetfu/protos/eth.rb +45 -44
- data/lib/packetfu/protos/eth/header.rb +244 -243
- data/lib/packetfu/protos/eth/mixin.rb +4 -3
- data/lib/packetfu/protos/hsrp.rb +70 -69
- data/lib/packetfu/protos/hsrp/header.rb +108 -107
- data/lib/packetfu/protos/hsrp/mixin.rb +30 -29
- data/lib/packetfu/protos/icmp.rb +72 -71
- data/lib/packetfu/protos/icmp/header.rb +83 -82
- data/lib/packetfu/protos/icmp/mixin.rb +15 -14
- data/lib/packetfu/protos/invalid.rb +50 -49
- data/lib/packetfu/protos/ip.rb +70 -69
- data/lib/packetfu/protos/ip/header.rb +292 -291
- data/lib/packetfu/protos/ip/mixin.rb +41 -40
- data/lib/packetfu/protos/ipv6.rb +51 -50
- data/lib/packetfu/protos/ipv6/header.rb +189 -188
- data/lib/packetfu/protos/ipv6/mixin.rb +30 -29
- data/lib/packetfu/protos/lldp.rb +3 -1
- data/lib/packetfu/protos/lldp/header.rb +1 -0
- data/lib/packetfu/protos/lldp/mixin.rb +1 -0
- data/lib/packetfu/protos/tcp.rb +177 -176
- data/lib/packetfu/protos/tcp/ecn.rb +36 -35
- data/lib/packetfu/protos/tcp/flags.rb +75 -74
- data/lib/packetfu/protos/tcp/header.rb +269 -268
- data/lib/packetfu/protos/tcp/hlen.rb +33 -32
- data/lib/packetfu/protos/tcp/mixin.rb +47 -46
- data/lib/packetfu/protos/tcp/option.rb +322 -321
- data/lib/packetfu/protos/tcp/options.rb +96 -95
- data/lib/packetfu/protos/tcp/reserved.rb +36 -35
- data/lib/packetfu/protos/udp.rb +117 -116
- data/lib/packetfu/protos/udp/header.rb +92 -91
- data/lib/packetfu/protos/udp/mixin.rb +4 -3
- data/lib/packetfu/structfu.rb +281 -280
- data/lib/packetfu/utils.rb +211 -208
- data/lib/packetfu/version.rb +42 -41
- data/packetfu.gemspec +1 -1
- data/spec/ethpacket_spec.rb +48 -48
- data/spec/packet_spec.rb +57 -57
- data/spec/packet_subclasses_spec.rb +8 -8
- data/spec/packetfu_spec.rb +59 -59
- data/spec/structfu_spec.rb +268 -268
- data/spec/tcp_spec.rb +75 -75
- data/test/all_tests.rb +13 -13
- data/test/func_lldp.rb +3 -3
- data/test/ptest.rb +2 -2
- data/test/test_arp.rb +116 -116
- data/test/test_capture.rb +45 -45
- data/test/test_eth.rb +68 -68
- data/test/test_hsrp.rb +9 -9
- data/test/test_icmp.rb +52 -52
- data/test/test_inject.rb +18 -18
- data/test/test_invalid.rb +16 -16
- data/test/test_ip.rb +36 -36
- data/test/test_ip6.rb +48 -48
- data/test/test_octets.rb +21 -21
- data/test/test_packet.rb +154 -154
- data/test/test_pcap.rb +170 -170
- data/test/test_structfu.rb +97 -97
- data/test/test_tcp.rb +320 -320
- data/test/test_udp.rb +76 -76
- metadata +2 -2
@@ -1,40 +1,41 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
3
|
# Implements the Header Length for TCPHeader.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
#
|
5
|
+
# ==== Header Definition
|
6
|
+
#
|
7
|
+
# Fixnum (4 bits) :hlen
|
8
|
+
class TcpHlen < Struct.new(:hlen)
|
9
|
+
|
10
|
+
include StructFu
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def initialize(args={})
|
13
|
+
super(args[:hlen])
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
# Returns the TcpHlen field as an integer. Note these will become the high
|
17
|
+
# bits at the TCP header's offset, even though the lower 4 bits
|
18
|
+
# will be further chopped up.
|
19
|
+
def to_i
|
20
|
+
hlen.to_i & 0b1111
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
# Reads a string to populate the object.
|
24
|
+
def read(str)
|
25
|
+
force_binary(str)
|
26
|
+
return self if str.nil? || str.size.zero?
|
27
|
+
if 1.respond_to? :ord
|
28
|
+
self[:hlen] = (str[0].ord & 0b11110000) >> 4
|
29
|
+
else
|
30
|
+
self[:hlen] = (str[0] & 0b11110000) >> 4
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
# Returns the object in string form.
|
36
|
+
def to_s
|
37
|
+
[self.to_i].pack("C")
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
+
end
|
40
41
|
end
|
@@ -1,48 +1,49 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
3
|
+
# This Mixin simplifies access to the TCPHeaders. Mix this in with your
|
4
|
+
# packet interface, and it will add methods that essentially delegate to
|
5
|
+
# the 'tcp_header' method (assuming that it is a TCPHeader object)
|
6
|
+
module TCPHeaderMixin
|
7
|
+
def tcp_src=(v); self.tcp_header.tcp_src= v; end
|
8
|
+
def tcp_src; self.tcp_header.tcp_src; end
|
9
|
+
def tcp_dst=(v); self.tcp_header.tcp_dst= v; end
|
10
|
+
def tcp_dst; self.tcp_header.tcp_dst; end
|
11
|
+
def tcp_seq=(v); self.tcp_header.tcp_seq= v; end
|
12
|
+
def tcp_seq; self.tcp_header.tcp_seq; end
|
13
|
+
def tcp_ack=(v); self.tcp_header.tcp_ack= v; end
|
14
|
+
def tcp_ack; self.tcp_header.tcp_ack; end
|
15
|
+
def tcp_win=(v); self.tcp_header.tcp_win= v; end
|
16
|
+
def tcp_win; self.tcp_header.tcp_win; end
|
17
|
+
def tcp_sum=(v); self.tcp_header.tcp_sum= v; end
|
18
|
+
def tcp_sum; self.tcp_header.tcp_sum; end
|
19
|
+
def tcp_urg=(v); self.tcp_header.tcp_urg= v; end
|
20
|
+
def tcp_urg; self.tcp_header.tcp_urg; end
|
21
|
+
def tcp_hlen; self.tcp_header.tcp_hlen; end
|
22
|
+
def tcp_hlen=(v); self.tcp_header.tcp_hlen= v; end
|
23
|
+
def tcp_reserved; self.tcp_header.tcp_reserved; end
|
24
|
+
def tcp_reserved=(v); self.tcp_header.tcp_reserved= v; end
|
25
|
+
def tcp_ecn; self.tcp_header.tcp_ecn; end
|
26
|
+
def tcp_ecn=(v); self.tcp_header.tcp_ecn= v; end
|
27
|
+
def tcp_opts; self.tcp_header.tcp_opts; end
|
28
|
+
def tcp_opts=(v); self.tcp_header.tcp_opts= v; end
|
29
|
+
def tcp_calc_seq; self.tcp_header.tcp_calc_seq; end
|
30
|
+
def tcp_calc_src; self.tcp_header.tcp_calc_src; end
|
31
|
+
def tcp_opts_len; self.tcp_header.tcp_opts_len; end
|
32
|
+
def tcp_calc_hlen; self.tcp_header.tcp_calc_hlen; end
|
33
|
+
def tcp_options; self.tcp_header.tcp_options; end
|
34
|
+
def tcp_flags_dotmap; self.tcp_header.tcp_flags_dotmap; end
|
35
|
+
def tcp_options=(v); self.tcp_header.tcp_options= v; end
|
36
|
+
def tcp_sport; self.tcp_header.tcp_sport; end
|
37
|
+
def tcp_sport=(v); self.tcp_header.tcp_sport= v; end
|
38
|
+
def tcp_dport; self.tcp_header.tcp_dport; end
|
39
|
+
def tcp_dport=(v); self.tcp_header.tcp_dport= v; end
|
40
|
+
def tcp_recalc(*v); self.tcp_header.tcp_recalc(*v); end
|
41
|
+
def tcp_flags_readable; self.tcp_header.tcp_flags_readable; end
|
42
|
+
def tcp_ack_readable; self.tcp_header.tcp_ack_readable; end
|
43
|
+
def tcp_seq_readable; self.tcp_header.tcp_seq_readable; end
|
44
|
+
def tcp_sum_readable; self.tcp_header.tcp_sum_readable; end
|
45
|
+
def tcp_opts_readable; self.tcp_header.tcp_opts_readable; end
|
46
|
+
def tcp_flags; self.tcp_header.tcp_flags; end
|
47
|
+
def tcp_flags=(v); self.tcp_header.tcp_flags= v; end
|
48
|
+
end
|
48
49
|
end
|
@@ -1,323 +1,324 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
3
|
+
# TcpOption is the base class for all TCP options. Note that TcpOption#len
|
4
|
+
# returns the size of the entire option, while TcpOption#optlen is the struct
|
5
|
+
# for the TCP Option Length field.
|
6
|
+
#
|
7
|
+
# Subclassed options should set the correct TcpOption#kind by redefining
|
8
|
+
# initialize. They should also deal with various value types there by setting
|
9
|
+
# them explicitly with an accompanying StructFu#typecast for the setter.
|
10
|
+
#
|
11
|
+
# By default, values are presumed to be strings, unless they are Numeric, in
|
12
|
+
# which case a guess is made to the width of the Numeric based on the given
|
13
|
+
# optlen.
|
14
|
+
#
|
15
|
+
# Note that normally, optlen is /not/ enforced for directly setting values,
|
16
|
+
# so the user is perfectly capable of setting incorrect lengths.
|
17
|
+
class TcpOption < Struct.new(:kind, :optlen, :value)
|
18
|
+
|
19
|
+
include StructFu
|
20
|
+
|
21
|
+
def initialize(args={})
|
22
|
+
super(
|
23
|
+
Int8.new(args[:kind]),
|
24
|
+
Int8.new(args[:optlen])
|
25
|
+
)
|
26
|
+
if args[:value].kind_of? Numeric
|
27
|
+
self[:value] = case args[:optlen]
|
28
|
+
when 3; Int8.new(args[:value])
|
29
|
+
when 4; Int16.new(args[:value])
|
30
|
+
when 6; Int32.new(args[:value])
|
31
|
+
else; StructFu::String.new.read(args[:value])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
self[:value] = StructFu::String.new.read(args[:value])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the object in string form.
|
39
|
+
def to_s
|
40
|
+
self[:kind].to_s +
|
41
|
+
(self[:optlen].value.nil? ? nil : self[:optlen]).to_s +
|
42
|
+
(self[:value].nil? ? nil : self[:value]).to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
# Reads a string to populate the object.
|
46
|
+
def read(str)
|
47
|
+
force_binary(str)
|
48
|
+
return self if str.nil?
|
49
|
+
self[:kind].read(str[0,1])
|
50
|
+
if str[1,1]
|
51
|
+
self[:optlen].read(str[1,1])
|
52
|
+
if str[2,1] && optlen.value > 2
|
53
|
+
self[:value].read(str[2,optlen.value-2])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# The default decode for an unknown option. Known options should redefine this.
|
60
|
+
def decode
|
61
|
+
unk = "unk-#{self.kind.to_i}"
|
62
|
+
(self[:optlen].to_i > 2 && self[:value].to_s.size > 1) ? [unk,self[:value]].join(":") : unk
|
63
|
+
end
|
64
|
+
|
65
|
+
# Setter for the "kind" byte of this option.
|
66
|
+
def kind=(i); typecast i; end
|
67
|
+
# Setter for the "option length" byte for this option.
|
68
|
+
def optlen=(i); typecast i; end
|
69
|
+
|
70
|
+
# Setter for the value of this option.
|
71
|
+
def value=(i)
|
72
|
+
if i.kind_of? Numeric
|
73
|
+
typecast i
|
74
|
+
elsif i.respond_to? :to_s
|
75
|
+
self[:value] = i
|
76
|
+
else
|
77
|
+
self[:value] = ''
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Generally, encoding a value is going to be just a read. Some
|
82
|
+
# options will treat things a little differently; TS for example,
|
83
|
+
# takes two values and concatenates them.
|
84
|
+
def encode(str)
|
85
|
+
self[:value] = self.class.new(:value => str).value
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns true if this option has an optlen. Some don't.
|
89
|
+
def has_optlen?
|
90
|
+
(kind.value && kind.value < 2) ? false : true
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns true if this option has a value. Some don't.
|
94
|
+
def has_value?
|
95
|
+
(value.respond_to? :to_s && value.to_s.size > 0) ? false : true
|
96
|
+
end
|
97
|
+
|
98
|
+
# End of Line option. Usually used to terminate a string of options.
|
99
|
+
#
|
100
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option000.htm
|
101
|
+
class EOL < TcpOption
|
102
|
+
def initialize(args={})
|
103
|
+
super(
|
104
|
+
args.merge(:kind => 0)
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def decode
|
109
|
+
"EOL"
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
# No Operation option. Usually used to pad out options to fit a 4-byte alignment.
|
115
|
+
#
|
116
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option001.htm
|
117
|
+
class NOP < TcpOption
|
118
|
+
def initialize(args={})
|
119
|
+
super(
|
120
|
+
args.merge(:kind => 1)
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def decode
|
125
|
+
"NOP"
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
# Maximum Segment Size option.
|
131
|
+
#
|
132
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option002.htm
|
133
|
+
class MSS < TcpOption
|
134
|
+
def initialize(args={})
|
135
|
+
super(
|
136
|
+
args.merge(:kind => 2,
|
137
|
+
:optlen => 4
|
138
|
+
)
|
139
|
+
)
|
140
|
+
self[:value] = Int16.new(args[:value])
|
141
|
+
end
|
142
|
+
|
143
|
+
def value=(i); typecast i; end
|
144
|
+
|
145
|
+
# MSS options with lengths other than 4 are malformed.
|
146
|
+
def decode
|
147
|
+
if self[:optlen].to_i == 4
|
148
|
+
"MSS:#{self[:value].to_i}"
|
149
|
+
else
|
150
|
+
"MSS-bad:#{self[:value]}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
# Window Size option.
|
157
|
+
#
|
158
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option003.htm
|
159
|
+
class WS < TcpOption
|
160
|
+
def initialize(args={})
|
161
|
+
super(
|
162
|
+
args.merge(:kind => 3,
|
163
|
+
:optlen => 3
|
164
|
+
)
|
165
|
+
)
|
166
|
+
self[:value] = Int8.new(args[:value])
|
167
|
+
end
|
168
|
+
|
169
|
+
def value=(i); typecast i; end
|
170
|
+
|
171
|
+
# WS options with lengths other than 3 are malformed.
|
172
|
+
def decode
|
173
|
+
if self[:optlen].to_i == 3
|
174
|
+
"WS:#{self[:value].to_i}"
|
175
|
+
else
|
176
|
+
"WS-bad:#{self[:value]}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
# Selective Acknowlegment OK option.
|
183
|
+
#
|
184
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option004.htm
|
185
|
+
class SACKOK < TcpOption
|
186
|
+
def initialize(args={})
|
187
|
+
super(
|
188
|
+
args.merge(:kind => 4,
|
189
|
+
:optlen => 2)
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
# SACKOK options with sizes other than 2 are malformed.
|
194
|
+
def decode
|
195
|
+
if self[:optlen].to_i == 2
|
196
|
+
"SACKOK"
|
197
|
+
else
|
198
|
+
"SACKOK-bad:#{self[:value]}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
# Selective Acknowledgement option.
|
205
|
+
#
|
206
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option004.htm
|
207
|
+
#
|
208
|
+
# Note that SACK always takes its optlen from the size of the string.
|
209
|
+
class SACK < TcpOption
|
210
|
+
def initialize(args={})
|
211
|
+
super(
|
212
|
+
args.merge(:kind => 5,
|
213
|
+
:optlen => ((args[:value] || "").size + 2)
|
214
|
+
)
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
def optlen=(i); typecast i; end
|
219
|
+
|
220
|
+
def value=(i)
|
221
|
+
self[:optlen] = Int8.new(i.to_s.size + 2)
|
222
|
+
self[:value] = StructFu::String.new(i)
|
223
|
+
end
|
224
|
+
|
225
|
+
def decode
|
226
|
+
"SACK:#{self[:value]}"
|
227
|
+
end
|
228
|
+
|
229
|
+
def encode(str)
|
230
|
+
temp_obj = self.class.new(:value => str)
|
231
|
+
self[:value] = temp_obj.value
|
232
|
+
self[:optlen] = temp_obj.optlen.value
|
233
|
+
self
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
# Echo option.
|
239
|
+
#
|
240
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option006.htm
|
241
|
+
class ECHO < TcpOption
|
242
|
+
def initialize(args={})
|
243
|
+
super(
|
244
|
+
args.merge(:kind => 6,
|
245
|
+
:optlen => 6
|
246
|
+
)
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
250
|
+
# ECHO options with lengths other than 6 are malformed.
|
251
|
+
def decode
|
252
|
+
if self[:optlen].to_i == 6
|
253
|
+
"ECHO:#{self[:value]}"
|
254
|
+
else
|
255
|
+
"ECHO-bad:#{self[:value]}"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
# Echo Reply option.
|
262
|
+
#
|
263
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option007.htm
|
264
|
+
class ECHOREPLY < TcpOption
|
265
|
+
def initialize(args={})
|
266
|
+
super(
|
267
|
+
args.merge(:kind => 7,
|
268
|
+
:optlen => 6
|
269
|
+
)
|
270
|
+
)
|
271
|
+
end
|
272
|
+
|
273
|
+
# ECHOREPLY options with lengths other than 6 are malformed.
|
274
|
+
def decode
|
275
|
+
if self[:optlen].to_i == 6
|
276
|
+
"ECHOREPLY:#{self[:value]}"
|
277
|
+
else
|
278
|
+
"ECHOREPLY-bad:#{self[:value]}"
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
# Timestamp option
|
285
|
+
#
|
286
|
+
# http://www.networksorcery.com/enp/protocol/tcp/option008.htm
|
287
|
+
class TS < TcpOption
|
288
|
+
def initialize(args={})
|
289
|
+
super(
|
290
|
+
args.merge(:kind => 8,
|
291
|
+
:optlen => 10
|
292
|
+
)
|
293
|
+
)
|
294
|
+
self[:value] = StructFu::String.new.read(args[:value] || "\x00" * 8)
|
295
|
+
end
|
296
|
+
|
297
|
+
# TS options with lengths other than 10 are malformed.
|
298
|
+
def decode
|
299
|
+
if self[:optlen].to_i == 10
|
300
|
+
val1,val2 = self[:value].unpack("NN")
|
301
|
+
"TS:#{val1};#{val2}"
|
302
|
+
else
|
303
|
+
"TS-bad:#{self[:value]}"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# TS options are in the format of "TS:[timestamp value];[timestamp secret]" Both
|
308
|
+
# should be written as decimal numbers.
|
309
|
+
def encode(str)
|
310
|
+
if str =~ /^([0-9]+);([0-9]+)$/
|
311
|
+
tsval,tsecr = str.split(";").map {|x| x.to_i}
|
312
|
+
if tsval <= 0xffffffff && tsecr <= 0xffffffff
|
313
|
+
self[:value] = StructFu::String.new([tsval,tsecr].pack("NN"))
|
314
|
+
else
|
315
|
+
self[:value] = StructFu::String.new(str)
|
316
|
+
end
|
317
|
+
else
|
318
|
+
self[:value] = StructFu::String.new(str)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
end
|
323
324
|
end
|