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,42 +1,43 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
# Implements the Explict Congestion Notification for TCPHeader.
|
4
|
+
#
|
5
|
+
# ==== Header Definition
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Fixnum (1 bit) :n
|
9
|
+
# Fixnum (1 bit) :c
|
10
|
+
# Fixnum (1 bit) :e
|
11
|
+
class TcpEcn < Struct.new(:n, :c, :e)
|
11
12
|
|
12
|
-
|
13
|
+
include StructFu
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def initialize(args={})
|
16
|
+
super(args[:n], args[:c], args[:e]) if args
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# Returns the TcpEcn field as an integer... even though it's going
|
20
|
+
# to be split across a byte boundary.
|
21
|
+
def to_i
|
22
|
+
(n.to_i << 2) + (c.to_i << 1) + e.to_i
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
25
|
+
# Reads a string to populate the object.
|
26
|
+
def read(str)
|
27
|
+
force_binary(str)
|
28
|
+
return self if str.nil? || str.size < 2
|
29
|
+
if 1.respond_to? :ord
|
30
|
+
byte1 = str[0].ord
|
31
|
+
byte2 = str[1].ord
|
32
|
+
else
|
33
|
+
byte1 = str[0]
|
34
|
+
byte2 = str[1]
|
35
|
+
end
|
36
|
+
self[:n] = byte1 & 0b00000001 == 0b00000001 ? 1 : 0
|
37
|
+
self[:c] = byte2 & 0b10000000 == 0b10000000 ? 1 : 0
|
38
|
+
self[:e] = byte2 & 0b01000000 == 0b01000000 ? 1 : 0
|
39
|
+
self
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
+
end
|
42
43
|
end
|
@@ -1,83 +1,84 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
# Implements flags for TCPHeader.
|
4
|
+
#
|
5
|
+
# ==== Header Definition
|
6
|
+
#
|
7
|
+
# Fixnum (1 bit) :urg
|
8
|
+
# Fixnum (1 bit) :ack
|
9
|
+
# Fixnum (1 bit) :psh
|
10
|
+
# Fixnum (1 bit) :rst
|
11
|
+
# Fixnum (1 bit) :syn
|
12
|
+
# Fixnum (1 bit) :fin
|
13
|
+
#
|
14
|
+
# Flags can typically be set by setting them either to 1 or 0, or to true or false.
|
15
|
+
class TcpFlags < Struct.new(:urg, :ack, :psh, :rst, :syn, :fin)
|
15
16
|
|
16
|
-
|
17
|
+
include StructFu
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
19
|
+
def initialize(args={})
|
20
|
+
# This technique attemts to ensure that flags are always 0 (off)
|
21
|
+
# or 1 (on). Statements like nil and false shouldn't be lurking in here.
|
22
|
+
if args.nil? || args.size.zero?
|
23
|
+
super( 0, 0, 0, 0, 0, 0)
|
24
|
+
else
|
25
|
+
super(
|
26
|
+
(args[:urg] ? 1 : 0),
|
27
|
+
(args[:ack] ? 1 : 0),
|
28
|
+
(args[:psh] ? 1 : 0),
|
29
|
+
(args[:rst] ? 1 : 0),
|
30
|
+
(args[:syn] ? 1 : 0),
|
31
|
+
(args[:fin] ? 1 : 0)
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
# Returns the TcpFlags as an integer.
|
37
|
+
# Also not a great candidate for to_s due to the short bitspace.
|
38
|
+
def to_i
|
39
|
+
(urg.to_i << 5) + (ack.to_i << 4) + (psh.to_i << 3) +
|
40
|
+
(rst.to_i << 2) + (syn.to_i << 1) + fin.to_i
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
# Helper to determine if this flag is a 1 or a 0.
|
44
|
+
def zero_or_one(i=0)
|
45
|
+
if i == 0 || i == false || i == nil
|
46
|
+
0
|
47
|
+
else
|
48
|
+
1
|
49
|
+
end
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
52
|
+
# Setter for the Urgent flag.
|
53
|
+
def urg=(i); self[:urg] = zero_or_one(i); end
|
54
|
+
# Setter for the Acknowlege flag.
|
55
|
+
def ack=(i); self[:ack] = zero_or_one(i); end
|
56
|
+
# Setter for the Push flag.
|
57
|
+
def psh=(i); self[:psh] = zero_or_one(i); end
|
58
|
+
# Setter for the Reset flag.
|
59
|
+
def rst=(i); self[:rst] = zero_or_one(i); end
|
60
|
+
# Setter for the Synchronize flag.
|
61
|
+
def syn=(i); self[:syn] = zero_or_one(i); end
|
62
|
+
# Setter for the Finish flag.
|
63
|
+
def fin=(i); self[:fin] = zero_or_one(i); end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
65
|
+
# Reads a string to populate the object.
|
66
|
+
def read(str)
|
67
|
+
force_binary(str)
|
68
|
+
return self if str.nil?
|
69
|
+
if 1.respond_to? :ord
|
70
|
+
byte = str[0].ord
|
71
|
+
else
|
72
|
+
byte = str[0]
|
73
|
+
end
|
74
|
+
self[:urg] = byte & 0b00100000 == 0b00100000 ? 1 : 0
|
75
|
+
self[:ack] = byte & 0b00010000 == 0b00010000 ? 1 : 0
|
76
|
+
self[:psh] = byte & 0b00001000 == 0b00001000 ? 1 : 0
|
77
|
+
self[:rst] = byte & 0b00000100 == 0b00000100 ? 1 : 0
|
78
|
+
self[:syn] = byte & 0b00000010 == 0b00000010 ? 1 : 0
|
79
|
+
self[:fin] = byte & 0b00000001 == 0b00000001 ? 1 : 0
|
80
|
+
self
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
+
end
|
83
84
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
require 'packetfu/protos/tcp/reserved'
|
2
3
|
require 'packetfu/protos/tcp/hlen'
|
3
4
|
require 'packetfu/protos/tcp/ecn'
|
@@ -7,301 +8,301 @@ require 'packetfu/protos/tcp/options'
|
|
7
8
|
|
8
9
|
|
9
10
|
module PacketFu
|
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
|
-
|
11
|
+
# TCPHeader is a complete TCP struct, used in TCPPacket. Most IP traffic is TCP-based, by
|
12
|
+
# volume.
|
13
|
+
#
|
14
|
+
# For more on TCP packets, see http://www.networksorcery.com/enp/protocol/tcp.htm
|
15
|
+
#
|
16
|
+
# ==== Header Definition
|
17
|
+
#
|
18
|
+
# Int16 :tcp_src Default: random
|
19
|
+
# Int16 :tcp_dst
|
20
|
+
# Int32 :tcp_seq Default: random
|
21
|
+
# Int32 :tcp_ack
|
22
|
+
# TcpHlen :tcp_hlen Default: 5 # Must recalc as options are set.
|
23
|
+
# TcpReserved :tcp_reserved Default: 0
|
24
|
+
# TcpEcn :tcp_ecn
|
25
|
+
# TcpFlags :tcp_flags
|
26
|
+
# Int16 :tcp_win, Default: 0 # WinXP's default syn packet
|
27
|
+
# Int16 :tcp_sum, Default: calculated # Must set this upon generation.
|
28
|
+
# Int16 :tcp_urg
|
29
|
+
# TcpOptions :tcp_opts
|
30
|
+
# String :body
|
31
|
+
#
|
32
|
+
# See also TcpHlen, TcpReserved, TcpEcn, TcpFlags, TcpOpts
|
33
|
+
class TCPHeader < Struct.new(:tcp_src, :tcp_dst,
|
34
|
+
:tcp_seq,
|
35
|
+
:tcp_ack,
|
36
|
+
:tcp_hlen, :tcp_reserved, :tcp_ecn, :tcp_flags, :tcp_win,
|
37
|
+
:tcp_sum, :tcp_urg,
|
38
|
+
:tcp_opts, :body)
|
39
|
+
include StructFu
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
def initialize(args={})
|
42
|
+
@random_seq = rand(0xffffffff)
|
43
|
+
@random_src = rand_port
|
44
|
+
super(
|
45
|
+
Int16.new(args[:tcp_src] || tcp_calc_src),
|
46
|
+
Int16.new(args[:tcp_dst]),
|
47
|
+
Int32.new(args[:tcp_seq] || tcp_calc_seq),
|
48
|
+
Int32.new(args[:tcp_ack]),
|
49
|
+
TcpHlen.new(:hlen => (args[:tcp_hlen] || 5)),
|
50
|
+
TcpReserved.new(args[:tcp_reserved] || 0),
|
51
|
+
TcpEcn.new(args[:tcp_ecn]),
|
52
|
+
TcpFlags.new(args[:tcp_flags]),
|
53
|
+
Int16.new(args[:tcp_win] || 0x4000),
|
54
|
+
Int16.new(args[:tcp_sum] || 0),
|
55
|
+
Int16.new(args[:tcp_urg]),
|
56
|
+
TcpOptions.new.read(args[:tcp_opts]),
|
57
|
+
StructFu::String.new.read(args[:body])
|
58
|
+
)
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
+
attr_accessor :flavor
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
63
|
+
# Helper function to create the string for Hlen, Reserved, ECN, and Flags.
|
64
|
+
def bits_to_s
|
65
|
+
bytes = []
|
66
|
+
bytes[0] = (self[:tcp_hlen].to_i << 4) +
|
67
|
+
(self[:tcp_reserved].to_i << 1) +
|
68
|
+
self[:tcp_ecn].n.to_i
|
69
|
+
bytes[1] = (self[:tcp_ecn].c.to_i << 7) +
|
70
|
+
(self[:tcp_ecn].e.to_i << 6) +
|
71
|
+
self[:tcp_flags].to_i
|
72
|
+
bytes.pack("CC")
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
75
|
+
# Returns the object in string form.
|
76
|
+
def to_s
|
77
|
+
hdr = self.to_a.map do |x|
|
78
|
+
if x.kind_of? TcpHlen
|
79
|
+
bits_to_s
|
80
|
+
elsif x.kind_of? TcpReserved
|
81
|
+
next
|
82
|
+
elsif x.kind_of? TcpEcn
|
83
|
+
next
|
84
|
+
elsif x.kind_of? TcpFlags
|
85
|
+
next
|
86
|
+
else
|
87
|
+
x.to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
hdr.flatten.join
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
93
|
+
# Reads a string to populate the object.
|
94
|
+
def read(str)
|
95
|
+
force_binary(str)
|
96
|
+
return self if str.nil?
|
97
|
+
self[:tcp_src].read(str[0,2])
|
98
|
+
self[:tcp_dst].read(str[2,2])
|
99
|
+
self[:tcp_seq].read(str[4,4])
|
100
|
+
self[:tcp_ack].read(str[8,4])
|
101
|
+
self[:tcp_hlen].read(str[12,1])
|
102
|
+
self[:tcp_reserved].read(str[12,1])
|
103
|
+
self[:tcp_ecn].read(str[12,2])
|
104
|
+
self[:tcp_flags].read(str[13,1])
|
105
|
+
self[:tcp_win].read(str[14,2])
|
106
|
+
self[:tcp_sum].read(str[16,2])
|
107
|
+
self[:tcp_urg].read(str[18,2])
|
108
|
+
self[:tcp_opts].read(str[20,((self[:tcp_hlen].to_i * 4) - 20)])
|
109
|
+
self[:body].read(str[(self[:tcp_hlen].to_i * 4),str.size])
|
110
|
+
self
|
111
|
+
end
|
111
112
|
|
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
|
-
|
113
|
+
# Setter for the TCP source port.
|
114
|
+
def tcp_src=(i); typecast i; end
|
115
|
+
# Getter for the TCP source port.
|
116
|
+
def tcp_src; self[:tcp_src].to_i; end
|
117
|
+
# Setter for the TCP destination port.
|
118
|
+
def tcp_dst=(i); typecast i; end
|
119
|
+
# Getter for the TCP destination port.
|
120
|
+
def tcp_dst; self[:tcp_dst].to_i; end
|
121
|
+
# Setter for the TCP sequence number.
|
122
|
+
def tcp_seq=(i); typecast i; end
|
123
|
+
# Getter for the TCP sequence number.
|
124
|
+
def tcp_seq; self[:tcp_seq].to_i; end
|
125
|
+
# Setter for the TCP ackowlegement number.
|
126
|
+
def tcp_ack=(i); typecast i; end
|
127
|
+
# Getter for the TCP ackowlegement number.
|
128
|
+
def tcp_ack; self[:tcp_ack].to_i; end
|
129
|
+
# Setter for the TCP window size number.
|
130
|
+
def tcp_win=(i); typecast i; end
|
131
|
+
# Getter for the TCP window size number.
|
132
|
+
def tcp_win; self[:tcp_win].to_i; end
|
133
|
+
# Setter for the TCP checksum.
|
134
|
+
def tcp_sum=(i); typecast i; end
|
135
|
+
# Getter for the TCP checksum.
|
136
|
+
def tcp_sum; self[:tcp_sum].to_i; end
|
137
|
+
# Setter for the TCP urgent field.
|
138
|
+
def tcp_urg=(i); typecast i; end
|
139
|
+
# Getter for the TCP urgent field.
|
140
|
+
def tcp_urg; self[:tcp_urg].to_i; end
|
140
141
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
142
|
+
# Getter for the TCP Header Length value.
|
143
|
+
def tcp_hlen; self[:tcp_hlen].to_i; end
|
144
|
+
# Setter for the TCP Header Length value. Can take
|
145
|
+
# either a string or an integer. Note that if it's
|
146
|
+
# a string, the top four bits are used.
|
147
|
+
def tcp_hlen=(i)
|
148
|
+
case i
|
149
|
+
when PacketFu::TcpHlen
|
150
|
+
self[:tcp_hlen] = i
|
151
|
+
when Numeric
|
152
|
+
self[:tcp_hlen] = TcpHlen.new(:hlen => i.to_i)
|
153
|
+
else
|
154
|
+
self[:tcp_hlen].read(i)
|
155
|
+
end
|
156
|
+
end
|
156
157
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
158
|
+
# Getter for the TCP Reserved field.
|
159
|
+
def tcp_reserved; self[:tcp_reserved].to_i; end
|
160
|
+
# Setter for the TCP Reserved field.
|
161
|
+
def tcp_reserved=(i)
|
162
|
+
case i
|
163
|
+
when PacketFu::TcpReserved
|
164
|
+
self[:tcp_reserved]=i
|
165
|
+
when Numeric
|
166
|
+
args = {}
|
167
|
+
args[:r1] = (i & 0b100) >> 2
|
168
|
+
args[:r2] = (i & 0b010) >> 1
|
169
|
+
args[:r3] = (i & 0b001)
|
170
|
+
self[:tcp_reserved] = TcpReserved.new(args)
|
171
|
+
else
|
172
|
+
self[:tcp_reserved].read(i)
|
173
|
+
end
|
174
|
+
end
|
174
175
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
176
|
+
# Getter for the ECN bits.
|
177
|
+
def tcp_ecn; self[:tcp_ecn].to_i; end
|
178
|
+
# Setter for the ECN bits.
|
179
|
+
def tcp_ecn=(i)
|
180
|
+
case i
|
181
|
+
when PacketFu::TcpEcn
|
182
|
+
self[:tcp_ecn]=i
|
183
|
+
when Numeric
|
184
|
+
args = {}
|
185
|
+
args[:n] = (i & 0b100) >> 2
|
186
|
+
args[:c] = (i & 0b010) >> 1
|
187
|
+
args[:e] = (i & 0b001)
|
188
|
+
self[:tcp_ecn] = TcpEcn.new(args)
|
189
|
+
else
|
190
|
+
self[:tcp_ecn].read(i)
|
191
|
+
end
|
192
|
+
end
|
192
193
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
194
|
+
# Getter for TCP Options.
|
195
|
+
def tcp_opts; self[:tcp_opts].to_s; end
|
196
|
+
# Setter for TCP Options.
|
197
|
+
def tcp_opts=(i)
|
198
|
+
case i
|
199
|
+
when PacketFu::TcpOptions
|
200
|
+
self[:tcp_opts]=i
|
201
|
+
else
|
202
|
+
self[:tcp_opts].read(i)
|
203
|
+
end
|
204
|
+
end
|
204
205
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
206
|
+
# Resets the sequence number to a new random number.
|
207
|
+
def tcp_calc_seq; @random_seq; end
|
208
|
+
# Resets the source port to a new random number.
|
209
|
+
def tcp_calc_src; @random_src; end
|
209
210
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
211
|
+
# Returns the actual length of the TCP options.
|
212
|
+
def tcp_opts_len
|
213
|
+
self[:tcp_opts].to_s.size
|
214
|
+
end
|
214
215
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
216
|
+
# Sets and returns the true length of the TCP Header.
|
217
|
+
# TODO: Think about making all the option stuff safer.
|
218
|
+
def tcp_calc_hlen
|
219
|
+
self[:tcp_hlen] = TcpHlen.new(:hlen => ((20 + tcp_opts_len) / 4))
|
220
|
+
end
|
220
221
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
222
|
+
# Generates a random high port. This is affected by packet flavor.
|
223
|
+
def rand_port
|
224
|
+
rand(0xffff - 1025) + 1025
|
225
|
+
end
|
225
226
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
227
|
+
# Gets a more readable option list.
|
228
|
+
def tcp_options
|
229
|
+
self[:tcp_opts].decode
|
230
|
+
end
|
230
231
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
232
|
+
# Gets a more readable flags list
|
233
|
+
def tcp_flags_dotmap
|
234
|
+
dotmap = tcp_flags.members.map do |flag|
|
235
|
+
status = self.tcp_flags.send flag
|
236
|
+
status == 0 ? "." : flag.to_s.upcase[0].chr
|
237
|
+
end
|
238
|
+
dotmap.join
|
239
|
+
end
|
239
240
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
241
|
+
# Sets a more readable option list.
|
242
|
+
def tcp_options=(arg)
|
243
|
+
self[:tcp_opts].encode arg
|
244
|
+
end
|
244
245
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
246
|
+
# Equivalent to tcp_src.
|
247
|
+
def tcp_sport
|
248
|
+
self.tcp_src.to_i
|
249
|
+
end
|
249
250
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
251
|
+
# Equivalent to tcp_src=.
|
252
|
+
def tcp_sport=(arg)
|
253
|
+
self.tcp_src=(arg)
|
254
|
+
end
|
254
255
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
256
|
+
# Equivalent to tcp_dst.
|
257
|
+
def tcp_dport
|
258
|
+
self.tcp_dst.to_i
|
259
|
+
end
|
260
|
+
|
261
|
+
# Equivalent to tcp_dst=.
|
262
|
+
def tcp_dport=(arg)
|
263
|
+
self.tcp_dst=(arg)
|
264
|
+
end
|
264
265
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
266
|
+
# Recalculates calculated fields for TCP (except checksum which is at the Packet level).
|
267
|
+
def tcp_recalc(arg=:all)
|
268
|
+
case arg
|
269
|
+
when :tcp_hlen
|
270
|
+
tcp_calc_hlen
|
271
|
+
when :tcp_src
|
272
|
+
@random_tcp_src = rand_port
|
273
|
+
when :tcp_sport
|
274
|
+
@random_tcp_src = rand_port
|
275
|
+
when :tcp_seq
|
276
|
+
@random_tcp_seq = rand(0xffffffff)
|
277
|
+
when :all
|
278
|
+
tcp_calc_hlen
|
279
|
+
@random_tcp_src = rand_port
|
280
|
+
@random_tcp_seq = rand(0xffffffff)
|
281
|
+
else
|
282
|
+
raise ArgumentError, "No such field `#{arg}'"
|
283
|
+
end
|
284
|
+
end
|
284
285
|
|
285
|
-
|
286
|
+
# Readability aliases
|
286
287
|
|
287
|
-
|
288
|
+
alias :tcp_flags_readable :tcp_flags_dotmap
|
288
289
|
|
289
|
-
|
290
|
-
|
291
|
-
|
290
|
+
def tcp_ack_readable
|
291
|
+
"0x%08x" % tcp_ack
|
292
|
+
end
|
292
293
|
|
293
|
-
|
294
|
-
|
295
|
-
|
294
|
+
def tcp_seq_readable
|
295
|
+
"0x%08x" % tcp_seq
|
296
|
+
end
|
296
297
|
|
297
|
-
|
298
|
-
|
299
|
-
|
298
|
+
def tcp_sum_readable
|
299
|
+
"0x%04x" % tcp_sum
|
300
|
+
end
|
300
301
|
|
301
|
-
|
302
|
-
|
303
|
-
|
302
|
+
def tcp_opts_readable
|
303
|
+
tcp_options
|
304
|
+
end
|
304
305
|
|
305
|
-
|
306
|
+
end
|
306
307
|
|
307
308
|
end
|