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,247 @@
1
+ module PacketFu
2
+ # EthOui is the Organizationally Unique Identifier portion of a MAC address, used in EthHeader.
3
+ #
4
+ # See the OUI list at http://standards.ieee.org/regauth/oui/oui.txt
5
+ #
6
+ # ==== Header Definition
7
+ #
8
+ # Fixnum :b0
9
+ # Fixnum :b1
10
+ # Fixnum :b2
11
+ # Fixnum :b3
12
+ # Fixnum :b4
13
+ # Fixnum :b5
14
+ # Fixnum :local
15
+ # Fixnum :multicast
16
+ # Int16 :oui, Default: 0x1ac5 :)
17
+ class EthOui < Struct.new(:b5, :b4, :b3, :b2, :b1, :b0, :local, :multicast, :oui)
18
+
19
+ # EthOui is unusual in that the bit values do not enjoy StructFu typing.
20
+ def initialize(args={})
21
+ args[:local] ||= 0
22
+ args[:oui] ||= 0x1ac # :)
23
+ args.each_pair {|k,v| args[k] = 0 unless v}
24
+ super(args[:b5], args[:b4], args[:b3], args[:b2],
25
+ args[:b1], args[:b0], args[:local], args[:multicast],
26
+ args[:oui])
27
+ end
28
+
29
+ # Returns the object in string form.
30
+ def to_s
31
+ byte = 0
32
+ byte += 0b10000000 if b5.to_i == 1
33
+ byte += 0b01000000 if b4.to_i == 1
34
+ byte += 0b00100000 if b3.to_i == 1
35
+ byte += 0b00010000 if b2.to_i == 1
36
+ byte += 0b00001000 if b1.to_i == 1
37
+ byte += 0b00000100 if b0.to_i == 1
38
+ byte += 0b00000010 if local.to_i == 1
39
+ byte += 0b00000001 if multicast.to_i == 1
40
+ [byte,oui].pack("Cn")
41
+ end
42
+
43
+ # Reads a string to populate the object.
44
+ def read(str)
45
+ force_binary(str)
46
+ return self if str.nil?
47
+ if 1.respond_to? :ord
48
+ byte = str[0].ord
49
+ else
50
+ byte = str[0]
51
+ end
52
+ self[:b5] = byte & 0b10000000 == 0b10000000 ? 1 : 0
53
+ self[:b4] = byte & 0b01000000 == 0b01000000 ? 1 : 0
54
+ self[:b3] = byte & 0b00100000 == 0b00100000 ? 1 : 0
55
+ self[:b2] = byte & 0b00010000 == 0b00010000 ? 1 : 0
56
+ self[:b1] = byte & 0b00001000 == 0b00001000 ? 1 : 0
57
+ self[:b0] = byte & 0b00000100 == 0b00000100 ? 1 : 0
58
+ self[:local] = byte & 0b00000010 == 0b00000010 ? 1 : 0
59
+ self[:multicast] = byte & 0b00000001 == 0b00000001 ? 1 : 0
60
+ self[:oui] = str[1,2].unpack("n").first
61
+ self
62
+ end
63
+
64
+ end
65
+
66
+ # EthNic is the Network Interface Controler portion of a MAC address, used in EthHeader.
67
+ #
68
+ # ==== Header Definition
69
+ #
70
+ # Fixnum :n1
71
+ # Fixnum :n2
72
+ # Fixnum :n3
73
+ #
74
+ class EthNic < Struct.new(:n0, :n1, :n2)
75
+
76
+ # EthNic does not enjoy StructFu typing.
77
+ def initialize(args={})
78
+ args.each_pair {|k,v| args[k] = 0 unless v}
79
+ super(args[:n0], args[:n1], args[:n2])
80
+ end
81
+
82
+ # Returns the object in string form.
83
+ def to_s
84
+ [n0,n1,n2].map {|x| x.to_i}.pack("C3")
85
+ end
86
+
87
+ # Reads a string to populate the object.
88
+ def read(str)
89
+ force_binary(str)
90
+ return self if str.nil?
91
+ self[:n0], self[:n1], self[:n2] = str[0,3].unpack("C3")
92
+ self
93
+ end
94
+
95
+ end
96
+
97
+ # EthMac is the combination of an EthOui and EthNic, used in EthHeader.
98
+ #
99
+ # ==== Header Definition
100
+ #
101
+ # EthOui :oui # See EthOui
102
+ # EthNic :nic # See EthNic
103
+ class EthMac < Struct.new(:oui, :nic)
104
+
105
+ def initialize(args={})
106
+ super(
107
+ EthOui.new.read(args[:oui]),
108
+ EthNic.new.read(args[:nic]))
109
+ end
110
+
111
+ # Returns the object in string form.
112
+ def to_s
113
+ "#{self[:oui]}#{self[:nic]}"
114
+ end
115
+
116
+ # Reads a string to populate the object.
117
+ def read(str)
118
+ force_binary(str)
119
+ return self if str.nil?
120
+ self.oui.read str[0,3]
121
+ self.nic.read str[3,3]
122
+ self
123
+ end
124
+
125
+ end
126
+
127
+ # EthHeader is a complete Ethernet struct, used in EthPacket.
128
+ # It's the base header for all other protocols, such as IPHeader,
129
+ # TCPHeader, etc.
130
+ #
131
+ # For more on the construction on MAC addresses, see
132
+ # http://en.wikipedia.org/wiki/MAC_address
133
+ #
134
+ # TODO: Need to come up with a good way of dealing with vlan
135
+ # tagging. Having a usually empty struct member seems weird,
136
+ # but there may not be another way to do it if I want to preserve
137
+ # the Eth-ness of vlan-tagged 802.1Q packets. Also, may as well
138
+ # deal with 0x88a8 as well (http://en.wikipedia.org/wiki/802.1ad)
139
+ #
140
+ # ==== Header Definition
141
+ #
142
+ # EthMac :eth_dst # See EthMac
143
+ # EthMac :eth_src # See EthMac
144
+ # Int16 :eth_proto, Default: 0x8000 # IP 0x0800, Arp 0x0806
145
+ # String :body
146
+ class EthHeader < Struct.new(:eth_dst, :eth_src, :eth_proto, :body)
147
+ include StructFu
148
+
149
+ def initialize(args={})
150
+ super(
151
+ EthMac.new.read(args[:eth_dst]),
152
+ EthMac.new.read(args[:eth_src]),
153
+ Int16.new(args[:eth_proto] || 0x0800),
154
+ StructFu::String.new.read(args[:body])
155
+ )
156
+ end
157
+
158
+ # Setter for the Ethernet destination address.
159
+ def eth_dst=(i); typecast(i); end
160
+ # Getter for the Ethernet destination address.
161
+ def eth_dst; self[:eth_dst].to_s; end
162
+ # Setter for the Ethernet source address.
163
+ def eth_src=(i); typecast(i); end
164
+ # Getter for the Ethernet source address.
165
+ def eth_src; self[:eth_src].to_s; end
166
+ # Setter for the Ethernet protocol number.
167
+ def eth_proto=(i); typecast(i); end
168
+ # Getter for the Ethernet protocol number.
169
+ def eth_proto; self[:eth_proto].to_i; end
170
+
171
+ # Returns the object in string form.
172
+ def to_s
173
+ self.to_a.map {|x| x.to_s}.join
174
+ end
175
+
176
+ # Reads a string to populate the object.
177
+ def read(str)
178
+ force_binary(str)
179
+ return self if str.nil?
180
+ self[:eth_dst].read str[0,6]
181
+ self[:eth_src].read str[6,6]
182
+ self[:eth_proto].read str[12,2]
183
+ self[:body].read str[14,str.size]
184
+ self
185
+ end
186
+
187
+ # Converts a readable MAC (11:22:33:44:55:66) to a binary string.
188
+ # Readable MAC's may be split on colons, dots, spaces, or underscores.
189
+ #
190
+ # irb> PacketFu::EthHeader.mac2str("11:22:33:44:55:66")
191
+ #
192
+ # #=> "\021\"3DUf"
193
+ def self.mac2str(mac)
194
+ if mac.split(/[:\x2d\x2e\x5f]+/).size == 6
195
+ ret = mac.split(/[:\x2d\x2e\x20\x5f]+/).collect {|x| x.to_i(16)}.pack("C6")
196
+ else
197
+ raise ArgumentError, "Unkown format for mac address."
198
+ end
199
+ return ret
200
+ end
201
+
202
+ # Converts a binary string to a readable MAC (11:22:33:44:55:66).
203
+ #
204
+ # irb> PacketFu::EthHeader.str2mac("\x11\x22\x33\x44\x55\x66")
205
+ #
206
+ # #=> "11:22:33:44:55:66"
207
+ def self.str2mac(mac='')
208
+ if mac.to_s.size == 6 && mac.kind_of?(::String)
209
+ ret = mac.unpack("C6").map {|x| sprintf("%02x",x)}.join(":")
210
+ end
211
+ end
212
+
213
+ # Sets the source MAC address in a more readable way.
214
+ def eth_saddr=(mac)
215
+ mac = EthHeader.mac2str(mac)
216
+ self[:eth_src].read mac
217
+ self[:eth_src]
218
+ end
219
+
220
+ # Gets the source MAC address in a more readable way.
221
+ def eth_saddr
222
+ EthHeader.str2mac(self[:eth_src].to_s)
223
+ end
224
+
225
+ # Set the destination MAC address in a more readable way.
226
+ def eth_daddr=(mac)
227
+ mac = EthHeader.mac2str(mac)
228
+ self[:eth_dst].read mac
229
+ self[:eth_dst]
230
+ end
231
+
232
+ # Gets the destination MAC address in a more readable way.
233
+ def eth_daddr
234
+ EthHeader.str2mac(self[:eth_dst].to_s)
235
+ end
236
+
237
+ # Readability aliases
238
+
239
+ alias :eth_dst_readable :eth_daddr
240
+ alias :eth_src_readable :eth_saddr
241
+
242
+ def eth_proto_readable
243
+ "0x%04x" % eth_proto
244
+ end
245
+
246
+ end
247
+ end
@@ -0,0 +1,20 @@
1
+ module PacketFu
2
+ # This Mixin simplifies access to the EthHeaders. Mix this in with your
3
+ # packet interface, and it will add methods that essentially delegate to
4
+ # the 'eth_header' method (assuming that it is a EthHeader object)
5
+ module EthHeaderMixin
6
+ def eth_daddr; self.eth_header.eth_daddr ; end
7
+ def eth_daddr=(v); self.eth_header.eth_daddr= v; end
8
+ def eth_dst; self.eth_header.eth_dst ; end
9
+ def eth_dst=(v); self.eth_header.eth_dst= v; end
10
+ def eth_dst_readable; self.eth_header.eth_dst_readable ; end
11
+ def eth_proto; self.eth_header.eth_proto ; end
12
+ def eth_proto=(v); self.eth_header.eth_proto= v; end
13
+ def eth_proto_readable; self.eth_header.eth_proto_readable ; end
14
+ def eth_saddr; self.eth_header.eth_saddr ; end
15
+ def eth_saddr=(v); self.eth_header.eth_saddr= v; end
16
+ def eth_src; self.eth_header.eth_src ; end
17
+ def eth_src=(v); self.eth_header.eth_src= v; end
18
+ def eth_src_readable; self.eth_header.eth_src_readable ; end
19
+ end
20
+ end
@@ -1,124 +1,16 @@
1
- module PacketFu
2
-
3
- # HSRPHeader is a complete HSRP struct, used in HSRPPacket. HSRP is typically used for
4
- # fault-tolerant default gateway in IP routing environment.
5
- #
6
- # For more on HSRP packets, see http://www.networksorcery.com/enp/protocol/hsrp.htm
7
- #
8
- # Submitted by fropert@packetfault.org. Thanks, Francois!
9
- #
10
- # ==== Header Definition
11
- #
12
- # Int8 :hsrp_version Default: 0 # Version
13
- # Int8 :hsrp_opcode # Opcode
14
- # Int8 :hsrp_state # State
15
- # Int8 :hsrp_hellotime Default: 3 # Hello Time
16
- # Int8 :hsrp_holdtime Default: 10 # Hold Time
17
- # Int8 :hsrp_priority # Priority
18
- # Int8 :hsrp_group # Group
19
- # Int8 :hsrp_reserved Default: 0 # Reserved
20
- # String :hsrp_password # Authentication Data
21
- # Octets :hsrp_vip # Virtual IP Address
22
- # String :body
23
- class HSRPHeader < Struct.new(:hsrp_version, :hsrp_opcode, :hsrp_state,
24
- :hsrp_hellotime, :hsrp_holdtime,
25
- :hsrp_priority, :hsrp_group,
26
- :hsrp_reserved, :hsrp_password,
27
- :hsrp_vip, :body)
28
-
29
- include StructFu
1
+ require 'packetfu/protos/eth/header'
2
+ require 'packetfu/protos/eth/mixin'
30
3
 
31
- def initialize(args={})
32
- super(
33
- Int8.new(args[:hsrp_version] || 0),
34
- Int8.new(args[:hsrp_opcode]),
35
- Int8.new(args[:hsrp_state]),
36
- Int8.new(args[:hsrp_hellotime] || 3),
37
- Int8.new(args[:hsrp_holdtime] || 10),
38
- Int8.new(args[:hsrp_priority]),
39
- Int8.new(args[:hsrp_group]),
40
- Int8.new(args[:hsrp_reserved] || 0),
41
- StructFu::String.new.read(args[:hsrp_password] || "cisco\x00\x00\x00"),
42
- Octets.new.read(args[:hsrp_vip] || ("\x00" * 4)),
43
- StructFu::String.new.read(args[:body])
44
- )
45
- end
4
+ require 'packetfu/protos/ip/header'
5
+ require 'packetfu/protos/ip/mixin'
46
6
 
47
- # Returns the object in string form.
48
- def to_s
49
- self.to_a.map {|x| x.to_s}.join
50
- end
7
+ require 'packetfu/protos/udp/header'
8
+ require 'packetfu/protos/udp/mixin'
51
9
 
52
- # Reads a string to populate the object.
53
- def read(str)
54
- force_binary(str)
55
- return self if str.nil?
56
- self[:hsrp_version].read(str[0,1])
57
- self[:hsrp_opcode].read(str[1,1])
58
- self[:hsrp_state].read(str[2,1])
59
- self[:hsrp_hellotime].read(str[3,1])
60
- self[:hsrp_holdtime].read(str[4,1])
61
- self[:hsrp_priority].read(str[5,1])
62
- self[:hsrp_group].read(str[6,1])
63
- self[:hsrp_reserved].read(str[7,1])
64
- self[:hsrp_password].read(str[8,8])
65
- self[:hsrp_vip].read(str[16,4])
66
- self[:body].read(str[20,str.size]) if str.size > 20
67
- self
68
- end
69
-
70
- # Setter for the type.
71
- def hsrp_version=(i); typecast i; end
72
- # Getter for the type.
73
- def hsrp_version; self[:hsrp_version].to_i; end
74
- # Setter for the type.
75
- def hsrp_opcode=(i); typecast i; end
76
- # Getter for the type.
77
- def hsrp_opcode; self[:hsrp_opcode].to_i; end
78
- # Setter for the type.
79
- def hsrp_state=(i); typecast i; end
80
- # Getter for the type.
81
- def hsrp_state; self[:hsrp_state].to_i; end
82
- # Setter for the type.
83
- def hsrp_hellotime=(i); typecast i; end
84
- # Getter for the type.
85
- def hsrp_hellotime; self[:hsrp_hellotime].to_i; end
86
- # Setter for the type.
87
- def hsrp_holdtime=(i); typecast i; end
88
- # Getter for the type.
89
- def hsrp_holdtime; self[:hsrp_holdtime].to_i; end
90
- # Setter for the type.
91
- def hsrp_priority=(i); typecast i; end
92
- # Getter for the type.
93
- def hsrp_priority; self[:hsrp_priority].to_i; end
94
- # Setter for the type.
95
- def hsrp_group=(i); typecast i; end
96
- # Getter for the type.
97
- def hsrp_group; self[:hsrp_group].to_i; end
98
- # Setter for the type.
99
- def hsrp_reserved=(i); typecast i; end
100
- # Getter for the type.
101
- def hsrp_reserved; self[:hsrp_reserved].to_i; end
102
-
103
- def hsrp_addr=(addr)
104
- self[:hsrp_vip].read_quad(addr)
105
- end
106
-
107
- # Returns a more readable IP source address.
108
- def hsrp_addr
109
- self[:hsrp_vip].to_x
110
- end
111
-
112
- # Readability aliases
113
-
114
- alias :hsrp_vip_readable :hsrp_addr
115
-
116
- def hsrp_password_readable
117
- hsrp_password.to_s.inspect
118
- end
119
-
120
- end
10
+ require 'packetfu/protos/hsrp/header'
11
+ require 'packetfu/protos/hsrp/mixin'
121
12
 
13
+ module PacketFu
122
14
  # HSRPPacket is used to construct HSRP Packets. They contain an EthHeader, an IPHeader, and a UDPHeader.
123
15
  #
124
16
  # == Example
@@ -145,6 +37,10 @@ module PacketFu
145
37
  # :config
146
38
  # A hash of return address details, often the output of Utils.whoami?
147
39
  class HSRPPacket < Packet
40
+ include ::PacketFu::EthHeaderMixin
41
+ include ::PacketFu::IPHeaderMixin
42
+ include ::PacketFu::UDPHeaderMixin
43
+ include ::PacketFu::HSRPHeaderMixin
148
44
 
149
45
  attr_accessor :eth_header, :ip_header, :udp_header, :hsrp_header
150
46
 
@@ -165,12 +61,6 @@ module PacketFu
165
61
  def read(str=nil, args={})
166
62
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
167
63
  @eth_header.read(str)
168
- @ip_header.read(str[14,str.size])
169
- @eth_header.body = @ip_header
170
- @udp_header.read(str[14+(@ip_header.ip_hlen),str.size])
171
- @ip_header.body = @udp_header
172
- @hsrp_header.read(str[14+(@ip_header.ip_hlen)+8,str.size])
173
- @udp_header.body = @hsrp_header
174
64
  super(args)
