packetfu 1.1.9 → 1.1.10

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 (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