Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-hsrp.c
blobb4a6d44e94e05cb78c088db0939b7375f856b17a
1 /* packet-hsrp.c
2 * Routines for the Cisco Hot Standby Router Protocol (HSRP)
4 * Heikki Vatiainen <hessu@cs.tut.fi>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copied from packet-vrrp.c
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 * RFC 2281 describes opcodes 0 - 2
18 * Op Code 3: **** HSRP Interface State Advertisements ****
19 * http://www.cisco.com/en/US/products/sw/iosswrel/ps1834/products_feature_guide09186a00800e9763.html
21 * An HSRP interface-state advertisement is sent:
23 * * when HSRP on the interface enters or leaves the passive state
24 * * when a group on the interface learns a new Active router
25 * * periodically while the interface is in the passive state
27 * 1 2 3
28 * 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
29 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 * | Version | Op Code = 3 | TLV Type |
31 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 * | TLV Length | State | Reserved |
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | Active Group Count | Passive Group Count |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | Reserved |
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * Passive Group Count: 2 octet
41 * A count of the number of passive groups on the interface. The range
42 * of values are 0-256.
44 * Active Group Count: 2 octet
46 * A count of the number of active groups on the interface. The range
47 * of values are 0-256.
50 * HSRP Version 2
51 * Ref. http://www.smartnetworks.jp/2006/02/hsrp_8_hsrp_version_2.html (Japanese Only)
53 * Group State TLV
55 * 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
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * | Type=1 | Length=40 | HSRP Version | Opcode |
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 * | State | IP Version | Group Number |
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | Identifier(6octets) |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * | Identifier | Priority(4octets) |
64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 * | Priority cont. | Hello Time(4octets) |
66 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67 * | Hello Time cont. | Hold Time(4octets) |
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | Hold Time cont. | Virtual IP Address(16octets) |
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * | Virtual IP Address cont. |
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * | Virtual IP Address cont. |
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * | Virtual IP Address cont. |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * | Virtual IP Address cont. |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 * Interface State TLV
82 * 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
83 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 * | Type=2 | Length=4 | Active Groups |
85 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 * | Passive Groups |
87 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * Text Authentication TLV
91 * 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
92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 * | Type=3 | Length=8 | Authentication Data(8octets) |
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 * | Authentication Data cont. |
96 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 * | Authentication Data cont. |
98 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 * MD5 Authentication TLV
102 * 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
103 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 * | Type=4 | Length | Algorithm | Padding |
105 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 * | Flags | IP Address(4octets) |
107 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 * | IP Address cont. | Key ID(4octets) |
109 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 * | Key ID cont. | Authentication Data(16octets) |
111 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 * | Authentication Data cont. |
113 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 * | Authentication Data cont. |
115 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 * | Authentication Data cont. |
117 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 * | Authentication Data cont. |
119 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 #include "config.h"
125 #include <epan/packet.h>
126 #include <epan/to_str.h>
127 #include <epan/expert.h>
129 void proto_register_hsrp(void);
130 void proto_reg_handoff_hsrp(void);
132 static dissector_handle_t hsrp_handle;
134 static int proto_hsrp;
136 static int hf_hsrp_version;
137 static int hf_hsrp_opcode;
138 /* Opcode 0-2 */
139 static int hf_hsrp_state;
140 static int hf_hsrp_hellotime;
141 static int hf_hsrp_holdtime;
142 static int hf_hsrp_priority;
143 static int hf_hsrp_group;
144 static int hf_hsrp_reserved;
145 static int hf_hsrp_auth_data;
146 static int hf_hsrp_virt_ip_addr;
147 /* Advertise (3) */
148 static int hf_hsrp_adv_type;
149 static int hf_hsrp_adv_length;
150 static int hf_hsrp_adv_state;
151 static int hf_hsrp_adv_reserved1;
152 static int hf_hsrp_adv_activegrp;
153 static int hf_hsrp_adv_passivegrp;
154 static int hf_hsrp_adv_reserved2;
156 static int ett_hsrp;
158 /* HSRPv2 */
159 static int hf_hsrp2_version;
160 static int hf_hsrp2_opcode;
161 static int hf_hsrp2_state;
162 static int hf_hsrp2_group_state_tlv;
163 static int hf_hsrp2_interface_state_tlv;
164 static int hf_hsrp2_text_auth_tlv;
165 static int hf_hsrp2_md5_auth_tlv;
166 static int hf_hsrp2_ipversion;
167 static int hf_hsrp2_hellotime;
168 static int hf_hsrp2_holdtime;
169 static int hf_hsrp2_priority;
170 static int hf_hsrp2_identifier;
171 static int hf_hsrp2_group;
172 static int hf_hsrp2_virt_ip_addr;
173 static int hf_hsrp2_virt_ip_addr_v6;
174 static int hf_hsrp2_auth_data;
175 static int hf_hsrp2_active_group;
176 static int hf_hsrp2_passive_group;
177 static int hf_hsrp2_md5_algorithm;
178 static int hf_hsrp2_md5_padding;
179 static int hf_hsrp2_md5_flags;
180 static int hf_hsrp2_md5_ip_address;
181 static int hf_hsrp2_md5_key_id;
182 static int hf_hsrp2_md5_auth_data;
184 static int ett_hsrp2_group_state_tlv;
185 static int ett_hsrp2_interface_state_tlv;
186 static int ett_hsrp2_text_auth_tlv;
187 static int ett_hsrp2_md5_auth_tlv;
189 static expert_field ei_hsrp_unknown_tlv;
191 #define UDP_PORT_HSRP 1985
192 #define UDP_PORT_HSRP2_V6 2029
193 #define UDP_PORT_HSRP_RANGE "1985,2029"
194 #define HSRP_DST_IP_ADDR 0xE0000002
195 #define HSRP2_DST_IP_ADDR 0xE0000066
197 struct hsrp_packet { /* Multicast to 224.0.0.2, TTL 1, UDP, port 1985 */
198 uint8_t version; /* RFC2281 describes version 0 */
199 uint8_t opcode;
200 uint8_t state;
201 #define HSRP_DEFAULT_HELLOTIME 3
202 uint8_t hellotime; /* In seconds */
203 #define HSRP_DEFAULT_HOLDTIME 10
204 uint8_t holdtime; /* In seconds */
205 uint8_t priority; /* Higher is stronger, highest IP address tie-breaker */
206 uint8_t group; /* Identifies the standby group */
207 uint8_t reserved;
208 uint8_t auth_data[8]; /* Clear-text password, recommended default is `cisco' */
209 uint32_t virt_ip_addr; /* The virtual IP address used by this group */
212 struct hsrpv2_packet { /* Multicast to 224.0.0.102, TTL 1, UDP, port 1985 */
213 uint8_t version;
214 uint8_t opcode;
215 uint8_t state;
216 #define HSRP2_DEFAULT_HELLOTIME 3000
217 uint32_t hellotime; /* In msecs */
218 #define HSRP2_DEFAULT_HOLDTIME 10000
219 uint32_t holdtime; /* In msecs */
220 uint32_t priority; /* Higher is stronger, highest IP address tie-breaker */
221 uint16_t group; /* Identifies the standby group */
222 uint8_t identifier[6]; /* Identifier of sender's MAC address */
223 uint8_t auth_data[8]; /* Clear-text password, recommended default is `cisco' */
224 char virt_ip_addr[16]; /* The virtual IPv4/IPv6 address used by this group */
225 uint8_t md5_algorithm; /* MD5 Hash algorithm */
226 uint8_t md5_flags; /* Undefined */
227 uint8_t md5_ip_address; /* IP address of sender interface */
228 uint8_t md5_key_id; /* Name of key chain */
229 uint8_t md5_auth_data[16]; /* MD5 digest data */
232 #define HSRP_OPCODE_HELLO 0
233 #define HSRP_OPCODE_COUP 1
234 #define HSRP_OPCODE_RESIGN 2
235 #define HSRP_OPCODE_ADVERTISE 3
236 static const value_string hsrp_opcode_vals[] = {
237 {HSRP_OPCODE_HELLO, "Hello"},
238 {HSRP_OPCODE_COUP, "Coup"},
239 {HSRP_OPCODE_RESIGN, "Resign"},
240 {HSRP_OPCODE_ADVERTISE, "Advertise"},
241 {0, NULL}
244 #define HSRP_STATE_INITIAL 0
245 #define HSRP_STATE_LEARN 1
246 #define HSRP_STATE_LISTEN 2
247 #define HSRP_STATE_SPEAK 4
248 #define HSRP_STATE_STANDBY 8
249 #define HSRP_STATE_ACTIVE 16
250 static const value_string hsrp_state_vals[] = {
251 {HSRP_STATE_INITIAL, "Initial"},
252 {HSRP_STATE_LEARN, "Learn"},
253 {HSRP_STATE_LISTEN, "Listen"},
254 {HSRP_STATE_SPEAK, "Speak"},
255 {HSRP_STATE_STANDBY, "Standby"},
256 {HSRP_STATE_ACTIVE, "Active"},
257 {0, NULL}
260 #define HSRP_ADV_TYPE_INTSTATE 1
261 #define HSRP_ADV_TYPE_IPREDUN 2
262 static const value_string hsrp_adv_type_vals[] = {
263 {HSRP_ADV_TYPE_INTSTATE, "HSRP interface state"},
264 {HSRP_ADV_TYPE_IPREDUN, "IP redundancy"},
265 {0, NULL}
268 #define HSRP_ADV_STATE_DORMANT 1
269 #define HSRP_ADV_STATE_PASSIVE 2
270 #define HSRP_ADV_STATE_ACTIVE 3
271 static const value_string hsrp_adv_state_vals[] = {
272 {HSRP_ADV_STATE_DORMANT, "Dormant"},
273 {HSRP_ADV_STATE_PASSIVE, "Passive"},
274 {HSRP_ADV_STATE_ACTIVE, "Active"},
275 {0, NULL}
278 #define HSRP2_OPCODE_HELLO 0
279 #define HSRP2_OPCODE_COUP 1
280 #define HSRP2_OPCODE_RESIGN 2
281 static const value_string hsrp2_opcode_vals[] = {
282 {HSRP2_OPCODE_HELLO, "Hello"},
283 {HSRP2_OPCODE_COUP, "Coup"},
284 {HSRP2_OPCODE_RESIGN, "Resign"},
285 {0, NULL}
288 #define HSRP2_STATE_DISABLED 0
289 #define HSRP2_STATE_INIT 1
290 #define HSRP2_STATE_LEARN 2
291 #define HSRP2_STATE_LISTEN 3
292 #define HSRP2_STATE_SPEAK 4
293 #define HSRP2_STATE_STANDBY 5
294 #define HSRP2_STATE_ACTIVE 6
295 static const value_string hsrp2_state_vals[] = {
296 {HSRP2_STATE_INIT, "Init"},
297 {HSRP2_STATE_LEARN, "Learn"},
298 {HSRP2_STATE_LISTEN, "Listen"},
299 {HSRP2_STATE_SPEAK, "Speak"},
300 {HSRP2_STATE_STANDBY, "Standby"},
301 {HSRP2_STATE_ACTIVE, "Active"},
302 {0, NULL}
305 #define HSRP2_IPVERSION_IPV4 4
306 #define HSRP2_IPVERSION_IPV6 6
307 static const value_string hsrp2_ipversion_vals[] = {
308 {HSRP2_IPVERSION_IPV4, "IPv4"},
309 {HSRP2_IPVERSION_IPV6, "IPv6"},
310 {0, NULL}
313 #define HSRP2_MD5_ALGORITHM 1
314 static const value_string hsrp2_md5_algorithm_vals[] = {
315 {HSRP2_MD5_ALGORITHM, "MD5"},
316 {0, NULL}
319 static void
320 process_hsrp_md5_tlv_sequence(tvbuff_t *tvb, proto_tree *hsrp_tree, unsigned offset)
322 uint8_t type = tvb_get_uint8(tvb, offset);
323 uint8_t len = tvb_get_uint8(tvb, offset+1);
324 proto_item *ti;
325 proto_tree *md5_auth_tlv;
327 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_md5_auth_tlv, tvb, offset, 2+len, type, "Type=%d Len=%d", type, len);
328 offset+=2;
330 /* Making MD5 Authentication TLV subtree */
331 md5_auth_tlv = proto_item_add_subtree(ti, ett_hsrp2_md5_auth_tlv);
332 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_algorithm, tvb, offset, 1, ENC_BIG_ENDIAN);
333 offset++;
334 /* padding field */
335 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_padding, tvb, offset, 1, ENC_BIG_ENDIAN);
336 offset++;
337 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
338 offset+=2;
339 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN);
340 offset+=4;
341 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_key_id, tvb, offset, 4, ENC_BIG_ENDIAN);
342 offset+=4; /* this now points to the start of the MD5 hash */
343 proto_tree_add_item(md5_auth_tlv, hf_hsrp2_md5_auth_data, tvb, offset, 16, ENC_NA);
346 static int
347 dissect_hsrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
349 tvbuff_t *next_tvb;
350 uint32_t hsrpv1 = g_htonl(HSRP_DST_IP_ADDR),
351 hsrpv2 = g_htonl(HSRP2_DST_IP_ADDR);
353 /* Return if this isn't really HSRP traffic
354 * (source and destination port must be UDP_PORT_HSRP on HSRPv1 or HSRPv2(IPv4))
355 * (source and destination port must be UDP_PORT_HSRP2_V6 on HSRPv2(IPv6))
357 if(pinfo->destport != UDP_PORT_HSRP && pinfo->destport != UDP_PORT_HSRP2_V6)
358 return 0;
361 * To check whether this is an HSRPv1 packet or HSRPv2 on dest IPv4 addr.
363 if (pinfo->dst.type == AT_IPv4 && memcmp(pinfo->dst.data, &hsrpv1, 4) == 0) {
364 /* HSRPv1 */
365 uint8_t opcode, state = 0;
366 proto_item *ti;
367 proto_tree *hsrp_tree;
368 int offset;
369 uint8_t hellotime, holdtime;
370 char *auth;
372 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSRP");
374 opcode = tvb_get_uint8(tvb, 1);
375 col_set_str(pinfo->cinfo, COL_INFO,
376 val_to_str_const(opcode, hsrp_opcode_vals, "Unknown"));
378 if (opcode < 3) {
379 state = tvb_get_uint8(tvb, 2);
380 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
381 val_to_str_const(state, hsrp_state_vals, "Unknown"));
382 } else if (opcode == 3) {
383 state = tvb_get_uint8(tvb, 6);
384 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
385 val_to_str_const(state, hsrp_adv_state_vals, "Unknown"));
388 offset = 0;
389 ti = proto_tree_add_item(tree, proto_hsrp, tvb, offset, -1, ENC_NA);
390 hsrp_tree = proto_item_add_subtree(ti, ett_hsrp);
392 proto_tree_add_item(hsrp_tree, hf_hsrp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
393 offset++;
394 proto_tree_add_uint(hsrp_tree, hf_hsrp_opcode, tvb, offset, 1, opcode);
395 offset++;
396 if (opcode < 3) {
397 proto_tree_add_uint(hsrp_tree, hf_hsrp_state, tvb, offset, 1, state);
398 offset++;
399 hellotime = tvb_get_uint8(tvb, offset);
400 proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp_hellotime, tvb, offset, 1, hellotime,
401 "%sDefault (%u)",
402 (hellotime == HSRP_DEFAULT_HELLOTIME) ? "" : "Non-",
403 hellotime);
404 offset++;
405 holdtime = tvb_get_uint8(tvb, offset);
406 proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp_holdtime, tvb, offset, 1, holdtime,
407 "%sDefault (%u)",
408 (holdtime == HSRP_DEFAULT_HOLDTIME) ? "" : "Non-",
409 holdtime);
410 offset++;
411 proto_tree_add_item(hsrp_tree, hf_hsrp_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
412 offset++;
413 proto_tree_add_item(hsrp_tree, hf_hsrp_group, tvb, offset, 1, ENC_BIG_ENDIAN);
414 offset++;
415 proto_tree_add_item(hsrp_tree, hf_hsrp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
416 offset++;
417 auth = (char *) tvb_get_string_enc(pinfo->pool, tvb, offset, 8, ENC_ASCII|ENC_NA);
418 proto_tree_add_string_format_value(hsrp_tree, hf_hsrp_auth_data, tvb, offset, 8, auth,
419 "%sDefault (%s)",
420 (strcmp(auth, "cisco") == 0) ? "" : "Non-",
421 auth);
422 offset += 8;
423 proto_tree_add_item(hsrp_tree, hf_hsrp_virt_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
424 /* offset += 4; */
425 } else if (opcode == 3) {
426 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
427 offset += 2;
428 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_length, tvb, offset, 2, ENC_BIG_ENDIAN);
429 offset += 2;
430 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_state, tvb, offset, 1, ENC_BIG_ENDIAN);
431 offset += 1;
432 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
433 offset += 1;
434 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_activegrp, tvb, offset, 2, ENC_BIG_ENDIAN);
435 offset += 2;
436 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_passivegrp, tvb, offset, 2, ENC_BIG_ENDIAN);
437 offset += 2;
438 proto_tree_add_item(hsrp_tree, hf_hsrp_adv_reserved2, tvb, offset, 4, ENC_BIG_ENDIAN);
439 /* offset += 4; */
440 } else {
441 next_tvb = tvb_new_subset_remaining(tvb, offset);
442 call_data_dissector(next_tvb, pinfo, hsrp_tree);
444 /* is MD5 authentication being used with HSRPv1? */
445 if (tvb_captured_length(tvb) == 50) { /* 20 bytes of regular HSRP data + 30 bytes of authentication payload */
446 unsigned offset2 = offset + 4; /* this now points to the start of a possible TLV sequence */
447 uint8_t type = tvb_get_uint8(tvb, offset2);
448 uint8_t len = tvb_get_uint8(tvb, offset2+1);
449 if (type == 4 && len == 28) {
450 /* MD5 Authentication TLV */
451 if (tree) {
452 process_hsrp_md5_tlv_sequence(tvb, hsrp_tree, offset2);
454 } else {
455 expert_add_info_format(pinfo, ti, &ei_hsrp_unknown_tlv,
456 "Unknown TLV sequence in HSRPv1 dissection, Type=(%d) Len=(%d)", type, len);
459 } else if ((pinfo->dst.type == AT_IPv4 && memcmp(pinfo->dst.data, &hsrpv2, 4) == 0) ||
460 (pinfo->dst.type == AT_IPv6 && pinfo->destport == UDP_PORT_HSRP2_V6)) {
461 /* HSRPv2 */
462 unsigned offset = 0, offset2;
463 proto_item *ti = NULL;
464 proto_tree *hsrp_tree = NULL;
465 uint8_t type,len;
467 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSRPv2");
469 if (tree) {
470 ti = proto_tree_add_item(tree, proto_hsrp, tvb, offset, -1, ENC_NA);
471 hsrp_tree = proto_item_add_subtree(ti, ett_hsrp);
474 while (tvb_reported_length_remaining(tvb, offset) > 0) {
475 type = tvb_get_uint8(tvb, offset);
476 len = tvb_get_uint8(tvb, offset+1);
478 offset2 = offset;
479 if (type == 1 && len == 40) {
480 /* Group State TLV */
481 uint8_t opcode, state = 0, ipver;
482 uint32_t hellotime, holdtime;
483 proto_tree *group_state_tlv;
485 if (tree) {
486 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_group_state_tlv, tvb, offset, 2+len, type,
487 "Type=%d Len=%d", type, len);
489 offset+=2;
491 opcode = tvb_get_uint8(tvb, offset+1);
492 col_set_str(pinfo->cinfo, COL_INFO,
493 val_to_str_const(opcode, hsrp2_opcode_vals, "Unknown"));
495 state = tvb_get_uint8(tvb, offset+2);
496 col_append_fstr(pinfo->cinfo, COL_INFO, " (state %s)",
497 val_to_str_const(state, hsrp2_state_vals, "Unknown"));
499 if (tree) {
500 /* Making Group State TLV subtree. */
501 group_state_tlv = proto_item_add_subtree(ti, ett_hsrp2_group_state_tlv);
502 proto_tree_add_item(group_state_tlv, hf_hsrp2_version, tvb, offset, 1, ENC_BIG_ENDIAN);
503 offset++;
504 proto_tree_add_uint(group_state_tlv, hf_hsrp2_opcode, tvb, offset, 1, opcode);
505 offset++;
506 proto_tree_add_uint(group_state_tlv, hf_hsrp2_state, tvb, offset, 1, state);
507 offset++;
508 ipver = tvb_get_uint8(tvb, offset);
509 proto_tree_add_uint(group_state_tlv, hf_hsrp2_ipversion, tvb, offset, 1, ipver);
510 offset++;
511 proto_tree_add_item(group_state_tlv, hf_hsrp2_group, tvb, offset, 2, ENC_BIG_ENDIAN);
512 offset+=2;
513 proto_tree_add_item(group_state_tlv, hf_hsrp2_identifier, tvb, offset, 6, ENC_NA);
514 offset+=6;
515 proto_tree_add_item(group_state_tlv, hf_hsrp2_priority, tvb, offset, 4, ENC_BIG_ENDIAN);
516 offset+=4;
518 hellotime = tvb_get_ntohl(tvb, offset);
519 proto_tree_add_uint_format_value(group_state_tlv, hf_hsrp2_hellotime, tvb, offset, 4, hellotime,
520 "%sDefault (%u)",
521 (hellotime == HSRP2_DEFAULT_HELLOTIME) ? "" : "Non-",
522 hellotime);
523 offset+=4;
524 holdtime = tvb_get_ntohl(tvb, offset);
525 proto_tree_add_uint_format_value(group_state_tlv, hf_hsrp2_holdtime, tvb, offset, 4, holdtime,
526 "%sDefault (%u)",
527 (holdtime == HSRP2_DEFAULT_HOLDTIME) ? "" : "Non-",
528 holdtime);
529 offset+=4;
530 if (ipver == 4) {
531 /* Fetch Virtual IP as IPv4 */
532 proto_tree_add_item(group_state_tlv, hf_hsrp2_virt_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
533 } else if (ipver == 6) {
534 /* Fetch Virtual IP as IPv6 */
535 proto_tree_add_item(group_state_tlv, hf_hsrp2_virt_ip_addr_v6, tvb, offset, 16, ENC_NA);
536 } else {
537 /* Unknown protocol */
538 next_tvb = tvb_new_subset_remaining(tvb, offset);
539 call_data_dissector(next_tvb, pinfo, hsrp_tree);
540 break;
542 /* offset+=16; */
544 } else if (type == 2 && len == 4) {
545 /* Interface State TLV */
546 uint16_t active,passive;
547 active = tvb_get_ntohs(tvb, offset+2);
548 passive = tvb_get_ntohs(tvb, offset+4);
550 col_add_fstr(pinfo->cinfo, COL_INFO, "Interface State TLV (Act=%d Pass=%d)",active,passive);
552 if (tree) {
553 proto_tree *interface_state_tlv;
554 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_interface_state_tlv, tvb, offset, 2+len, type,
555 "Type=%d Len=%d", type, len);
556 offset+=2;
558 /* Making Interface State TLV subtree */
559 interface_state_tlv = proto_item_add_subtree(ti, ett_hsrp2_interface_state_tlv);
560 proto_tree_add_item(interface_state_tlv, hf_hsrp2_active_group, tvb, offset, 2, ENC_BIG_ENDIAN);
561 offset+=2;
562 proto_tree_add_item(interface_state_tlv, hf_hsrp2_passive_group, tvb, offset, 2, ENC_BIG_ENDIAN);
563 /* offset+=2; */
565 } else if (type == 3 && len == 8) {
566 /* Text Authentication TLV */
567 /* FIXME: Is the length of the authentication string really restricted to 8 bytes
568 * or is it maybe padded to multiples of 4 or 8 bytes?
570 if (tree) {
571 proto_tree *text_auth_tlv;
572 char *auth;
574 ti = proto_tree_add_uint_format_value(hsrp_tree, hf_hsrp2_text_auth_tlv, tvb, offset, 2+len, type,
575 "Type=%d Len=%d", type, len);
576 offset+=2;
578 /* Making Text Authentication TLV subtree */
579 text_auth_tlv = proto_item_add_subtree(ti, ett_hsrp2_text_auth_tlv);
581 auth = (char *) tvb_get_string_enc(pinfo->pool, tvb, offset, 8, ENC_ASCII|ENC_NA);
582 proto_tree_add_string_format_value(text_auth_tlv, hf_hsrp2_auth_data, tvb, offset, 8, auth,
583 "%sDefault (%s)",
584 (strcmp(auth, "cisco") == 0) ? "" : "Non-",
585 auth);
586 /* offset += 8; */
588 } else if (type == 4 && len == 28) {
589 /* MD5 Authentication TLV */
590 if (tree) {
591 process_hsrp_md5_tlv_sequence(tvb, hsrp_tree, offset);
592 /* offset += 16; */
594 } else {
595 /* Undefined TLV */
596 next_tvb = tvb_new_subset_remaining(tvb, offset);
597 call_data_dissector(next_tvb, pinfo, hsrp_tree);
598 break;
600 offset = offset2+len+2;
604 return tvb_captured_length(tvb);
607 void proto_register_hsrp(void)
609 expert_module_t* expert_hsrp;
611 static hf_register_info hf[] = {
612 { &hf_hsrp_version,
613 { "Version", "hsrp.version",
614 FT_UINT8, BASE_DEC, NULL, 0x0,
615 "The version of the HSRP messages", HFILL }},
617 { &hf_hsrp_opcode,
618 { "Op Code", "hsrp.opcode",
619 FT_UINT8, BASE_DEC, VALS(hsrp_opcode_vals), 0x0,
620 "The type of message contained in this packet", HFILL }},
622 { &hf_hsrp_state,
623 { "State", "hsrp.state",
624 FT_UINT8, BASE_DEC, VALS(hsrp_state_vals), 0x0,
625 "The current state of the router sending the message", HFILL }},
627 { &hf_hsrp_hellotime,
628 { "Hellotime", "hsrp.hellotime",
629 FT_UINT8, BASE_DEC, NULL, 0x0,
630 "The approximate period between the Hello messages that the router sends", HFILL }},
632 { &hf_hsrp_holdtime,
633 { "Holdtime", "hsrp.holdtime",
634 FT_UINT8, BASE_DEC, NULL, 0x0,
635 "Time that the current Hello message should be considered valid", HFILL }},
637 { &hf_hsrp_priority,
638 { "Priority", "hsrp.priority",
639 FT_UINT8, BASE_DEC, NULL, 0x0,
640 "Used to elect the active and standby routers. Numerically higher priority wins vote", HFILL }},
642 { &hf_hsrp_group,
643 { "Group", "hsrp.group",
644 FT_UINT8, BASE_DEC, NULL, 0x0,
645 "This field identifies the standby group", HFILL }},
647 { &hf_hsrp_reserved,
648 { "Reserved", "hsrp.reserved",
649 FT_UINT8, BASE_DEC, NULL, 0x0,
650 NULL, HFILL }},
652 { &hf_hsrp_auth_data,
653 { "Authentication Data", "hsrp.auth_data",
654 FT_STRING, BASE_NONE, NULL, 0x0,
655 "Contains a clear-text 8 character reused password", HFILL }},
657 { &hf_hsrp_virt_ip_addr,
658 { "Virtual IP Address", "hsrp.virt_ip",
659 FT_IPv4, BASE_NONE, NULL, 0x0,
660 "The virtual IP address used by this group", HFILL }},
662 { &hf_hsrp_adv_type,
663 { "Adv type", "hsrp.adv.tlvtype",
664 FT_UINT16, BASE_DEC, VALS(hsrp_adv_type_vals), 0x0,
665 "Advertisement tlv type", HFILL }},
667 { &hf_hsrp_adv_length,
668 { "Adv length", "hsrp.adv.tlvlength",
669 FT_UINT16, BASE_DEC, NULL, 0x0,
670 "Advertisement tlv length", HFILL }},
672 { &hf_hsrp_adv_state,
673 { "Adv state", "hsrp.adv.state",
674 FT_UINT8, BASE_DEC, VALS(hsrp_adv_state_vals), 0x0,
675 "Advertisement tlv length", HFILL }},
677 { &hf_hsrp_adv_reserved1,
678 { "Adv reserved1", "hsrp.adv.reserved1",
679 FT_UINT8, BASE_DEC, NULL, 0x0,
680 "Advertisement tlv length", HFILL }},
682 { &hf_hsrp_adv_activegrp,
683 { "Adv active groups", "hsrp.adv.activegrp",
684 FT_UINT16, BASE_DEC, NULL, 0x0,
685 "Advertisement active group count", HFILL }},
687 { &hf_hsrp_adv_passivegrp,
688 { "Adv passive groups", "hsrp.adv.passivegrp",
689 FT_UINT16, BASE_DEC, NULL, 0x0,
690 "Advertisement passive group count", HFILL }},
692 { &hf_hsrp_adv_reserved2,
693 { "Adv reserved2", "hsrp.adv.reserved2",
694 FT_UINT32, BASE_DEC, NULL, 0x0,
695 "Advertisement tlv length", HFILL }},
697 { &hf_hsrp2_version,
698 { "Version", "hsrp2.version",
699 FT_UINT8, BASE_DEC, NULL, 0x0,
700 "The version of the HSRP messages", HFILL }},
702 { &hf_hsrp2_opcode,
703 { "Op Code", "hsrp2.opcode",
704 FT_UINT8, BASE_DEC, VALS(hsrp2_opcode_vals), 0x0,
705 "The type of message contained in this packet", HFILL }},
707 { &hf_hsrp2_state,
708 { "State", "hsrp2.state",
709 FT_UINT8, BASE_DEC, VALS(hsrp2_state_vals), 0x0,
710 "The current state of the router sending the message", HFILL }},
712 { &hf_hsrp2_group_state_tlv,
713 { "Group State TLV", "hsrp2.group_state_tlv",
714 FT_UINT8, BASE_DEC, NULL, 0x0,
715 NULL, HFILL }},
717 { &hf_hsrp2_interface_state_tlv,
718 { "Interface State TLV", "hsrp2.interface_state_tlv",
719 FT_UINT8, BASE_DEC, NULL, 0x0,
720 NULL, HFILL }},
722 { &hf_hsrp2_text_auth_tlv,
723 { "Text Authentication TLV", "hsrp2.text_auth_tlv",
724 FT_UINT8, BASE_DEC, NULL, 0x0,
725 NULL, HFILL }},
727 { &hf_hsrp2_md5_auth_tlv,
728 { "MD5 Authentication TLV", "hsrp2.md5_auth_tlv",
729 FT_UINT8, BASE_DEC, NULL, 0x0,
730 NULL, HFILL }},
732 { &hf_hsrp2_ipversion,
733 { "IP Ver.", "hsrp2.ipversion",
734 FT_UINT8, BASE_DEC, VALS(hsrp2_ipversion_vals), 0x0,
735 "The IP protocol version used in this hsrp message", HFILL }},
737 { &hf_hsrp2_group,
738 { "Group", "hsrp2.group",
739 FT_UINT16, BASE_DEC, NULL, 0x0,
740 "This field identifies the standby group", HFILL }},
742 { &hf_hsrp2_identifier,
743 { "Identifier", "hsrp2.identifier",
744 FT_ETHER, BASE_NONE, NULL, 0x0,
745 "BIA value of a sender interface", HFILL }},
747 { &hf_hsrp2_hellotime,
748 { "Hellotime", "hsrp2.hellotime",
749 FT_UINT32, BASE_DEC, NULL, 0x0,
750 "The approximate period between the Hello messages that the router sends", HFILL }},
752 { &hf_hsrp2_holdtime,
753 { "Holdtime", "hsrp2.holdtime",
754 FT_UINT32, BASE_DEC, NULL, 0x0,
755 "Time that the current Hello message should be considered valid", HFILL }},
757 { &hf_hsrp2_priority,
758 { "Priority", "hsrp2.priority",
759 FT_UINT32, BASE_DEC, NULL, 0x0,
760 "Used to elect the active and standby routers. Numerically higher priority wins vote", HFILL }},
762 { &hf_hsrp2_auth_data,
763 { "Authentication Data", "hsrp2.auth_data",
764 FT_STRING, BASE_NONE, NULL, 0x0,
765 "Contains a clear-text 8 character reused password", HFILL }},
767 { &hf_hsrp2_virt_ip_addr,
768 { "Virtual IP Address", "hsrp2.virt_ip",
769 FT_IPv4, BASE_NONE, NULL, 0x0,
770 "The virtual IP address used by this group", HFILL }},
772 { &hf_hsrp2_virt_ip_addr_v6,
773 { "Virtual IPv6 Address", "hsrp2.virt_ip_v6",
774 FT_IPv6, BASE_NONE, NULL, 0x0,
775 "The virtual IPv6 address used by this group", HFILL }},
777 { &hf_hsrp2_active_group,
778 { "Active Groups", "hsrp2.active_groups",
779 FT_UINT16, BASE_DEC, NULL, 0x0,
780 "Active group number which becomes the active router myself", HFILL }},
782 { &hf_hsrp2_passive_group,
783 { "Passive Groups", "hsrp2.passive_groups",
784 FT_UINT16, BASE_DEC, NULL, 0x0,
785 "Standby group number which doesn't become the active router myself", HFILL }},
787 { &hf_hsrp2_md5_algorithm,
788 { "MD5 Algorithm", "hsrp2.md5_algorithm",
789 FT_UINT8, BASE_DEC, VALS(hsrp2_md5_algorithm_vals), 0x0,
790 "Hash Algorithm used by this group", HFILL }},
792 { &hf_hsrp2_md5_padding,
793 { "Padding", "hsrp2.md5_padding",
794 FT_UINT8, BASE_HEX, NULL, 0x0,
795 "Must be zero", HFILL }},
797 { &hf_hsrp2_md5_flags,
798 { "MD5 Flags", "hsrp2.md5_flags",
799 FT_UINT16, BASE_DEC, NULL, 0x0,
800 "Undefined", HFILL }},
802 { &hf_hsrp2_md5_ip_address,
803 { "Sender's IP Address", "hsrp.md5_ip_address",
804 FT_IPv4, BASE_NONE, NULL, 0x0,
805 "IP Address of the sender interface", HFILL }},
807 { &hf_hsrp2_md5_key_id,
808 { "MD5 Key ID", "hsrp2.md5_key_id",
809 FT_UINT32, BASE_DEC, NULL, 0x0,
810 "This field contains Key chain ID", HFILL }},
812 { &hf_hsrp2_md5_auth_data,
813 { "MD5 Authentication Data", "hsrp2.md5_auth_data",
814 FT_BYTES, BASE_NONE, NULL, 0x0,
815 "MD5 digest string is contained.", HFILL }}
818 static int *ett[] = {
819 &ett_hsrp,
820 &ett_hsrp2_group_state_tlv,
821 &ett_hsrp2_interface_state_tlv,
822 &ett_hsrp2_text_auth_tlv,
823 &ett_hsrp2_md5_auth_tlv
826 static ei_register_info ei[] = {
827 { &ei_hsrp_unknown_tlv, { "hsrp.unknown_tlv", PI_UNDECODED, PI_WARN, "Unknown TLV sequence (HSRPv1)", EXPFILL }},
830 proto_hsrp = proto_register_protocol("Cisco Hot Standby Router Protocol", "HSRP", "hsrp");
832 proto_register_field_array(proto_hsrp, hf, array_length(hf));
833 proto_register_subtree_array(ett, array_length(ett));
834 expert_hsrp = expert_register_protocol(proto_hsrp);
835 expert_register_field_array(expert_hsrp, ei, array_length(ei));
837 hsrp_handle = register_dissector("hsrp", dissect_hsrp, proto_hsrp);
840 void
841 proto_reg_handoff_hsrp(void)
843 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_HSRP_RANGE, hsrp_handle);
847 * Editor modelines - https://www.wireshark.org/tools/modelines.html
849 * Local variables:
850 * c-basic-offset: 8
851 * tab-width: 8
852 * indent-tabs-mode: nil
853 * End:
855 * vi: set shiftwidth=8 tabstop=8 expandtab:
856 * :indentSize=8:tabSize=8:noTabs=true: