HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-hsrp.c
blobe45c0788d080ea1c3d79b51c59bd9ff0a541765b
1 /* packet-hsrp.c
2 * Routines for the Cisco Hot Standby Router Protocol (HSRP)
4 * Heikki Vatiainen <hessu@cs.tut.fi>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Copied from packet-vrrp.c
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 * RFC 2281 describes opcodes 0 - 2
32 * Op Code 3: **** HSRP Interface State Advertisements ****
33 * http://www.cisco.com/en/US/products/sw/iosswrel/ps1834/products_feature_guide09186a00800e9763.html
35 * An HSRP interface-state advertisement is sent:
37 * * when HSRP on the interface enters or leaves the passive state
38 * * when a group on the interface learns a new Active router
39 * * periodically while the interface is in the passive state
41 * 1 2 3
42 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | Version | Op Code = 3 | TLV Type |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | TLV Length | State | Reserved |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * | Active Group Count | Passive Group Count |
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * | Reserved |
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * Passive Group Count: 2 octet
55 * A count of the number of passive groups on the interface. The range
56 * of values are 0-256.
58 * Active Group Count: 2 octet
60 * A count of the number of active groups on the interface. The range
61 * of values are 0-256.
64 * HSRP Version 2
65 * Ref. http://www.smartnetworks.jp/2006/02/hsrp_8_hsrp_version_2.html (Japanese Only)
67 * Group State TLV
69 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * | Type=1 | Length=40 | HSRP Version | Opcode |
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * | State | IP Version | Group Number |
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * | Identifier(6octets) |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * | Identifier | Priority(4octets) |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 * | Priority cont. | Hello Time(4octets) |
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 * | Hello Time cont. | Hold Time(4octets) |
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 * | Hold Time cont. | Virtual IP Address(16octets) |
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 * | Virtual IP Address cont. |
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 * | Virtual IP Address cont. |
88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * | Virtual IP Address cont. |
90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 * | Virtual IP Address cont. |
92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 * Interface State TLV
96 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
97 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 * | Type=2 | Length=4 | Active Groups |
99 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 * | Passive Groups |
101 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 * Text Authentication TLV
105 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 * | Type=3 | Length=8 | Authentication Data(8octets) |
108 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 * | Authentication Data cont. |
110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111 * | Authentication Data cont. |
112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 * MD5 Authentication TLV
116 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
117 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 * | Type=4 | Length | Algorithm | Padding |
119 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 * | Flags | IP Address(4octets) |
121 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 * | IP Address cont. | Key ID(4octets) |
123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 * | Key ID cont. | Authentication Data(16octets) |
125 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 * | Authentication Data cont. |
127 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 * | Authentication Data cont. |
129 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130 * | Authentication Data cont. |
131 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 * | Authentication Data cont. |
133 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 #include "config.h"
139 #include <string.h>
140 #include <glib.h>
141 #include <epan/packet.h>
142 #include <epan/to_str.h>
144 static gint proto_hsrp = -1;
145 static dissector_handle_t data_handle;
147 static gint hf_hsrp_version = -1;
148 static gint hf_hsrp_opcode = -1;
149 /* Opcode 0-2 */
150 static gint hf_hsrp_state = -1;
151 static gint hf_hsrp_hellotime = -1;
152 static gint hf_hsrp_holdtime = -1;
153 static gint hf_hsrp_priority = -1;
154 static gint hf_hsrp_group = -1;
155 static gint hf_hsrp_reserved = -1;
156 static gint hf_hsrp_auth_data = -1;
157 static gint hf_hsrp_virt_ip_addr = -1;
158 /* Advertise (3) */
159 static gint hf_hsrp_adv_type = -1;
160 static gint hf_hsrp_adv_length = -1;
161 static gint hf_hsrp_adv_state = -1;
162 static gint hf_hsrp_adv_reserved1 = -1;
163 static gint hf_hsrp_adv_activegrp = -1;
164 static gint hf_hsrp_adv_passivegrp = -1;
165 static gint hf_hsrp_adv_reserved2 = -1;
167 static gint ett_hsrp = -1;
169 /* HSRPv2 */
170 static gint hf_hsrp2_version = -1;
171 static gint hf_hsrp2_opcode = -1;
172 static gint hf_hsrp2_state = -1;
173 static gint hf_hsrp2_group_state_tlv = -1;
174 static gint hf_hsrp2_interface_state_tlv = -1;
175 static gint hf_hsrp2_text_auth_tlv = -1;
176 static gint hf_hsrp2_md5_auth_tlv = -1;
177 static gint hf_hsrp2_ipversion = -1;
178 static gint hf_hsrp2_hellotime = -1;
179 static gint hf_hsrp2_holdtime = -1;
180 static gint hf_hsrp2_priority = -1;
181 static gint hf_hsrp2_identifier = -1;
182 static gint hf_hsrp2_group = -1;
183 static gint hf_hsrp2_virt_ip_addr = -1;
184 static gint hf_hsrp2_virt_ip_addr_v6 = -1;
185 static gint hf_hsrp2_auth_data = -1;
186 static gint hf_hsrp2_active_group = -1;
187 static gint hf_hsrp2_passive_group = -1;
188 static gint hf_hsrp2_md5_algorithm = -1;
189 static gint hf_hsrp2_md5_flags = -1;
190 static gint hf_hsrp2_md5_ip_address= -1;
191 static gint hf_hsrp2_md5_key_id= -1;
192 static gint hf_hsrp2_md5_auth_data= -1;
194 static gint ett_hsrp2_group_state_tlv = -1;
195 static gint ett_hsrp2_interface_state_tlv = -1;
196 static gint ett_hsrp2_text_auth_tlv = -1;
197 static gint ett_hsrp2_md5_auth_tlv = -1;
199 #define UDP_PORT_HSRP 1985
200 #define UDP_PORT_HSRP2_V6 2029
201 #define HSRP_DST_IP_ADDR "224.0.0.2"
202 #define HSRP2_DST_IP_ADDR "224.0.0.102"
204 struct hsrp_packet { /* Multicast to 224.0.0.2, TTL 1, UDP, port 1985 */
205 guint8 version; /* RFC2281 describes version 0 */
206 guint8 opcode;
207 guint8 state;
208 #define HSRP_DEFAULT_HELLOTIME 3
209 guint8 hellotime; /* In seconds */
210 #define HSRP_DEFAULT_HOLDTIME 10
211 guint8 holdtime; /* In seconds */
212 guint8 priority; /* Higher is stronger, highest IP address tie-breaker */
213 guint8 group; /* Identifies the standby group */
214 guint8 reserved;
215 guint8 auth_data[8]; /* Clear-text password, recommended default is `cisco' */
216 guint32 virt_ip_addr; /* The virtual IP address used by this group */
219 struct hsrpv2_packet { /* Multicast to 224.0.0.102, TTL 1, UDP, port 1985 */
220 guint8 version;
221 guint8 opcode;
222 guint8 state;
223 #define HSRP2_DEFAULT_HELLOTIME 3000
224 guint32 hellotime; /* In msecs */
225 #define HSRP2_DEFAULT_HOLDTIME 10000
226 guint32 holdtime; /* In msecs */
227 guint32 priority; /* Higher is stronger, highest IP address tie-breaker */
228 guint16 group; /* Identifies the standby group */
229 guint8 identifier[6]; /* Identifier of sender's MAC address */
230 guint8 auth_data[8]; /* Clear-text password, recommended default is `cisco' */
231 gchar virt_ip_addr[16]; /* The virtual IPv4/IPv6 address used by this group */
232 guint8 md5_algorithm; /* MD5 Hash algorithm */
233 guint8 md5_flags; /* Undefined */
234 guint8 md5_ip_address; /* IP address of sender interface */
235 guint8 md5_key_id; /* Name of key chain */
236 guint8 md5_auth_data[16]; /* MD5 digest data */
239 #define HSRP_OPCODE_HELLO 0
240 #define HSRP_OPCODE_COUP 1
241 #define HSRP_OPCODE_RESIGN 2
242 #define HSRP_OPCODE_ADVERTISE 3
243 static const value_string hsrp_opcode_vals[] = {
244 {HSRP_OPCODE_HELLO, "Hello"},
245 {HSRP_OPCODE_COUP, "Coup"},
246 {HSRP_OPCODE_RESIGN, "Resign"},
247 {HSRP_OPCODE_ADVERTISE, "Advertise"},
248 {0, NULL}
251 #define HSRP_STATE_INITIAL 0
252 #define HSRP_STATE_LEARN 1
253 #define HSRP_STATE_LISTEN 2
254 #define HSRP_STATE_SPEAK 4
255 #define HSRP_STATE_STANDBY 8
256 #define HSRP_STATE_ACTIVE 16
257 static const value_string hsrp_state_vals[] = {
258 {HSRP_STATE_INITIAL, "Initial"},
259 {HSRP_STATE_LEARN, "Learn"},
260 {HSRP_STATE_LISTEN, "Listen"},
261 {HSRP_STATE_SPEAK, "Speak"},
262 {HSRP_STATE_STANDBY, "Standby"},
263 {HSRP_STATE_ACTIVE, "Active"},
264 {0, NULL}
267 #define HSRP_ADV_TYPE_INTSTATE 1
268 #define HSRP_ADV_TYPE_IPREDUN 2
269 static const value_string hsrp_adv_type_vals[] = {
270 {HSRP_ADV_TYPE_INTSTATE, "HSRP interface state"},
271 {HSRP_ADV_TYPE_IPREDUN, "IP redundancy"},
272 {0, NULL}
275 #define HSRP_ADV_STATE_DORMANT 1
276 #define HSRP_ADV_STATE_PASSIVE 2
277 #define HSRP_ADV_STATE_ACTIVE 3
278 static const value_string hsrp_adv_state_vals[] = {
279 {HSRP_ADV_STATE_DORMANT, "Dormant"},
280 {HSRP_ADV_STATE_PASSIVE, "Passive"},
281 {HSRP_ADV_STATE_ACTIVE, "Active"},
282 {0, NULL}
285 #define HSRP2_OPCODE_HELLO 0
286 #define HSRP2_OPCODE_COUP 1
287 #define HSRP2_OPCODE_RESIGN 2
288 static const value_string hsrp2_opcode_vals[] = {
289 {HSRP2_OPCODE_HELLO, "Hello"},
290 {HSRP2_OPCODE_COUP, "Coup"},
291 {HSRP2_OPCODE_RESIGN, "Resign"},
292 {0, NULL}
295 #define HSRP2_STATE_DISABLED 0
296 #define HSRP2_STATE_INIT 1
297 #define HSRP2_STATE_LEARN 2
298 #define HSRP2_STATE_LISTEN 3
299 #define HSRP2_STATE_SPEAK 4
300 #define HSRP2_STATE_STANDBY 5
301 #define HSRP2_STATE_ACTIVE 6
302 static const value_string hsrp2_state_vals[] = {
303 {HSRP2_STATE_INIT, "Init"},
304 {HSRP2_STATE_LEARN, "Learn"},
305 {HSRP2_STATE_LISTEN, "Listen"},
306 {HSRP2_STATE_SPEAK, "Speak"},
307 {HSRP2_STATE_STANDBY, "Standby"},
308 {HSRP2_STATE_ACTIVE, "Active"},
309 {0, NULL}
312 #define HSRP2_IPVERSION_IPV4 4
313 #define HSRP2_IPVERSION_IPV6 6
314 static const value_string hsrp2_ipversion_vals[] = {
315 {HSRP2_IPVERSION_IPV4, "IPv4"},
316 {HSRP2_IPVERSION_IPV6, "IPv6"},
317 {0, NULL}
320 #define HSRP2_MD5_ALGORITHM 1
321 static const value_string hsrp2_md5_algorithm_vals[] = {
322 {HSRP2_MD5_ALGORITHM, "MD5"},
323 {0, NULL}
326 static int
327 dissect_hsrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
329 tvbuff_t *next_tvb;
330 gchar dst[16];
332 /* Return if this isn't really HSRP traffic
333 * (source and destination port must be UDP_PORT_HSRP on HSRPv1 or HSRPv2(IPv4))
334 * (source and destination port must be UDP_PORT_HSRP2_V6 on HSRPv2(IPv6))
336 if(pinfo->destport != UDP_PORT_HSRP && pinfo->destport != UDP_PORT_HSRP2_V6)
337 return 0;
340 * To check whether this is an HSRPv1 packet or HSRPv2 on dest IPv4 addr.
342 address_to_str_buf(&(pinfo->dst), dst, sizeof dst);
344 if (pinfo->dst.type == AT_IPv4 && strcmp(dst,HSRP_DST_IP_ADDR) == 0) {
345 /* HSRPv1 */
346 guint8 opcode, state = 0;
348 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSRP");
350 opcode = tvb_get_guint8(tvb, 1);
351 col_set_str(pinfo->cinfo, COL_INFO,
352 val_to_str_const(opcode, hsrp_opcode_vals, "Unknown"));
354 if (opcode < 3) {
355 state = tvb_get_guint8(tvb, 2);
356 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
357 val_to_str_const(state, hsrp_state_vals, "Unknown"));
358 } else if (opcode == 3) {
359 state = tvb_get_guint8(tvb, 6);
360 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
361 val_to_str_const(state, hsrp_adv_state_vals, "Unknown"));
364 if (tree) {
365 proto_item *ti;
366 proto_tree *hsrp_tree;
367 gint offset;
368 guint8 hellotime, holdtime;
369 gchar auth_buf[8 + 1];
371 offset = 0;
372 ti = proto_tree_add_item(tree, proto_hsrp, tvb, offset, -1, ENC_NA);
373 hsrp_tree = proto_item_add_subtree(ti, ett_hsrp);
375 proto_tree_add_item(hsrp_tree, hf_hsrp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
376 offset++;
377 proto_tree_add_uint(hsrp_tree, hf_hsrp_opcode, tvb, offset, 1, opcode);
378 offset++;
379 if (opcode < 3) {
380 proto_tree_add_uint(hsrp_tree, hf_hsrp_state, tvb, offset, 1, state);
381 offset++;
382 hellotime = tvb_get_guint8(tvb, offset);
383 proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp_hellotime, tvb, offset, 1, hellotime,
384 "%sDefault (%u)",
385 (hellotime == HSRP_DEFAULT_HELLOTIME) ? "" : "Non-",
386 hellotime);
387 offset++;
388 holdtime = tvb_get_guint8(tvb, offset);
389 proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp_holdtime, tvb, offset, 1, holdtime,
390 "%sDefault (%u)",
391 (holdtime == HSRP_DEFAULT_HOLDTIME) ? "" : "Non-",
392 holdtime);
393 offset++;
394 proto_tree_add_item(hsrp_tree, hf_hsrp_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
395 offset++;
396 proto_tree_add_item(hsrp_tree, hf_hsrp_group, tvb, offset, 1, ENC_BIG_ENDIAN);
397 offset++;
398 proto_tree_add_item(hsrp_tree, hf_hsrp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
399 offset++;
400 tvb_memcpy(tvb, auth_buf, offset, 8);
401 auth_buf[sizeof auth_buf - 1] = '\0';
402 proto_tree_add_string_format_value(hsrp_tree, hf_hsrp_auth_data, tvb, offset, 8, auth_buf,
403 "%sDefault (%s)",
404 (tvb_strneql(tvb, offset, "cisco", strlen("cisco"))) == 0 ? "" : "Non-",
405 auth_buf);
406 offset += 8;
407 proto_tree_add_item(hsrp_tree, hf_hsrp_virt_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
408 /* offset += 4; */
409 } else if (opcode == 3) {
410 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
411 offset += 2;
412 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_length, tvb, offset, 2, ENC_BIG_ENDIAN);
413 offset += 2;
414 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_state, tvb, offset, 1, ENC_BIG_ENDIAN);
415 offset += 1;
416 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
417 offset += 1;
418 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_activegrp, tvb, offset, 2, ENC_BIG_ENDIAN);
419 offset += 2;
420 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_passivegrp, tvb, offset, 2, ENC_BIG_ENDIAN);
421 offset += 2;
422 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_reserved2, tvb, offset, 4, ENC_BIG_ENDIAN);
423 /* offset += 4; */
424 } else {
425 next_tvb = tvb_new_subset_remaining(tvb, offset);
426 call_dissector(data_handle, next_tvb, pinfo, hsrp_tree);
429 } else if ((pinfo->dst.type == AT_IPv4 && strcmp(dst,HSRP2_DST_IP_ADDR) == 0) ||
430 (pinfo->dst.type == AT_IPv6 && pinfo->destport == UDP_PORT_HSRP2_V6)) {
431 /* HSRPv2 */
432 guint offset = 0, offset2;
433 proto_item *ti = NULL;
434 proto_tree *hsrp_tree = NULL;
435 guint8 type,len;
437 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSRPv2");
439 if (tree) {
440 ti = proto_tree_add_item(tree, proto_hsrp, tvb, offset, -1, ENC_NA);
441 hsrp_tree = proto_item_add_subtree(ti, ett_hsrp);
444 while (tvb_reported_length_remaining(tvb, offset) > 0) {
445 type = tvb_get_guint8(tvb, offset);
446 len = tvb_get_guint8(tvb, offset+1);
448 offset2 = offset;
449 if (type == 1 && len == 40) {
450 /* Group State TLV */
451 guint8 opcode, state = 0, ipver;
452 guint32 hellotime, holdtime;
453 proto_tree *group_state_tlv;
455 if (tree) {
456 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_group_state_tlv, tvb, offset, 2, type,
457 "Type=%d Len=%d", type, len);
459 offset+=2;
461 opcode = tvb_get_guint8(tvb, offset+1);
462 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
463 val_to_str_const(opcode, hsrp2_opcode_vals, "Unknown"));
465 state = tvb_get_guint8(tvb, offset+2);
466 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
467 val_to_str_const(state, hsrp2_state_vals, "Unknown"));
469 if (tree) {
470 /* Making Group State TLV subtree. */
471 group_state_tlv = proto_item_add_subtree(ti, ett_hsrp2_group_state_tlv);
472 proto_tree_add_item(group_state_tlv, hf_hsrp2_version, tvb, offset, 1, ENC_BIG_ENDIAN);
473 offset++;
474 proto_tree_add_uint(group_state_tlv, hf_hsrp2_opcode, tvb, offset, 1, opcode);
475 offset++;
476 proto_tree_add_uint(group_state_tlv, hf_hsrp2_state, tvb, offset, 1, state);
477 offset++;
478 ipver = tvb_get_guint8(tvb, offset);
479 proto_tree_add_uint(group_state_tlv, hf_hsrp2_ipversion, tvb, offset, 1, ipver);
480 offset++;
481 proto_tree_add_item(group_state_tlv, hf_hsrp2_group, tvb, offset, 2, ENC_BIG_ENDIAN);
482 offset+=2;
483 proto_tree_add_item(group_state_tlv, hf_hsrp2_identifier, tvb, offset, 6, ENC_NA);
484 offset+=6;
485 proto_tree_add_item(group_state_tlv, hf_hsrp2_priority, tvb, offset, 4, ENC_BIG_ENDIAN);
486 offset+=4;
488 hellotime = tvb_get_ntohl(tvb, offset);
489 proto_tree_add_uint_format_value(group_state_tlv, hf_hsrp2_hellotime, tvb, offset, 4, hellotime,
490 "%sDefault (%u)",
491 (hellotime == HSRP2_DEFAULT_HELLOTIME) ? "" : "Non-",
492 hellotime);
493 offset+=4;
494 holdtime = tvb_get_ntohl(tvb, offset);
495 proto_tree_add_uint_format_value(group_state_tlv, hf_hsrp2_holdtime, tvb, offset, 4, holdtime,
496 "%sDefault (%u)",
497 (holdtime == HSRP2_DEFAULT_HOLDTIME) ? "" : "Non-",
498 holdtime);
499 offset+=4;
500 if (ipver == 4) {
501 /* Fetch Virtual IP as IPv4 */
502 proto_tree_add_item(group_state_tlv, hf_hsrp2_virt_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
503 } else if (ipver == 6) {
504 /* Fetch Virtual IP as IPv6 */
505 proto_tree_add_item(group_state_tlv, hf_hsrp2_virt_ip_addr_v6, tvb, offset, 16, ENC_NA);
506 } else {
507 /* Unknown protocol */
508 next_tvb = tvb_new_subset_remaining(tvb, offset);
509 call_dissector(data_handle, next_tvb, pinfo, hsrp_tree);
510 break;
512 /* offset+=16; */
514 } else if (type == 2 && len == 4) {
515 /* Interface State TLV */
516 guint16 active,passive;
517 active = tvb_get_ntohs(tvb, offset+2);
518 passive = tvb_get_ntohs(tvb, offset+4);
520 col_add_fstr(pinfo->cinfo, COL_INFO, "Interface State TLV (Act=%d Pass=%d)",active,passive);
522 if (tree) {
523 proto_tree *interface_state_tlv;
524 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_interface_state_tlv, tvb, offset, 1, type,
525 "Type=%d Len=%d", type, len);
526 offset+=2;
528 /* Making Interface State TLV subtree */
529 interface_state_tlv = proto_item_add_subtree(ti, ett_hsrp2_interface_state_tlv);
530 proto_tree_add_item(interface_state_tlv, hf_hsrp2_active_group, tvb, offset, 2, ENC_BIG_ENDIAN);
531 offset+=2;
532 proto_tree_add_item(interface_state_tlv, hf_hsrp2_passive_group, tvb, offset, 2, ENC_BIG_ENDIAN);
533 /* offset+=2; */
535 } else if (type == 3 && len == 8) {
536 /* Text Authentication TLV */
537 if (tree) {
538 proto_tree *text_auth_tlv;
539 gchar auth_buf[8 + 1];
541 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_text_auth_tlv, tvb, offset, 1, type,
542 "Type=%d Len=%d", type, len);
543 offset+=2;
545 /* Making Text Authentication TLV subtree */
546 text_auth_tlv = proto_item_add_subtree(ti, ett_hsrp2_text_auth_tlv);
548 tvb_memcpy(tvb, auth_buf, offset, 8);
549 auth_buf[sizeof auth_buf - 1] = '\0';
550 proto_tree_add_string_format_value(text_auth_tlv, hf_hsrp2_auth_data, tvb, offset, 8, auth_buf,
551 "%sDefault (%s)",
552 (tvb_strneql(tvb, offset, "cisco", strlen("cisco"))) == 0 ? "" : "Non-",
553 auth_buf);
554 /* offset += 8; */
556 } else if (type == 4 && len == 28) {
557 /* MD5 Authentication TLV */
558 if (tree) {
559 proto_tree *md5_auth_tlv;
561 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_md5_auth_tlv, tvb, offset, 1, type,
562 "Type=%d Len=%d", type, len);
563 offset+=2;
565 /* Making MD5 Authentication TLV subtree */
566 md5_auth_tlv = proto_item_add_subtree(ti, ett_hsrp2_md5_auth_tlv);
567 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_algorithm, tvb, offset, 1, ENC_BIG_ENDIAN);
568 offset++;
569 /* Skip padding field */
570 offset++;
571 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
572 offset+=2;
573 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN);
574 offset+=4;
575 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_key_id, tvb, offset, 4, ENC_BIG_ENDIAN);
576 offset+=4;
577 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_auth_data, tvb, offset, 16, ENC_NA);
578 /* offset += 16; */
580 } else {
581 /* Undefined TLV */
582 if (tree) {
583 next_tvb = tvb_new_subset_remaining(tvb, offset);
584 call_dissector(data_handle, next_tvb, pinfo, hsrp_tree);
586 break;
588 offset = offset2+len+2;
592 return tvb_length(tvb);
595 void proto_register_hsrp(void)
597 static hf_register_info hf[] = {
598 { &hf_hsrp_version,
599 { "Version", "hsrp.version",
600 FT_UINT8, BASE_DEC, NULL, 0x0,
601 "The version of the HSRP messages", HFILL }},
603 { &hf_hsrp_opcode,
604 { "Op Code", "hsrp.opcode",
605 FT_UINT8, BASE_DEC, VALS(hsrp_opcode_vals), 0x0,
606 "The type of message contained in this packet", HFILL }},
608 { &hf_hsrp_state,
609 { "State", "hsrp.state",
610 FT_UINT8, BASE_DEC, VALS(hsrp_state_vals), 0x0,
611 "The current state of the router sending the message", HFILL }},
613 { &hf_hsrp_hellotime,
614 { "Hellotime", "hsrp.hellotime",
615 FT_UINT8, BASE_DEC, NULL, 0x0,
616 "The approximate period between the Hello messages that the router sends", HFILL }},
618 { &hf_hsrp_holdtime,
619 { "Holdtime", "hsrp.holdtime",
620 FT_UINT8, BASE_DEC, NULL, 0x0,
621 "Time that the current Hello message should be considered valid", HFILL }},
623 { &hf_hsrp_priority,
624 { "Priority", "hsrp.priority",
625 FT_UINT8, BASE_DEC, NULL, 0x0,
626 "Used to elect the active and standby routers. Numerically higher priority wins vote", HFILL }},
628 { &hf_hsrp_group,
629 { "Group", "hsrp.group",
630 FT_UINT8, BASE_DEC, NULL, 0x0,
631 "This field identifies the standby group", HFILL }},
633 { &hf_hsrp_reserved,
634 { "Reserved", "hsrp.reserved",
635 FT_UINT8, BASE_DEC, NULL, 0x0,
636 NULL, HFILL }},
638 { &hf_hsrp_auth_data,
639 { "Authentication Data", "hsrp.auth_data",
640 FT_STRING, BASE_NONE, NULL, 0x0,
641 "Contains a clear-text 8 character reused password", HFILL }},
643 { &hf_hsrp_virt_ip_addr,
644 { "Virtual IP Address", "hsrp.virt_ip",
645 FT_IPv4, BASE_NONE, NULL, 0x0,
646 "The virtual IP address used by this group", HFILL }},
648 { &hf_hsrp_adv_type,
649 { "Adv type", "hsrp.adv.tlvtype",
650 FT_UINT16, BASE_DEC, VALS(hsrp_adv_type_vals), 0x0,
651 "Advertisement tlv type", HFILL }},
653 { &hf_hsrp_adv_length,
654 { "Adv length", "hsrp.adv.tlvlength",
655 FT_UINT16, BASE_DEC, NULL, 0x0,
656 "Advertisement tlv length", HFILL }},
658 { &hf_hsrp_adv_state,
659 { "Adv state", "hsrp.adv.state",
660 FT_UINT8, BASE_DEC, VALS(hsrp_adv_state_vals), 0x0,
661 "Advertisement tlv length", HFILL }},
663 { &hf_hsrp_adv_reserved1,
664 { "Adv reserved1", "hsrp.adv.reserved1",
665 FT_UINT8, BASE_DEC, NULL, 0x0,
666 "Advertisement tlv length", HFILL }},
668 { &hf_hsrp_adv_activegrp,
669 { "Adv active groups", "hsrp.adv.activegrp",
670 FT_UINT8, BASE_DEC, NULL, 0x0,
671 "Advertisement active group count", HFILL }},
673 { &hf_hsrp_adv_passivegrp,
674 { "Adv passive groups", "hsrp.adv.passivegrp",
675 FT_UINT8, BASE_DEC, NULL, 0x0,
676 "Advertisement passive group count", HFILL }},
678 { &hf_hsrp_adv_reserved2,
679 { "Adv reserved2", "hsrp.adv.reserved2",
680 FT_UINT32, BASE_DEC, NULL, 0x0,
681 "Advertisement tlv length", HFILL }},
683 { &hf_hsrp2_version,
684 { "Version", "hsrp2.version",
685 FT_UINT8, BASE_DEC, NULL, 0x0,
686 "The version of the HSRP messages", HFILL }},
688 { &hf_hsrp2_opcode,
689 { "Op Code", "hsrp2.opcode",
690 FT_UINT8, BASE_DEC, VALS(hsrp2_opcode_vals), 0x0,
691 "The type of message contained in this packet", HFILL }},
693 { &hf_hsrp2_state,
694 { "State", "hsrp2.state",
695 FT_UINT8, BASE_DEC, VALS(hsrp2_state_vals), 0x0,
696 "The current state of the router sending the message", HFILL }},
698 { &hf_hsrp2_group_state_tlv,
699 { "Group State TLV", "hsrp2.group_state_tlv",
700 FT_UINT8, BASE_DEC, NULL, 0x0,
701 NULL, HFILL }},
703 { &hf_hsrp2_interface_state_tlv,
704 { "Interface State TLV", "hsrp2.interface_state_tlv",
705 FT_UINT8, BASE_DEC, NULL, 0x0,
706 NULL, HFILL }},
708 { &hf_hsrp2_text_auth_tlv,
709 { "Text Authentication TLV", "hsrp2.text_auth_tlv",
710 FT_UINT8, BASE_DEC, NULL, 0x0,
711 NULL, HFILL }},
713 { &hf_hsrp2_md5_auth_tlv,
714 { "MD5 Authentication TLV", "hsrp2.md5_auth_tlv",
715 FT_UINT8, BASE_DEC, NULL, 0x0,
716 NULL, HFILL }},
718 { &hf_hsrp2_ipversion,
719 { "IP Ver.", "hsrp2.ipversion",
720 FT_UINT8, BASE_DEC, VALS(hsrp2_ipversion_vals), 0x0,
721 "The IP protocol version used in this hsrp message", HFILL }},
723 { &hf_hsrp2_group,
724 { "Group", "hsrp2.group",
725 FT_UINT16, BASE_DEC, NULL, 0x0,
726 "This field identifies the standby group", HFILL }},
728 { &hf_hsrp2_identifier,
729 { "Identifier", "hsrp2.identifier",
730 FT_ETHER, BASE_NONE, NULL, 0x0,
731 "BIA value of a sender interface", HFILL }},
733 { &hf_hsrp2_hellotime,
734 { "Hellotime", "hsrp2.hellotime",
735 FT_UINT32, BASE_DEC, NULL, 0x0,
736 "The approximate period between the Hello messages that the router sends", HFILL }},
738 { &hf_hsrp2_holdtime,
739 { "Holdtime", "hsrp2.holdtime",
740 FT_UINT32, BASE_DEC, NULL, 0x0,
741 "Time that the current Hello message should be considered valid", HFILL }},
743 { &hf_hsrp2_priority,
744 { "Priority", "hsrp2.priority",
745 FT_UINT32, BASE_DEC, NULL, 0x0,
746 "Used to elect the active and standby routers. Numerically higher priority wins vote", HFILL }},
748 { &hf_hsrp2_auth_data,
749 { "Authentication Data", "hsrp2.auth_data",
750 FT_STRING, BASE_NONE, NULL, 0x0,
751 "Contains a clear-text 8 character reused password", HFILL }},
753 { &hf_hsrp2_virt_ip_addr,
754 { "Virtual IP Address", "hsrp2.virt_ip",
755 FT_IPv4, BASE_NONE, NULL, 0x0,
756 "The virtual IP address used by this group", HFILL }},
758 { &hf_hsrp2_virt_ip_addr_v6,
759 { "Virtual IPv6 Address", "hsrp2.virt_ip_v6",
760 FT_IPv6, BASE_NONE, NULL, 0x0,
761 "The virtual IPv6 address used by this group", HFILL }},
763 { &hf_hsrp2_active_group,
764 { "Active Groups", "hsrp2.active_groups",
765 FT_UINT16, BASE_DEC, NULL, 0x0,
766 "Active group number which becomes the active router myself", HFILL }},
768 { &hf_hsrp2_passive_group,
769 { "Passive Groups", "hsrp2.passive_groups",
770 FT_UINT16, BASE_DEC, NULL, 0x0,
771 "Standby group number which doesn't become the active router myself", HFILL }},
773 { &hf_hsrp2_md5_algorithm,
774 { "MD5 Algorithm", "hsrp2.md5_algorithm",
775 FT_UINT8, BASE_DEC, VALS(hsrp2_md5_algorithm_vals), 0x0,
776 "Hash Algorithm used by this group", HFILL }},
778 { &hf_hsrp2_md5_flags,
779 { "MD5 Flags", "hsrp2.md5_flags",
780 FT_UINT8, BASE_DEC, NULL, 0x0,
781 "Undefined", HFILL }},
783 { &hf_hsrp2_md5_ip_address,
784 { "Sender's IP Address", "hsrp.md5_ip_address",
785 FT_IPv4, BASE_NONE, NULL, 0x0,
786 "IP Address of the sender interface", HFILL }},
788 { &hf_hsrp2_md5_key_id,
789 { "MD5 Key ID", "hsrp2.md5_key_id",
790 FT_UINT32, BASE_DEC, NULL, 0x0,
791 "This field contains Key chain ID", HFILL }},
793 { &hf_hsrp2_md5_auth_data,
794 { "MD5 Authentication Data", "hsrp2.md5_auth_data",
795 FT_BYTES, BASE_NONE, NULL, 0x0,
796 "MD5 digest string is contained.", HFILL }}
799 static gint *ett[] = {
800 &ett_hsrp,
801 &ett_hsrp2_group_state_tlv,
802 &ett_hsrp2_interface_state_tlv,
803 &ett_hsrp2_text_auth_tlv,
804 &ett_hsrp2_md5_auth_tlv
807 proto_hsrp = proto_register_protocol("Cisco Hot Standby Router Protocol",
808 "HSRP", "hsrp");
809 proto_register_field_array(proto_hsrp, hf, array_length(hf));
810 proto_register_subtree_array(ett, array_length(ett));
812 return;
815 void
816 proto_reg_handoff_hsrp(void)
818 dissector_handle_t hsrp_handle;
820 data_handle = find_dissector("data");
821 hsrp_handle = new_create_dissector_handle(dissect_hsrp, proto_hsrp);
822 dissector_add_uint("udp.port", UDP_PORT_HSRP, hsrp_handle);
823 dissector_add_uint("udp.port", UDP_PORT_HSRP2_V6, hsrp_handle);
827 * Editor modelines - http://www.wireshark.org/tools/modelines.html
829 * Local variables:
830 * c-basic-offset: 8
831 * tab-width: 8
832 * indent-tabs-mode: t
833 * End:
835 * vi: set shiftwidth=8 tabstop=8 expandtab:
836 * :indentSize=8:tabSize=8:noTabs=true: