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.
Files changed (84) hide show
  1. data/README.rdoc +11 -12
  2. data/bench/octets.rb +9 -9
  3. data/examples/100kpackets.rb +13 -12
  4. data/examples/ackscan.rb +17 -16
  5. data/examples/arp.rb +36 -35
  6. data/examples/arphood.rb +37 -36
  7. data/examples/dissect_thinger.rb +7 -6
  8. data/examples/ethernet.rb +1 -0
  9. data/examples/examples.rb +1 -0
  10. data/examples/ifconfig.rb +1 -0
  11. data/examples/new-simple-stats.rb +24 -23
  12. data/examples/packetfu-shell.rb +26 -25
  13. data/examples/simple-sniffer.rb +10 -9
  14. data/examples/simple-stats.rb +24 -23
  15. data/examples/slammer.rb +4 -3
  16. data/lib/packetfu.rb +128 -127
  17. data/lib/packetfu/capture.rb +170 -169
  18. data/lib/packetfu/config.rb +53 -52
  19. data/lib/packetfu/inject.rb +57 -56
  20. data/lib/packetfu/packet.rb +529 -528
  21. data/lib/packetfu/pcap.rb +580 -579
  22. data/lib/packetfu/protos/arp.rb +91 -90
  23. data/lib/packetfu/protos/arp/header.rb +159 -158
  24. data/lib/packetfu/protos/arp/mixin.rb +37 -36
  25. data/lib/packetfu/protos/eth.rb +45 -44
  26. data/lib/packetfu/protos/eth/header.rb +244 -243
  27. data/lib/packetfu/protos/eth/mixin.rb +4 -3
  28. data/lib/packetfu/protos/hsrp.rb +70 -69
  29. data/lib/packetfu/protos/hsrp/header.rb +108 -107
  30. data/lib/packetfu/protos/hsrp/mixin.rb +30 -29
  31. data/lib/packetfu/protos/icmp.rb +72 -71
  32. data/lib/packetfu/protos/icmp/header.rb +83 -82
  33. data/lib/packetfu/protos/icmp/mixin.rb +15 -14
  34. data/lib/packetfu/protos/invalid.rb +50 -49
  35. data/lib/packetfu/protos/ip.rb +70 -69
  36. data/lib/packetfu/protos/ip/header.rb +292 -291
  37. data/lib/packetfu/protos/ip/mixin.rb +41 -40
  38. data/lib/packetfu/protos/ipv6.rb +51 -50
  39. data/lib/packetfu/protos/ipv6/header.rb +189 -188
  40. data/lib/packetfu/protos/ipv6/mixin.rb +30 -29
  41. data/lib/packetfu/protos/lldp.rb +3 -1
  42. data/lib/packetfu/protos/lldp/header.rb +1 -0
  43. data/lib/packetfu/protos/lldp/mixin.rb +1 -0
  44. data/lib/packetfu/protos/tcp.rb +177 -176
  45. data/lib/packetfu/protos/tcp/ecn.rb +36 -35
  46. data/lib/packetfu/protos/tcp/flags.rb +75 -74
  47. data/lib/packetfu/protos/tcp/header.rb +269 -268
  48. data/lib/packetfu/protos/tcp/hlen.rb +33 -32
  49. data/lib/packetfu/protos/tcp/mixin.rb +47 -46
  50. data/lib/packetfu/protos/tcp/option.rb +322 -321
  51. data/lib/packetfu/protos/tcp/options.rb +96 -95
  52. data/lib/packetfu/protos/tcp/reserved.rb +36 -35
  53. data/lib/packetfu/protos/udp.rb +117 -116
  54. data/lib/packetfu/protos/udp/header.rb +92 -91
  55. data/lib/packetfu/protos/udp/mixin.rb +4 -3
  56. data/lib/packetfu/structfu.rb +281 -280
  57. data/lib/packetfu/utils.rb +211 -208
  58. data/lib/packetfu/version.rb +42 -41
  59. data/packetfu.gemspec +1 -1
  60. data/spec/ethpacket_spec.rb +48 -48
  61. data/spec/packet_spec.rb +57 -57
  62. data/spec/packet_subclasses_spec.rb +8 -8
  63. data/spec/packetfu_spec.rb +59 -59
  64. data/spec/structfu_spec.rb +268 -268
  65. data/spec/tcp_spec.rb +75 -75
  66. data/test/all_tests.rb +13 -13
  67. data/test/func_lldp.rb +3 -3
  68. data/test/ptest.rb +2 -2
  69. data/test/test_arp.rb +116 -116
  70. data/test/test_capture.rb +45 -45
  71. data/test/test_eth.rb +68 -68
  72. data/test/test_hsrp.rb +9 -9
  73. data/test/test_icmp.rb +52 -52
  74. data/test/test_inject.rb +18 -18
  75. data/test/test_invalid.rb +16 -16
  76. data/test/test_ip.rb +36 -36
  77. data/test/test_ip6.rb +48 -48
  78. data/test/test_octets.rb +21 -21
  79. data/test/test_packet.rb +154 -154
  80. data/test/test_pcap.rb +170 -170
  81. data/test/test_structfu.rb +97 -97
  82. data/test/test_tcp.rb +320 -320
  83. data/test/test_udp.rb +76 -76
  84. metadata +2 -2
@@ -1,31 +1,32 @@
1
+ # -*- coding: binary -*-
1
2
  module PacketFu
2
- # This Mixin simplifies access to the IPv6Headers. Mix this in with your
3
- # packet interface, and it will add methods that essentially delegate to
4
- # the 'ipv6_header' method (assuming that it is a IPv6Header object)
5
- module IPv6HeaderMixin
6
- def ipv6_v=(v); self.ipv6_header.ipv6_v= v; end
7
- def ipv6_v; self.ipv6_header.ipv6_v; end
8
- def ipv6_class=(v); self.ipv6_header.ipv6_class= v; end
9
- def ipv6_class; self.ipv6_header.ipv6_class; end
10
- def ipv6_label=(v); self.ipv6_header.ipv6_label= v; end
11
- def ipv6_label; self.ipv6_header.ipv6_label; end
12
- def ipv6_len=(v); self.ipv6_header.ipv6_len= v; end
13
- def ipv6_len; self.ipv6_header.ipv6_len; end
14
- def ipv6_next=(v); self.ipv6_header.ipv6_next= v; end
15
- def ipv6_next; self.ipv6_header.ipv6_next; end
16
- def ipv6_hop=(v); self.ipv6_header.ipv6_hop= v; end
17
- def ipv6_hop; self.ipv6_header.ipv6_hop; end
18
- def ipv6_src=(v); self.ipv6_header.ipv6_src= v; end
19
- def ipv6_src; self.ipv6_header.ipv6_src; end
20
- def ipv6_dst=(v); self.ipv6_header.ipv6_dst= v; end
21
- def ipv6_dst; self.ipv6_header.ipv6_dst; end
22
- def ipv6_calc_len; self.ipv6_header.ipv6_calc_len; end
23
- def ipv6_recalc(*v); self.ipv6_header.ipv6_recalc(*v); end
24
- def ipv6_saddr; self.ipv6_header.ipv6_saddr; end
25
- def ipv6_saddr=(v); self.ipv6_header.ipv6_saddr= v; end
26
- def ipv6_daddr; self.ipv6_header.ipv6_daddr; end
27
- def ipv6_daddr=(v); self.ipv6_header.ipv6_daddr= v; end
28
- def ipv6_src_readable; self.ipv6_header.ipv6_src_readable; end
29
- def ipv6_dst_readable; self.ipv6_header.ipv6_dst_readable; end
30
- end
3
+ # This Mixin simplifies access to the IPv6Headers. Mix this in with your
4
+ # packet interface, and it will add methods that essentially delegate to
5
+ # the 'ipv6_header' method (assuming that it is a IPv6Header object)
6
+ module IPv6HeaderMixin
7
+ def ipv6_v=(v); self.ipv6_header.ipv6_v= v; end
8
+ def ipv6_v; self.ipv6_header.ipv6_v; end
9
+ def ipv6_class=(v); self.ipv6_header.ipv6_class= v; end
10
+ def ipv6_class; self.ipv6_header.ipv6_class; end
11
+ def ipv6_label=(v); self.ipv6_header.ipv6_label= v; end
12
+ def ipv6_label; self.ipv6_header.ipv6_label; end
13
+ def ipv6_len=(v); self.ipv6_header.ipv6_len= v; end
14
+ def ipv6_len; self.ipv6_header.ipv6_len; end
15
+ def ipv6_next=(v); self.ipv6_header.ipv6_next= v; end
16
+ def ipv6_next; self.ipv6_header.ipv6_next; end
17
+ def ipv6_hop=(v); self.ipv6_header.ipv6_hop= v; end
18
+ def ipv6_hop; self.ipv6_header.ipv6_hop; end
19
+ def ipv6_src=(v); self.ipv6_header.ipv6_src= v; end
20
+ def ipv6_src; self.ipv6_header.ipv6_src; end
21
+ def ipv6_dst=(v); self.ipv6_header.ipv6_dst= v; end
22
+ def ipv6_dst; self.ipv6_header.ipv6_dst; end
23
+ def ipv6_calc_len; self.ipv6_header.ipv6_calc_len; end
24
+ def ipv6_recalc(*v); self.ipv6_header.ipv6_recalc(*v); end
25
+ def ipv6_saddr; self.ipv6_header.ipv6_saddr; end
26
+ def ipv6_saddr=(v); self.ipv6_header.ipv6_saddr= v; end
27
+ def ipv6_daddr; self.ipv6_header.ipv6_daddr; end
28
+ def ipv6_daddr=(v); self.ipv6_header.ipv6_daddr= v; end
29
+ def ipv6_src_readable; self.ipv6_header.ipv6_src_readable; end
30
+ def ipv6_dst_readable; self.ipv6_header.ipv6_dst_readable; end
31
+ end
31
32
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  require 'packetfu/protos/eth/header'
2
3
  require 'packetfu/protos/eth/mixin'
