packetfu 1.1.9 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/bench/octets.rb +9 -9
  2. data/examples/100kpackets.rb +12 -12
  3. data/examples/ackscan.rb +16 -16
  4. data/examples/arp.rb +35 -35
  5. data/examples/arphood.rb +36 -36
  6. data/examples/dissect_thinger.rb +6 -6
  7. data/examples/new-simple-stats.rb +23 -23
  8. data/examples/packetfu-shell.rb +25 -25
  9. data/examples/simple-sniffer.rb +9 -9
  10. data/examples/simple-stats.rb +23 -23
  11. data/examples/slammer.rb +3 -3
  12. data/lib/packetfu.rb +127 -127
  13. data/lib/packetfu/capture.rb +169 -169
  14. data/lib/packetfu/config.rb +52 -52
  15. data/lib/packetfu/inject.rb +56 -56
  16. data/lib/packetfu/packet.rb +528 -528
  17. data/lib/packetfu/pcap.rb +579 -579
  18. data/lib/packetfu/protos/arp.rb +90 -90
  19. data/lib/packetfu/protos/arp/header.rb +158 -158
  20. data/lib/packetfu/protos/arp/mixin.rb +36 -36
  21. data/lib/packetfu/protos/eth.rb +44 -44
  22. data/lib/packetfu/protos/eth/header.rb +243 -243
  23. data/lib/packetfu/protos/eth/mixin.rb +3 -3
  24. data/lib/packetfu/protos/hsrp.rb +69 -69
  25. data/lib/packetfu/protos/hsrp/header.rb +107 -107
  26. data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
  27. data/lib/packetfu/protos/icmp.rb +71 -71
  28. data/lib/packetfu/protos/icmp/header.rb +82 -82
  29. data/lib/packetfu/protos/icmp/mixin.rb +14 -14
  30. data/lib/packetfu/protos/invalid.rb +49 -49
  31. data/lib/packetfu/protos/ip.rb +69 -69
  32. data/lib/packetfu/protos/ip/header.rb +291 -291
  33. data/lib/packetfu/protos/ip/mixin.rb +40 -40
  34. data/lib/packetfu/protos/ipv6.rb +50 -50
  35. data/lib/packetfu/protos/ipv6/header.rb +188 -188
  36. data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
  37. data/lib/packetfu/protos/tcp.rb +176 -176
  38. data/lib/packetfu/protos/tcp/ecn.rb +35 -35
  39. data/lib/packetfu/protos/tcp/flags.rb +74 -74
  40. data/lib/packetfu/protos/tcp/header.rb +268 -268
  41. data/lib/packetfu/protos/tcp/hlen.rb +32 -32
  42. data/lib/packetfu/protos/tcp/mixin.rb +46 -46
  43. data/lib/packetfu/protos/tcp/option.rb +321 -321
  44. data/lib/packetfu/protos/tcp/options.rb +95 -95
  45. data/lib/packetfu/protos/tcp/reserved.rb +35 -35
  46. data/lib/packetfu/protos/udp.rb +116 -116
  47. data/lib/packetfu/protos/udp/header.rb +91 -91
  48. data/lib/packetfu/protos/udp/mixin.rb +3 -3
  49. data/lib/packetfu/structfu.rb +280 -280
  50. data/lib/packetfu/utils.rb +226 -217
  51. data/lib/packetfu/version.rb +41 -41
  52. data/packetfu.gemspec +2 -1
  53. data/spec/ethpacket_spec.rb +48 -48
  54. data/spec/packet_spec.rb +57 -57
  55. data/spec/packet_subclasses_spec.rb +8 -8
  56. data/spec/packetfu_spec.rb +59 -59
  57. data/spec/structfu_spec.rb +268 -268
  58. data/spec/tcp_spec.rb +75 -75
  59. data/test/all_tests.rb +13 -13
  60. data/test/func_lldp.rb +3 -3
  61. data/test/ptest.rb +2 -2
  62. data/test/test_arp.rb +116 -116
  63. data/test/test_capture.rb +45 -45
  64. data/test/test_eth.rb +68 -68
  65. data/test/test_hsrp.rb +9 -9
  66. data/test/test_icmp.rb +52 -52
  67. data/test/test_inject.rb +18 -18
  68. data/test/test_invalid.rb +16 -16
  69. data/test/test_ip.rb +36 -36
  70. data/test/test_ip6.rb +48 -48
  71. data/test/test_octets.rb +21 -21
  72. data/test/test_packet.rb +154 -154
  73. data/test/test_pcap.rb +170 -170
  74. data/test/test_structfu.rb +97 -97
  75. data/test/test_tcp.rb +320 -320
  76. data/test/test_udp.rb +76 -76
  77. metadata +4 -3
@@ -1,32 +1,32 @@
1
1
  # -*- coding: binary -*-
2
2
  module PacketFu
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
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
32
32
  end
@@ -9,194 +9,194 @@ require 'packetfu/protos/ip/header'
9
9
  require 'packetfu/protos/ip/mixin'
10
10
 
11
11
  module PacketFu
12
- # TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
13
- #
14
- # == Example
15
- #
12
+ # TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
13
+ #
14
+ # == Example
15
+ #
16
16
  # tcp_pkt = PacketFu::TCPPacket.new
17
17
  # tcp_pkt.tcp_flags.syn=1
18
18
  # tcp_pkt.tcp_dst=80
19
19
  # tcp_pkt.tcp_win=5840
20
20
  # tcp_pkt.tcp_options="mss:1460,sack.ok,ts:#{rand(0xffffffff)};0,nop,ws:7"
21
- #
21
+ #
22
22
  # tcp_pkt.ip_saddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
23
23
  # tcp_pkt.ip_daddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
24
- #
24
+ #
25
25
  # tcp_pkt.recalc
26
26
  # tcp_pkt.to_f('/tmp/tcp.pcap')
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
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
42
42
  include ::PacketFu::EthHeaderMixin
43
43
  include ::PacketFu::IPHeaderMixin
44
44
  include ::PacketFu::TCPHeaderMixin
45
45
 
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
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
201
201
 
202
202
  end
@@ -1,43 +1,43 @@
1
1
  # -*- coding: binary -*-
2
2
  module PacketFu
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)
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)
12
12
 
13
- include StructFu
13
+ include StructFu
14
14
 
15
- def initialize(args={})
16
- super(args[:n], args[:c], args[:e]) if args
17
- end
15
+ def initialize(args={})
16
+ super(args[:n], args[:c], args[:e]) if args
17
+ end
18
18
 
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
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
24
24
 
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
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
41
41
 
42
- end
42
+ end
43
43
  end