175
65
  self
176
66
  end
@@ -0,0 +1,120 @@
1
+ module PacketFu
2
+ # HSRPHeader is a complete HSRP struct, used in HSRPPacket. HSRP is typically used for
3
+ # fault-tolerant default gateway in IP routing environment.
4
+ #
5
+ # For more on HSRP packets, see http://www.networksorcery.com/enp/protocol/hsrp.htm
6
+ #
7
+ # Submitted by fropert@packetfault.org. Thanks, Francois!
8
+ #
9
+ # ==== Header Definition
10
+ #
11
+ # Int8 :hsrp_version Default: 0 # Version
12
+ # Int8 :hsrp_opcode # Opcode
13
+ # Int8 :hsrp_state # State
14
+ # Int8 :hsrp_hellotime Default: 3 # Hello Time
15
+ # Int8 :hsrp_holdtime Default: 10 # Hold Time
16
+ # Int8 :hsrp_priority # Priority
17
+ # Int8 :hsrp_group # Group
18
+ # Int8 :hsrp_reserved Default: 0 # Reserved
19
+ # String :hsrp_password # Authentication Data
20
+ # Octets :hsrp_vip # Virtual IP Address
21
+ # String :body
22
+ class HSRPHeader < Struct.new(:hsrp_version, :hsrp_opcode, :hsrp_state,
23
+ :hsrp_hellotime, :hsrp_holdtime,
24
+ :hsrp_priority, :hsrp_group,
25
+ :hsrp_reserved, :hsrp_password,
26
+ :hsrp_vip, :body)
27
+
28
+ include StructFu
29
+
30
+ def initialize(args={})
31
+ super(
32
+ Int8.new(args[:hsrp_version] || 0),
33
+ Int8.new(args[:hsrp_opcode]),
34
+ Int8.new(args[:hsrp_state]),
35
+ Int8.new(args[:hsrp_hellotime] || 3),
36
+ Int8.new(args[:hsrp_holdtime] || 10),
37
+ Int8.new(args[:hsrp_priority]),
38
+ Int8.new(args[:hsrp_group]),
39
+ Int8.new(args[:hsrp_reserved] || 0),
40
+ StructFu::String.new.read(args[:hsrp_password] || "cisco\x00\x00\x00"),
41
+ Octets.new.read(args[:hsrp_vip] || ("\x00" * 4)),
42
+ StructFu::String.new.read(args[:body])
43
+ )
44
+ end
45
+
46
+ # Returns the object in string form.
47
+ def to_s
48
+ self.to_a.map {|x| x.to_s}.join
49
+ end
50
+
51
+ # Reads a string to populate the object.
52
+ def read(str)
53
+ force_binary(str)
54
+ return self if str.nil?
55
+ self[:hsrp_version].read(str[0,1])
56
+ self[:hsrp_opcode].read(str[1,1])
57
+ self[:hsrp_state].read(str[2,1])
58
+ self[:hsrp_hellotime].read(str[3,1])
59
+ self[:hsrp_holdtime].read(str[4,1])
60
+ self[:hsrp_priority].read(str[5,1])
61
+ self[:hsrp_group].read(str[6,1])
62
+ self[:hsrp_reserved].read(str[7,1])
63
+ self[:hsrp_password].read(str[8,8])
64
+ self[:hsrp_vip].read(str[16,4])
65
+ self[:body].read(str[20,str.size]) if str.size > 20
66
+ self
67
+ end
68
+
69
+ # Setter for the type.
70
+ def hsrp_version=(i); typecast i; end
71
+ # Getter for the type.
72
+ def hsrp_version; self[:hsrp_version].to_i; end
73
+ # Setter for the type.
74
+ def hsrp_opcode=(i); typecast i; end
75
+ # Getter for the type.
76
+ def hsrp_opcode; self[:hsrp_opcode].to_i; end
77
+ # Setter for the type.
78
+ def hsrp_state=(i); typecast i; end
79
+ # Getter for the type.
80
+ def hsrp_state; self[:hsrp_state].to_i; end
81
+ # Setter for the type.
82
+ def hsrp_hellotime=(i); typecast i; end
83
+ # Getter for the type.
84
+ def hsrp_hellotime; self[:hsrp_hellotime].to_i; end
85
+ # Setter for the type.
86
+ def hsrp_holdtime=(i); typecast i; end
87
+ # Getter for the type.
88
+ def hsrp_holdtime; self[:hsrp_holdtime].to_i; end
89
+ # Setter for the type.
90
+ def hsrp_priority=(i); typecast i; end
91
+ # Getter for the type.
92
+ def hsrp_priority; self[:hsrp_priority].to_i; end
93
+ # Setter for the type.
94
+ def hsrp_group=(i); typecast i; end
95
+ # Getter for the type.
96
+ def hsrp_group; self[:hsrp_group].to_i; end
97
+ # Setter for the type.
98
+ def hsrp_reserved=(i); typecast i; end
99
+ # Getter for the type.
100
+ def hsrp_reserved; self[:hsrp_reserved].to_i; end
101
+
102
+ def hsrp_addr=(addr)
103
+ self[:hsrp_vip].read_quad(addr)
104
+ end
105
+
106
+ # Returns a more readable IP source address.
107
+ def hsrp_addr
108
+ self[:hsrp_vip].to_x
109
+ end
110
+
111
+ # Readability aliases
112
+
113
+ alias :hsrp_vip_readable :hsrp_addr
114
+
115
+ def hsrp_password_readable
116
+ hsrp_password.to_s.inspect
117
+ end
118
+
119
+ end
120
+ end