3
4
 
@@ -7,6 +8,7 @@ require 'packetfu/protos/lldp/mixin'
7
8
  module PacketFu
8
9
 
9
10
  class LLDPPacket < Packet
11
+ MAGIC = Regexp.new("^\x01\x80\xc2\x00\x00[\x0e\x03\x00]", nil, "n")
10
12
  include ::PacketFu::EthHeaderMixin
11
13
  include ::PacketFu::LLDPHeaderMixin
12
14
 
@@ -16,7 +18,7 @@ module PacketFu
16
18
  return false unless EthPacket.can_parse? str
17
19
  return false unless str.size >= 6
18
20
  return false unless str[12,2] == "\x88\xcc"
19
- return false unless str =~ /^\x01\x80\xc2\x00\x00[\x0e\x03\x00]/
21
+ return false unless str =~ MAGIC
20
22
  true
21
23
  end
22
24
 
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  module PacketFu
2
3
  # LLDPHeader is a complete LLDP struct, used in LLDPPacket.
3
4
 
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  module PacketFu
2
3
  # This Mixin simplifies access to the LLDPHeaders. Mix this in with your
3
4
  # packet interface, and it will add methods that essentially delegate to
@@ -1,3 +1,4 @@
1
+ # -*- coding: binary -*-
1
2
  require 'packetfu/protos/eth/header'
2
3
  require 'packetfu/protos/eth/mixin'
3
4
 
@@ -8,194 +9,194 @@ require 'packetfu/protos/ip/header'
8
9
  require 'packetfu/protos/ip/mixin'
9
10
 
10
11
  module PacketFu
11
- # TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
12
- #
13
- # == Example
14
- #
12
+ # TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
13
+ #
14
+ # == Example
15
+ #
15
16
  # tcp_pkt = PacketFu::TCPPacket.new
16
17
  # tcp_pkt.tcp_flags.syn=1
17
18
  # tcp_pkt.tcp_dst=80
18
19
  # tcp_pkt.tcp_win=5840
19
20
  # tcp_pkt.tcp_options="mss:1460,sack.ok,ts:#{rand(0xffffffff)};0,nop,ws:7"
20
- #
21
+ #
21
22
  # tcp_pkt.ip_saddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
22
23
  # tcp_pkt.ip_daddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
23
- #
24
+ #
24
25
  # tcp_pkt.recalc
25
26
  # tcp_pkt.to_f('/tmp/tcp.pcap')
26
- #
27
- # == Parameters
28
- # :eth
29
- # A pre-generated EthHeader object.
30
- # :ip
31
- # A pre-generated IPHeader object.
32
- # :flavor
33
- # TODO: Sets the "flavor" of the TCP packet. This will include TCP options and the initial window
34
- # size, per stack. There is a lot of variety here, and it's one of the most useful methods to
35
- # remotely fingerprint devices. :flavor will span both ip and tcp for consistency.
36
- # :type
37
- # TODO: Set up particular types of packets (syn, psh_ack, rst, etc). This can change the initial flavor.
38
- # :config
39
- # A hash of return address details, often the output of Utils.whoami?
40
- class TCPPacket < Packet
27
+ #
28
+ # == Parameters
29
+ # :eth
30
+ # A pre-generated EthHeader object.
31
+ # :ip
32
+ # A pre-generated IPHeader object.
33
+ # :flavor
34
+ # TODO: Sets the "flavor" of the TCP packet. This will include TCP options and the initial window
35
+ # size, per stack. There is a lot of variety here, and it's one of the most useful methods to
36
+ # remotely fingerprint devices. :flavor will span both ip and tcp for consistency.
37
+ # :type
38
+ # TODO: Set up particular types of packets (syn, psh_ack, rst, etc). This can change the initial flavor.
39
+ # :config
40
+ # A hash of return address details, often the output of Utils.whoami?
41
+ class TCPPacket < Packet
41
42
  include ::PacketFu::EthHeaderMixin
42
43
  include ::PacketFu::IPHeaderMixin
43
44
  include ::PacketFu::TCPHeaderMixin
44
45
 
45
- attr_accessor :eth_header, :ip_header, :tcp_header
46
-
47
- def self.can_parse?(str)
48
- return false unless str.size >= 54
49
- return false unless EthPacket.can_parse? str
50
- return false unless IPPacket.can_parse? str
51
- return false unless str[23,1] == "\x06"
52
- return true
53
- end
54
-
55
- def read(str=nil, args={})
56
- raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
57
- @eth_header.read(str)
58
-
59
- # Strip off any extra data, if we are asked to do so.
60
- if args[:strip]
61
- tcp_body_len = self.ip_len - self.ip_hlen - (self.tcp_hlen * 4)
62
- @tcp_header.body.read(@tcp_header.body.to_s[0,tcp_body_len])
63
- end
64
- super(args)
65
- self
66
- end
67
-
68
- def initialize(args={})
69
- @eth_header = (args[:eth] || EthHeader.new)
70
- @ip_header = (args[:ip] || IPHeader.new)
71
- @tcp_header = (args[:tcp] || TCPHeader.new)
72
- @tcp_header.flavor = args[:flavor].to_s.downcase
73
-
74
- @ip_header.body = @tcp_header
75
- @eth_header.body = @ip_header
76
- @headers = [@eth_header, @ip_header, @tcp_header]
77
-
78
- @ip_header.ip_proto=0x06
79
- super
80
- if args[:flavor]
81
- tcp_calc_flavor(@tcp_header.flavor)
82
- else
83
- tcp_calc_sum
84
- end
85
- end
86
-
87
- # Sets the correct flavor for TCP Packets. Recognized flavors are:
88
- # windows, linux, freebsd
89
- def tcp_calc_flavor(str)
90
- ts_val = Time.now.to_i + rand(0x4fffffff)
91
- ts_sec = rand(0xffffff)
92
- case @tcp_header.flavor = str.to_s.downcase
93
- when "windows" # WinXP's default syn
94
- @tcp_header.tcp_win = 0x4000
95
- @tcp_header.tcp_options="MSS:1460,NOP,NOP,SACKOK"
96
- @tcp_header.tcp_src = rand(5000 - 1026) + 1026
97
- @ip_header.ip_ttl = 64
98
- when "linux" # Ubuntu Linux 2.6.24-19-generic default syn
99
- @tcp_header.tcp_win = 5840
100
- @tcp_header.tcp_options="MSS:1460,SACKOK,TS:#{ts_val};0,NOP,WS:7"
101
- @tcp_header.tcp_src = rand(61_000 - 32_000) + 32_000
102
- @ip_header.ip_ttl = 64
103
- when "freebsd" # Freebsd
104
- @tcp_header.tcp_win = 0xffff
105
- @tcp_header.tcp_options="MSS:1460,NOP,WS:3,NOP,NOP,TS:#{ts_val};#{ts_sec},SACKOK,EOL,EOL"
106
- @ip_header.ip_ttl = 64
107
- else
108
- @tcp_header.tcp_options="MSS:1460,NOP,NOP,SACKOK"
109
- end
110
- tcp_calc_sum
111
- end
112
-
113
- # tcp_calc_sum() computes the TCP checksum, and is called upon intialization. It usually
114
- # should be called just prior to dropping packets to a file or on the wire.
115
- #--
116
- # This is /not/ delegated down to @tcp_header since we need info
117
- # from the IP header, too.
118
- #++
119
- def tcp_calc_sum
120
- checksum = (ip_src.to_i >> 16)
121
- checksum += (ip_src.to_i & 0xffff)
122
- checksum += (ip_dst.to_i >> 16)
123
- checksum += (ip_dst.to_i & 0xffff)
124
- checksum += 0x06 # TCP Protocol.
125
- checksum += (ip_len.to_i - ((ip_hl.to_i) * 4))
126
- checksum += tcp_src
127
- checksum += tcp_dst
128
- checksum += (tcp_seq.to_i >> 16)
129
- checksum += (tcp_seq.to_i & 0xffff)
130
- checksum += (tcp_ack.to_i >> 16)
131
- checksum += (tcp_ack.to_i & 0xffff)
132
- checksum += ((tcp_hlen << 12) +
133
- (tcp_reserved << 9) +
134
- (tcp_ecn.to_i << 6) +
135
- tcp_flags.to_i
136
- )
137
- checksum += tcp_win
138
- checksum += tcp_urg
139
-
140
- chk_tcp_opts = (tcp_opts.to_s.size % 2 == 0 ? tcp_opts.to_s : tcp_opts.to_s + "\x00")
141
- chk_tcp_opts.unpack("n*").each {|x| checksum = checksum + x }
142
- if (ip_len - ((ip_hl + tcp_hlen) * 4)) >= 0
143
- real_tcp_payload = payload[0,( ip_len - ((ip_hl + tcp_hlen) * 4) )] # Can't forget those pesky FCSes!
144
- else
145
- real_tcp_payload = payload # Something's amiss here so don't bother figuring out where the real payload is.
146
- end
147
- chk_payload = (real_tcp_payload.size % 2 == 0 ? real_tcp_payload : real_tcp_payload + "\x00") # Null pad if it's odd.
148
- chk_payload.unpack("n*").each {|x| checksum = checksum+x }
149
- checksum = checksum % 0xffff
150
- checksum = 0xffff - checksum
151
- checksum == 0 ? 0xffff : checksum
152
- @tcp_header.tcp_sum = checksum
153
- end
154
-
155
- # Recalculates various fields of the TCP packet.
156
- #
157
- # ==== Parameters
158
- #
159
- # :all
160
- # Recomputes all calculated fields.
161
- # :tcp_sum
162
- # Recomputes the TCP checksum.
163
- # :tcp_hlen
164
- # Recomputes the TCP header length. Useful after options are added.
165
- def tcp_recalc(arg=:all)
166
- case arg
167
- when :tcp_sum
168
- tcp_calc_sum
169
- when :tcp_hlen
170
- @tcp_header.tcp_recalc :tcp_hlen
171
- when :all
172
- @tcp_header.tcp_recalc :all
173
- tcp_calc_sum
174
- else
175
- raise ArgumentError, "No such field `#{arg}'"
176
- end
177
- end
178
-
179
- # TCP packets are denoted by a "T ", followed by size,
180
- # source and dest information, packet flags, sequence
181
- # number, and IPID.
182
- def peek_format
183
- peek_data = ["T "]
184
- peek_data << "%-5d" % self.to_s.size
185
- peek_data << "%-21s" % "#{self.ip_saddr}:#{self.tcp_src}"
186
- peek_data << "->"
187
- peek_data << "%21s" % "#{self.ip_daddr}:#{self.tcp_dst}"
188
- flags = ' ['
189
- flags << self.tcp_flags_dotmap
190
- flags << '] '
191
- peek_data << flags
192
- peek_data << "S:"
193
- peek_data << "%08x" % self.tcp_seq
194
- peek_data << "|I:"
195
- peek_data << "%04x" % self.ip_id
196
- peek_data.join
197
- end
198
-
199
- end
46
+ attr_accessor :eth_header, :ip_header, :tcp_header
47
+
48
+ def self.can_parse?(str)
49
+ return false unless str.size >= 54
50
+ return false unless EthPacket.can_parse? str
51
+ return false unless IPPacket.can_parse? str
52
+ return false unless str[23,1] == "\x06"
53
+ return true
54
+ end
55
+
56
+ def read(str=nil, args={})
57
+ raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
58
+ @eth_header.read(str)
59
+
60
+ # Strip off any extra data, if we are asked to do so.
61
+ if args[:strip]
62
+ tcp_body_len = self.ip_len - self.ip_hlen - (self.tcp_hlen * 4)
63
+ @tcp_header.body.read(@tcp_header.body.to_s[0,tcp_body_len])
64
+ end
65
+ super(args)
66
+ self
67
+ end
68
+
69
+ def initialize(args={})
70
+ @eth_header = (args[:eth] || EthHeader.new)
71
+ @ip_header = (args[:ip] || IPHeader.new)
72
+ @tcp_header = (args[:tcp] || TCPHeader.new)
73
+ @tcp_header.flavor = args[:flavor].to_s.downcase
74
+
75
+ @ip_header.body = @tcp_header
76
+ @eth_header.body = @ip_header
77
+ @headers = [@eth_header, @ip_header, @tcp_header]
78
+
79
+ @ip_header.ip_proto=0x06
80
+ super
81
+ if args[:flavor]
82
+ tcp_calc_flavor(@tcp_header.flavor)
83
+ else
84
+ tcp_calc_sum
85
+ end
86
+ end
87
+
88
+ # Sets the correct flavor for TCP Packets. Recognized flavors are:
89
+ # windows, linux, freebsd
90
+ def tcp_calc_flavor(str)
91
+ ts_val = Time.now.to_i + rand(0x4fffffff)
92
+ ts_sec = rand(0xffffff)
93
+ case @tcp_header.flavor = str.to_s.downcase
94
+ when "windows" # WinXP's default syn
95
+ @tcp_header.tcp_win = 0x4000
96
+ @tcp_header.tcp_options="MSS:1460,NOP,NOP,SACKOK"
97
+ @tcp_header.tcp_src = rand(5000 - 1026) + 1026
98
+ @ip_header.ip_ttl = 64
99
+ when "linux" # Ubuntu Linux 2.6.24-19-generic default syn
100
+ @tcp_header.tcp_win = 5840
101
+ @tcp_header.tcp_options="MSS:1460,SACKOK,TS:#{ts_val};0,NOP,WS:7"
102
+ @tcp_header.tcp_src = rand(61_000 - 32_000) + 32_000
103
+ @ip_header.ip_ttl = 64
104
+ when "freebsd" # Freebsd
105
+ @tcp_header.tcp_win = 0xffff
106
+ @tcp_header.tcp_options="MSS:1460,NOP,WS:3,NOP,NOP,TS:#{ts_val};#{ts_sec},SACKOK,EOL,EOL"
107
+ @ip_header.ip_ttl = 64
108
+ else
109
+ @tcp_header.tcp_options="MSS:1460,NOP,NOP,SACKOK"
110
+ end
111
+ tcp_calc_sum
112
+ end
113
+
114
+ # tcp_calc_sum() computes the TCP checksum, and is called upon intialization. It usually
115
+ # should be called just prior to dropping packets to a file or on the wire.
116
+ #--
117
+ # This is /not/ delegated down to @tcp_header since we need info
118
+ # from the IP header, too.
119
+ #++
120
+ def tcp_calc_sum
121
+ checksum = (ip_src.to_i >> 16)
122
+ checksum += (ip_src.to_i & 0xffff)
123
+ checksum += (ip_dst.to_i >> 16)
124
+ checksum += (ip_dst.to_i & 0xffff)
125
+ checksum += 0x06 # TCP Protocol.
126
+ checksum += (ip_len.to_i - ((ip_hl.to_i) * 4))
127
+ checksum += tcp_src
128
+ checksum += tcp_dst
129
+ checksum += (tcp_seq.to_i >> 16)
130
+ checksum += (tcp_seq.to_i & 0xffff)
131
+ checksum += (tcp_ack.to_i >> 16)
132
+ checksum += (tcp_ack.to_i & 0xffff)
133
+ checksum += ((tcp_hlen << 12) +
134
+ (tcp_reserved << 9) +
135
+ (tcp_ecn.to_i << 6) +
136
+ tcp_flags.to_i
137
+ )
138
+ checksum += tcp_win
139
+ checksum += tcp_urg
140
+
141
+ chk_tcp_opts = (tcp_opts.to_s.size % 2 == 0 ? tcp_opts.to_s : tcp_opts.to_s + "\x00")
142
+ chk_tcp_opts.unpack("n*").each {|x| checksum = checksum + x }
143
+ if (ip_len - ((ip_hl + tcp_hlen) * 4)) >= 0
144
+ real_tcp_payload = payload[0,( ip_len - ((ip_hl + tcp_hlen) * 4) )] # Can't forget those pesky FCSes!
145
+ else
146
+ real_tcp_payload = payload # Something's amiss here so don't bother figuring out where the real payload is.
147
+ end
148
+ chk_payload = (real_tcp_payload.size % 2 == 0 ? real_tcp_payload : real_tcp_payload + "\x00") # Null pad if it's odd.
149
+ chk_payload.unpack("n*").each {|x| checksum = checksum+x }
150
+ checksum = checksum % 0xffff
151
+ checksum = 0xffff - checksum
152
+ checksum == 0 ? 0xffff : checksum
153
+ @tcp_header.tcp_sum = checksum
154
+ end
155
+
156
+ # Recalculates various fields of the TCP packet.
157
+ #
158
+ # ==== Parameters
159
+ #
160
+ # :all
161
+ # Recomputes all calculated fields.
162
+ # :tcp_sum
163
+ # Recomputes the TCP checksum.
164
+ # :tcp_hlen
165
+ # Recomputes the TCP header length. Useful after options are added.
166
+ def tcp_recalc(arg=:all)
167
+ case arg
168
+ when :tcp_sum
169
+ tcp_calc_sum
170
+ when :tcp_hlen
171
+ @tcp_header.tcp_recalc :tcp_hlen
172
+ when :all
173
+ @tcp_header.tcp_recalc :all
174
+ tcp_calc_sum
175
+ else
176
+ raise ArgumentError, "No such field `#{arg}'"
177
+ end
178
+ end
179
+
180
+ # TCP packets are denoted by a "T ", followed by size,
181
+ # source and dest information, packet flags, sequence
182
+ # number, and IPID.
183
+ def peek_format
184
+ peek_data = ["T "]
185
+ peek_data << "%-5d" % self.to_s.size
186
+ peek_data << "%-21s" % "#{self.ip_saddr}:#{self.tcp_src}"
187
+ peek_data << "->"
188
+ peek_data << "%21s" % "#{self.ip_daddr}:#{self.tcp_dst}"
189
+ flags = ' ['
190
+ flags << self.tcp_flags_dotmap
191
+ flags << '] '
192
+ peek_data << flags
193
+ peek_data << "S:"
194
+ peek_data << "%08x" % self.tcp_seq
195
+ peek_data << "|I:"
196
+ peek_data << "%04x" % self.ip_id
197
+ peek_data.join
198
+ end
199
+
200
+ end
200
201
 
201
202
  end