packetfu 1.1.5 → 1.1.6

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 (52) hide show
  1. data/.document +5 -2
  2. data/.gitignore +1 -0
  3. data/LICENSE.txt +1 -1
  4. data/bench/after-2012-07-28.txt +25 -0
  5. data/bench/before-2012-07-28.txt +25 -0
  6. data/bench/benchit.rb +68 -0
  7. data/bench/calc_delta.rb +17 -0
  8. data/bench/octets.rb +22 -0
  9. data/bench/octets_after.txt +8 -0
  10. data/bench/octets_after_refactor.txt +8 -0
  11. data/bench/octets_before.txt +8 -0
  12. data/lib/packetfu.rb +8 -3
  13. data/lib/packetfu/packet.rb +2 -2
  14. data/lib/packetfu/pcap.rb +20 -4
  15. data/lib/packetfu/protos/arp.rb +7 -160
  16. data/lib/packetfu/protos/arp/header.rb +160 -0
  17. data/lib/packetfu/protos/arp/mixin.rb +38 -0
  18. data/lib/packetfu/protos/eth.rb +5 -247
  19. data/lib/packetfu/protos/eth/header.rb +247 -0
  20. data/lib/packetfu/protos/eth/mixin.rb +20 -0
  21. data/lib/packetfu/protos/hsrp.rb +13 -123
  22. data/lib/packetfu/protos/hsrp/header.rb +120 -0
  23. data/lib/packetfu/protos/hsrp/mixin.rb +31 -0
  24. data/lib/packetfu/protos/icmp.rb +10 -97
  25. data/lib/packetfu/protos/icmp/header.rb +93 -0
  26. data/lib/packetfu/protos/icmp/mixin.rb +17 -0
  27. data/lib/packetfu/protos/ip.rb +7 -295
  28. data/lib/packetfu/protos/ip/header.rb +335 -0
  29. data/lib/packetfu/protos/ip/mixin.rb +43 -0
  30. data/lib/packetfu/protos/ipv6.rb +7 -191
  31. data/lib/packetfu/protos/ipv6/header.rb +190 -0
  32. data/lib/packetfu/protos/ipv6/mixin.rb +31 -0
  33. data/lib/packetfu/protos/tcp.rb +13 -939
  34. data/lib/packetfu/protos/tcp/ecn.rb +42 -0
  35. data/lib/packetfu/protos/tcp/flags.rb +83 -0
  36. data/lib/packetfu/protos/tcp/header.rb +307 -0
  37. data/lib/packetfu/protos/tcp/hlen.rb +40 -0
  38. data/lib/packetfu/protos/tcp/mixin.rb +48 -0
  39. data/lib/packetfu/protos/tcp/option.rb +323 -0
  40. data/lib/packetfu/protos/tcp/options.rb +106 -0
  41. data/lib/packetfu/protos/tcp/reserved.rb +42 -0
  42. data/lib/packetfu/protos/udp.rb +12 -110
  43. data/lib/packetfu/protos/udp/header.rb +107 -0
  44. data/lib/packetfu/protos/udp/mixin.rb +23 -0
  45. data/lib/packetfu/utils.rb +24 -24
  46. data/lib/packetfu/version.rb +1 -1
  47. data/packetfu.gemspec +2 -2
  48. data/test/test_ip.rb +0 -19
  49. data/test/test_octets.rb +18 -21
  50. data/test/test_tcp.rb +10 -0
  51. data/test/test_udp.rb +17 -0
  52. metadata +79 -50
@@ -0,0 +1,31 @@
1
+ module PacketFu
2
+ # This Mixin simplifies access to the HSRPHeaders. Mix this in with your
3
+ # packet interface, and it will add methods that essentially delegate to
4
+ # the 'hsrp_header' method (assuming that it is a HSRPHeader object)
5
+ module HSRPHeaderMixin
6
+ def hsrp_version=(v); self.hsrp_header.hsrp_version= v; end
7
+ def hsrp_version; self.hsrp_header.hsrp_version; end
8
+ def hsrp_opcode=(v); self.hsrp_header.hsrp_opcode= v; end
9
+ def hsrp_opcode; self.hsrp_header.hsrp_opcode; end
10
+ def hsrp_state=(v); self.hsrp_header.hsrp_state= v; end
11
+ def hsrp_state; self.hsrp_header.hsrp_state; end
12
+ def hsrp_hellotime=(v); self.hsrp_header.hsrp_hellotime= v; end
13
+ def hsrp_hellotime; self.hsrp_header.hsrp_hellotime; end
14
+ def hsrp_holdtime=(v); self.hsrp_header.hsrp_holdtime= v; end
15
+ def hsrp_holdtime; self.hsrp_header.hsrp_holdtime; end
16
+ def hsrp_priority=(v); self.hsrp_header.hsrp_priority= v; end
17
+ def hsrp_priority; self.hsrp_header.hsrp_priority; end
18
+ def hsrp_group=(v); self.hsrp_header.hsrp_group= v; end
19
+ def hsrp_group; self.hsrp_header.hsrp_group; end
20
+ def hsrp_reserved=(v); self.hsrp_header.hsrp_reserved= v; end
21
+ def hsrp_reserved; self.hsrp_header.hsrp_reserved; end
22
+ def hsrp_addr=(v); self.hsrp_header.hsrp_addr= v; end
23
+ def hsrp_addr; self.hsrp_header.hsrp_addr; end
24
+ def hsrp_vip_readable; self.hsrp_header.hsrp_vip_readable; end
25
+ def hsrp_password_readable; self.hsrp_header.hsrp_password_readable; end
26
+ def hsrp_password; self.hsrp_header.hsrp_password; end
27
+ def hsrp_password=(v); self.hsrp_header.hsrp_password= v; end
28
+ def hsrp_vip; self.hsrp_header.hsrp_vip; end
29
+ def hsrp_vip=(v); self.hsrp_header.hsrp_vip= v; end
30
+ end
31
+ end
@@ -1,97 +1,13 @@
1
- module PacketFu
1
+ require 'packetfu/protos/eth/header'
2
+ require 'packetfu/protos/eth/mixin'
2
3
 
3
- # ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
4
- # typically used for network administration and connectivity testing.
5
- #
6
- # For more on ICMP packets, see
7
- # http://www.networksorcery.com/enp/protocol/icmp.htm
8
- #
9
- # ==== Header Definition
10
- #
11
- # Int8 :icmp_type # Type
12
- # Int8 :icmp_code # Code
13
- # Int16 :icmp_sum Default: calculated # Checksum
14
- # String :body
15
- class ICMPHeader < Struct.new(:icmp_type, :icmp_code, :icmp_sum, :body)
4
+ require 'packetfu/protos/ip/header'
5
+ require 'packetfu/protos/ip/mixin'
16
6
 
17
- include StructFu
18
-
19
- def initialize(args={})
20
- super(
21
- Int8.new(args[:icmp_type]),
22
- Int8.new(args[:icmp_code]),
23
- Int16.new(args[:icmp_sum] || icmp_calc_sum),
24
- StructFu::String.new.read(args[:body])
25
- )
26
- end
27
-
28
- # Returns the object in string form.
29
- def to_s
30
- self.to_a.map {|x| x.to_s}.join
31
- end
32
-
33
- # Reads a string to populate the object.
34
- def read(str)
35
- force_binary(str)
36
- return self if str.nil?
37
- self[:icmp_type].read(str[0,1])
38
- self[:icmp_code].read(str[1,1])
39
- self[:icmp_sum].read(str[2,2])
40
- self[:body].read(str[4,str.size])
41
- self
42
- end
43
-
44
- # Setter for the type.
45
- def icmp_type=(i); typecast i; end
46
- # Getter for the type.
47
- def icmp_type; self[:icmp_type].to_i; end
48
- # Setter for the code.
49
- def icmp_code=(i); typecast i; end
50
- # Getter for the code.
51
- def icmp_code; self[:icmp_code].to_i; end
52
- # Setter for the checksum. Note, this is calculated automatically with
53
- # icmp_calc_sum.
54
- def icmp_sum=(i); typecast i; end
55
- # Getter for the checksum.
56
- def icmp_sum; self[:icmp_sum].to_i; end
57
-
58
- # Calculates and sets the checksum for the object.
59
- def icmp_calc_sum
60
- checksum = (icmp_type.to_i << 8) + icmp_code.to_i
61
- chk_body = (body.to_s.size % 2 == 0 ? body.to_s : body.to_s + "\x00")
62
- if 1.respond_to? :ord
63
- chk_body.scan(/../).map { |x| (x[0].ord << 8) + x[1].ord }.each { |y| checksum += y }
64
- else
65
- chk_body.scan(/../).map { |x| (x[0] << 8) + x[1] }.each { |y| checksum += y }
66
- end
67
- checksum = checksum % 0xffff
68
- checksum = 0xffff - checksum
69
- checksum == 0 ? 0xffff : checksum
70
- end
71
-
72
- # Recalculates the calculatable fields for ICMP.
73
- def icmp_recalc(arg=:all)
74
- # How silly is this, you can't intern a symbol in ruby 1.8.7pl72?
75
- # I'm this close to monkey patching Symbol so you can force it...
76
- arg = arg.intern if arg.respond_to? :intern
77
- case arg
78
- when :icmp_sum
79
- self.icmp_sum=icmp_calc_sum
80
- when :all
81
- self.icmp_sum=icmp_calc_sum
82
- else
83
- raise ArgumentError, "No such field `#{arg}'"
84
- end
85
- end
86
-
87
- # Readability aliases
88
-
89
- def icmp_sum_readable
90
- "0x%04x" % icmp_sum
91
- end
92
-
93
- end
7
+ require 'packetfu/protos/icmp/header'
8
+ require 'packetfu/protos/icmp/mixin'
94
9
 
10
+ module PacketFu
95
11
  # ICMPPacket is used to construct ICMP Packets. They contain an EthHeader, an IPHeader, and a ICMPHeader.
96
12
  #
97
13
  # == Example
@@ -119,6 +35,9 @@ module PacketFu
119
35
  # :config
120
36
  # A hash of return address details, often the output of Utils.whoami?
121
37
  class ICMPPacket < Packet
38
+ include ::PacketFu::EthHeaderMixin
39
+ include ::PacketFu::IPHeaderMixin
40
+ include ::PacketFu::ICMPHeaderMixin
122
41
 
123
42
  attr_accessor :eth_header, :ip_header, :icmp_header
124
43
 
@@ -133,10 +52,6 @@ module PacketFu
133
52
  def read(str=nil, args={})
134
53
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
135
54
  @eth_header.read(str)
136
- @ip_header.read(str[14,str.size])
137
- @eth_header.body = @ip_header
138
- @icmp_header.read(str[14+(@ip_header.ip_hlen),str.size])
139
- @ip_header.body = @icmp_header
140
55
  super(args)
141
56
  self
142
57
  end
@@ -173,7 +88,5 @@ module PacketFu
173
88
  peek_data << "%04x" % self.ip_id
174
89
  peek_data.join
175
90
  end
176
-
177
91
  end
178
-
179
92
  end
@@ -0,0 +1,93 @@
1
+ module PacketFu
2
+ # ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
3
+ # typically used for network administration and connectivity testing.
4
+ #
5
+ # For more on ICMP packets, see
6
+ # http://www.networksorcery.com/enp/protocol/icmp.htm
7
+ #
8
+ # ==== Header Definition
9
+ #
10
+ # Int8 :icmp_type # Type
11
+ # Int8 :icmp_code # Code
12
+ # Int16 :icmp_sum Default: calculated # Checksum
13
+ # String :body
14
+ class ICMPHeader < Struct.new(:icmp_type, :icmp_code, :icmp_sum, :body)
15
+
16
+ include StructFu
17
+
18
+ def initialize(args={})
19
+ super(
20
+ Int8.new(args[:icmp_type]),
21
+ Int8.new(args[:icmp_code]),
22
+ Int16.new(args[:icmp_sum] || icmp_calc_sum),
23
+ StructFu::String.new.read(args[:body])
24
+ )
25
+ end
26
+
27
+ # Returns the object in string form.
28
+ def to_s
29
+ self.to_a.map {|x| x.to_s}.join
30
+ end
31
+
32
+ # Reads a string to populate the object.
33
+ def read(str)
34
+ force_binary(str)
35
+ return self if str.nil?
36
+ self[:icmp_type].read(str[0,1])
37
+ self[:icmp_code].read(str[1,1])
38
+ self[:icmp_sum].read(str[2,2])
39
+ self[:body].read(str[4,str.size])
40
+ self
41
+ end
42
+
43
+ # Setter for the type.
44
+ def icmp_type=(i); typecast i; end
45
+ # Getter for the type.
46
+ def icmp_type; self[:icmp_type].to_i; end
47
+ # Setter for the code.
48
+ def icmp_code=(i); typecast i; end
49
+ # Getter for the code.
50
+ def icmp_code; self[:icmp_code].to_i; end
51
+ # Setter for the checksum. Note, this is calculated automatically with
52
+ # icmp_calc_sum.
53
+ def icmp_sum=(i); typecast i; end
54
+ # Getter for the checksum.
55
+ def icmp_sum; self[:icmp_sum].to_i; end
56
+
57
+ # Calculates and sets the checksum for the object.
58
+ def icmp_calc_sum
59
+ checksum = (icmp_type.to_i << 8) + icmp_code.to_i
60
+ chk_body = (body.to_s.size % 2 == 0 ? body.to_s : body.to_s + "\x00")
61
+ if 1.respond_to? :ord
62
+ chk_body.scan(/../).map { |x| (x[0].ord << 8) + x[1].ord }.each { |y| checksum += y }
63
+ else
64
+ chk_body.scan(/../).map { |x| (x[0] << 8) + x[1] }.each { |y| checksum += y }
65
+ end
66
+ checksum = checksum % 0xffff
67
+ checksum = 0xffff - checksum
68
+ checksum == 0 ? 0xffff : checksum
69
+ end
70
+
71
+ # Recalculates the calculatable fields for ICMP.
72
+ def icmp_recalc(arg=:all)
73
+ # How silly is this, you can't intern a symbol in ruby 1.8.7pl72?
74
+ # I'm this close to monkey patching Symbol so you can force it...
75
+ arg = arg.intern if arg.respond_to? :intern
76
+ case arg
77
+ when :icmp_sum
78
+ self.icmp_sum=icmp_calc_sum
79
+ when :all
80
+ self.icmp_sum=icmp_calc_sum
81
+ else
82
+ raise ArgumentError, "No such field `#{arg}'"
83
+ end
84
+ end
85
+
86
+ # Readability aliases
87
+
88
+ def icmp_sum_readable
89
+ "0x%04x" % icmp_sum
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ module PacketFu
2
+ # This Mixin simplifies access to the ICMPHeaders. Mix this in with your
3
+ # packet interface, and it will add methods that essentially delegate to
4
+ # the 'icmp_header' method (assuming that it is a ICMPHeader object)
5
+ module ICMPHeaderMixin
6
+ def icmp_type=(v); self.icmp_header.icmp_type= v; end
7
+ def icmp_type; self.icmp_header.icmp_type; end
8
+ def icmp_code=(v); self.icmp_header.icmp_code= v; end
9
+ def icmp_code; self.icmp_header.icmp_code; end
10
+ def icmp_sum=(v); self.icmp_header.icmp_sum= v; end
11
+ def icmp_sum; self.icmp_header.icmp_sum; end
12
+ def icmp_calc_sum; self.icmp_header.icmp_calc_sum; end
13
+ def icmp_recalc(*v); self.icmp_header.icmp_recalc(*v); end
14
+ def icmp_sum_readable; self.icmp_header.icmp_sum_readable; end
15
+ end
16
+ end
17
+
@@ -1,298 +1,10 @@
1
- require 'ipaddr'
2
- module PacketFu
3
-
4
- # Octets implements the addressing scheme for IP.
5
- #
6
- # ==== Header Definition
7
- #
8
- # Int8 :o1
9
- # Int8 :o2
10
- # Int8 :o3
11
- # Int8 :o4
12
- class Octets < Struct.new(:o1, :o2, :o3, :o4)
13
- include StructFu
14
-
15
- def initialize(args={})
16
- super(
17
- Int8.new(args[:o1]),
18
- Int8.new(args[:o2]),
19
- Int8.new(args[:o3]),
20
- Int8.new(args[:o4]))
21
- end
22
-
23
- # Returns the object in string form.
24
- def to_s
25
- self.to_a.map {|x| x.to_s}.join
26
- end
27
-
28
- # Reads a string to populate the object.
29
- def read(str)
30
- force_binary(str)
31
- return self if str.nil?
32
- self[:o1].read str[0,1]
33
- self[:o2].read str[1,1]
34
- self[:o3].read str[2,1]
35
- self[:o4].read str[3,1]
36
- self
37
- end
38
-
39
- # Returns an address in dotted-quad format.
40
- def to_x
41
- ip_str = [o1, o2, o3, o4].map {|x| x.to_i.to_s}.join('.')
42
- IPAddr.new(ip_str).to_s
43
- end
44
-
45
- # Returns an address in numerical format.
46
- def to_i
47
- ip_str = [o1, o2, o3, o4].map {|x| x.to_i.to_s}.join('.')
48
- IPAddr.new(ip_str).to_i
49
- end
50
-
51
- # Set the IP Address by reading a dotted-quad address.
52
- def read_quad(str)
53
- read([IPAddr.new(str).to_i].pack("N"))
54
- end
1
+ require 'packetfu/protos/eth/header'
2
+ require 'packetfu/protos/eth/mixin'
55
3
 
56
- end
57
-
58
- # IPHeader is a complete IP struct, used in IPPacket. Most traffic on most networks today is IP-based.
59
- #
60
- # For more on IP packets, see http://www.networksorcery.com/enp/protocol/ip.htm
61
- #
62
- # ==== Header Definition
63
- #
64
- # Fixnum (4 bits) :ip_v, Default: 4
65
- # Fixnum (4 bits) :ip_hl, Default: 5
66
- # Int8 :ip_tos, Default: 0 # TODO: Break out the bits
67
- # Int16 :ip_len, Default: calculated
68
- # Int16 :ip_id, Default: calculated # IRL, hardly random.
69
- # Int16 :ip_frag, Default: 0 # TODO: Break out the bits
70
- # Int8 :ip_ttl, Default: 0xff # Changes per flavor
71
- # Int8 :ip_proto, Default: 0x01 # TCP: 0x06, UDP 0x11, ICMP 0x01
72
- # Int16 :ip_sum, Default: calculated
73
- # Octets :ip_src
74
- # Octets :ip_dst
75
- # String :body
76
- #
77
- # Note that IPPackets will always be somewhat incorrect upon initalization,
78
- # and want an IPHeader#recalc() to become correct before a
79
- # Packet#to_f or Packet#to_w.
80
- class IPHeader < Struct.new(:ip_v, :ip_hl, :ip_tos, :ip_len,
81
- :ip_id, :ip_frag, :ip_ttl, :ip_proto,
82
- :ip_sum, :ip_src, :ip_dst, :body)
83
- include StructFu
84
-
85
- def initialize(args={})
86
- @random_id = rand(0xffff)
87
- super(
88
- (args[:ip_v] || 4),
89
- (args[:ip_hl] || 5),
90
- Int8.new(args[:ip_tos]),
91
- Int16.new(args[:ip_len] || 20),
92
- Int16.new(args[:ip_id] || ip_calc_id),
93
- Int16.new(args[:ip_frag]),
94
- Int8.new(args[:ip_ttl] || 32),
95
- Int8.new(args[:ip_proto]),
96
- Int16.new(args[:ip_sum] || ip_calc_sum),
97
- Octets.new.read(args[:ip_src] || "\x00\x00\x00\x00"),
98
- Octets.new.read(args[:ip_dst] || "\x00\x00\x00\x00"),
99
- StructFu::String.new.read(args[:body])
100
- )
101
- end
4
+ require 'packetfu/protos/ip/header'
5
+ require 'packetfu/protos/ip/mixin'
102
6
 
103
- # Returns the object in string form.
104
- def to_s
105
- byte_v_hl = [(self.ip_v << 4) + self.ip_hl].pack("C")
106
- byte_v_hl + (self.to_a[2,10].map {|x| x.to_s}.join)
107
- end
108
-
109
- # Reads a string to populate the object.
110
- def read(str)
111
- force_binary(str)
112
- return self if str.nil?
113
- self[:ip_v] = str[0,1].unpack("C").first >> 4
114
- self[:ip_hl] = str[0,1].unpack("C").first.to_i & 0x0f
115
- self[:ip_tos].read(str[1,1])
116
- self[:ip_len].read(str[2,2])
117
- self[:ip_id].read(str[4,2])
118
- self[:ip_frag].read(str[6,2])
119
- self[:ip_ttl].read(str[8,1])
120
- self[:ip_proto].read(str[9,1])
121
- self[:ip_sum].read(str[10,2])
122
- self[:ip_src].read(str[12,4])
123
- self[:ip_dst].read(str[16,4])
124
- self[:body].read(str[20,str.size]) if str.size > 20
125
- self
126
- end
127
-
128
- # Setter for the version.
129
- def ip_v=(i); self[:ip_v] = i.to_i; end
130
- # Getter for the version.
131
- def ip_v; self[:ip_v].to_i; end
132
- # Setter for the header length (divide by 4)
133
- def ip_hl=(i); self[:ip_hl] = i.to_i; end
134
- # Getter for the header length (multiply by 4)
135
- def ip_hl; self[:ip_hl].to_i; end
136
- # Setter for the differentiated services
137
- def ip_tos=(i); typecast i; end
138
- # Getter for the differentiated services
139
- def ip_tos; self[:ip_tos].to_i; end
140
- # Setter for total length.
141
- def ip_len=(i); typecast i; end
142
- # Getter for total length.
143
- def ip_len; self[:ip_len].to_i; end
144
- # Setter for the identication number.
145
- def ip_id=(i); typecast i; end
146
- # Getter for the identication number.
147
- def ip_id; self[:ip_id].to_i; end
148
- # Setter for the fragmentation ID.
149
- def ip_frag=(i); typecast i; end
150
- # Getter for the fragmentation ID.
151
- def ip_frag; self[:ip_frag].to_i; end
152
- # Setter for the time to live.
153
- def ip_ttl=(i); typecast i; end
154
- # Getter for the time to live.
155
- def ip_ttl; self[:ip_ttl].to_i; end
156
- # Setter for the protocol number.
157
- def ip_proto=(i); typecast i; end
158
- # Getter for the protocol number.
159
- def ip_proto; self[:ip_proto].to_i; end
160
- # Setter for the checksum.
161
- def ip_sum=(i); typecast i; end
162
- # Getter for the checksum.
163
- def ip_sum; self[:ip_sum].to_i; end
164
- # Setter for the source IP address.
165
- def ip_src=(i)
166
- case i
167
- when Numeric
168
- self[:ip_src] = Octets.new.read([i].pack("N"))
169
- when Octets
170
- self[:ip_src] = i
171
- else
172
- typecast i
173
- end
174
- end
175
- # Getter for the source IP address.
176
- def ip_src; self[:ip_src].to_i; end
177
- # Setter for the destination IP address.
178
- def ip_dst=(i)
179
- case i
180
- when Numeric
181
- self[:ip_dst] = Octets.new.read([i].pack("N"))
182
- when Octets
183
- self[:ip_dst] = i
184
- else
185
- typecast i
186
- end
187
- end
188
- # Getter for the destination IP address.
189
- def ip_dst; self[:ip_dst].to_i; end
190
-
191
- # Calulcate the true length of the packet.
192
- def ip_calc_len
193
- (ip_hl * 4) + body.to_s.length
194
- end
195
-
196
- # Return the claimed header length
197
- def ip_hlen
198
- (ip_hl * 4)
199
- end
200
-
201
- # Calculate the true checksum of the packet.
202
- # (Yes, this is the long way to do it, but it's e-z-2-read for mathtards like me.)
203
- def ip_calc_sum
204
- checksum = (((self.ip_v << 4) + self.ip_hl) << 8) + self.ip_tos
205
- checksum += self.ip_len
206
- checksum += self.ip_id
207
- checksum += self.ip_frag
208
- checksum += (self.ip_ttl << 8) + self.ip_proto
209
- checksum += (self.ip_src >> 16)
210
- checksum += (self.ip_src & 0xffff)
211
- checksum += (self.ip_dst >> 16)
212
- checksum += (self.ip_dst & 0xffff)
213
- checksum = checksum % 0xffff
214
- checksum = 0xffff - checksum
215
- checksum == 0 ? 0xffff : checksum
216
- end
217
-
218
- # Retrieve the IP ID
219
- def ip_calc_id
220
- @random_id
221
- end
222
-
223
- # Sets a more readable IP address. If you wants to manipulate individual octets,
224
- # (eg, for host scanning in one network), it would be better use ip_src.o1 through
225
- # ip_src.o4 instead.
226
- def ip_saddr=(addr)
227
- self[:ip_src].read_quad(addr)
228
- end
229
-
230
- # Returns a more readable IP source address.
231
- def ip_saddr
232
- self[:ip_src].to_x
233
- end
234
-
235
- # Sets a more readable IP address.
236
- def ip_daddr=(addr)
237
- self[:ip_dst].read_quad(addr)
238
- end
239
-
240
- # Returns a more readable IP destination address.
241
- def ip_daddr
242
- self[:ip_dst].to_x
243
- end
244
-
245
- # Translate various formats of IPv4 Addresses to an array of digits.
246
- def self.octet_array(addr)
247
- if addr.class == String
248
- oa = addr.split('.').collect {|x| x.to_i}
249
- elsif addr.class == Fixnum
250
- oa = IPAddr.new(addr, Socket::AF_INET).to_s.split('.')
251
- elsif addr.class == Bignum
252
- oa = IPAddr.new(addr, Socket::AF_INET).to_s.split('.')
253
- elsif addr.class == Array
254
- oa = addr
255
- else
256
- raise ArgumentError, "IP Address should be a dotted quad string, an array of ints, or a bignum"
257
- end
258
- end
259
-
260
- # Recalculate the calculated IP fields. Valid arguments are:
261
- # :all
262
- # :ip_len
263
- # :ip_sum
264
- # :ip_id
265
- def ip_recalc(arg=:all)
266
- case arg
267
- when :ip_len
268
- self.ip_len=ip_calc_len
269
- when :ip_sum
270
- self.ip_sum=ip_calc_sum
271
- when :ip_id
272
- @random_id = rand(0xffff)
273
- when :all
274
- self.ip_id= ip_calc_id
275
- self.ip_len= ip_calc_len
276
- self.ip_sum= ip_calc_sum
277
- else
278
- raise ArgumentError, "No such field `#{arg}'"
279
- end
280
- end
281
-
282
- # Readability aliases
283
-
284
- alias :ip_src_readable :ip_saddr
285
- alias :ip_dst_readable :ip_daddr
286
-
287
- def ip_id_readable
288
- "0x%04x" % ip_id
289
- end
290
-
291
- def ip_sum_readable
292
- "0x%04x" % ip_sum
293
- end
294
-
295
- end
7
+ module PacketFu
296
8
 
297
9
  # IPPacket is used to construct IP packets. They contain an EthHeader, an IPHeader, and usually
298
10
  # a transport-layer protocol such as UDPHeader, TCPHeader, or ICMPHeader.
@@ -322,6 +34,8 @@ module PacketFu
322
34
  # :config
323
35
  # A hash of return address details, often the output of Utils.whoami?
324
36
  class IPPacket < Packet
37
+ include ::PacketFu::EthHeaderMixin
38
+ include ::PacketFu::IPHeaderMixin
325
39
 
326
40
  attr_accessor :eth_header, :ip_header
327
41
 
@@ -343,8 +57,6 @@ module PacketFu
343
57
  def read(str=nil, args={})
344
58
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
345
59
  @eth_header.read(str)
346
- @ip_header.read(str[14,str.size])
347
- @eth_header.body = @ip_header
348
60
  super(args)
349
61
  self
350
62
  end