packetfu 1.1.5 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -2
- data/.gitignore +1 -0
- data/LICENSE.txt +1 -1
- data/bench/after-2012-07-28.txt +25 -0
- data/bench/before-2012-07-28.txt +25 -0
- data/bench/benchit.rb +68 -0
- data/bench/calc_delta.rb +17 -0
- data/bench/octets.rb +22 -0
- data/bench/octets_after.txt +8 -0
- data/bench/octets_after_refactor.txt +8 -0
- data/bench/octets_before.txt +8 -0
- data/lib/packetfu.rb +8 -3
- data/lib/packetfu/packet.rb +2 -2
- data/lib/packetfu/pcap.rb +20 -4
- data/lib/packetfu/protos/arp.rb +7 -160
- data/lib/packetfu/protos/arp/header.rb +160 -0
- data/lib/packetfu/protos/arp/mixin.rb +38 -0
- data/lib/packetfu/protos/eth.rb +5 -247
- data/lib/packetfu/protos/eth/header.rb +247 -0
- data/lib/packetfu/protos/eth/mixin.rb +20 -0
- data/lib/packetfu/protos/hsrp.rb +13 -123
- data/lib/packetfu/protos/hsrp/header.rb +120 -0
- data/lib/packetfu/protos/hsrp/mixin.rb +31 -0
- data/lib/packetfu/protos/icmp.rb +10 -97
- data/lib/packetfu/protos/icmp/header.rb +93 -0
- data/lib/packetfu/protos/icmp/mixin.rb +17 -0
- data/lib/packetfu/protos/ip.rb +7 -295
- data/lib/packetfu/protos/ip/header.rb +335 -0
- data/lib/packetfu/protos/ip/mixin.rb +43 -0
- data/lib/packetfu/protos/ipv6.rb +7 -191
- data/lib/packetfu/protos/ipv6/header.rb +190 -0
- data/lib/packetfu/protos/ipv6/mixin.rb +31 -0
- data/lib/packetfu/protos/tcp.rb +13 -939
- data/lib/packetfu/protos/tcp/ecn.rb +42 -0
- data/lib/packetfu/protos/tcp/flags.rb +83 -0
- data/lib/packetfu/protos/tcp/header.rb +307 -0
- data/lib/packetfu/protos/tcp/hlen.rb +40 -0
- data/lib/packetfu/protos/tcp/mixin.rb +48 -0
- data/lib/packetfu/protos/tcp/option.rb +323 -0
- data/lib/packetfu/protos/tcp/options.rb +106 -0
- data/lib/packetfu/protos/tcp/reserved.rb +42 -0
- data/lib/packetfu/protos/udp.rb +12 -110
- data/lib/packetfu/protos/udp/header.rb +107 -0
- data/lib/packetfu/protos/udp/mixin.rb +23 -0
- data/lib/packetfu/utils.rb +24 -24
- data/lib/packetfu/version.rb +1 -1
- data/packetfu.gemspec +2 -2
- data/test/test_ip.rb +0 -19
- data/test/test_octets.rb +18 -21
- data/test/test_tcp.rb +10 -0
- data/test/test_udp.rb +17 -0
- 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
|
data/lib/packetfu/protos/hsrp.rb
CHANGED
@@ -1,124 +1,16 @@
|
|
1
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
48
|
-
|
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
|
-
|
53
|
-
|
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
|