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