1 /*
2 * Copyright (c) 2000 William C. Fenner.
3 * All rights reserved.
4 *
5 * Kevin Steves <ks@hp.se> July 2000
6 * Modified to:
7 * - print version, type string and packet length
8 * - print IP address count if > 1 (-v)
9 * - verify checksum (-v)
10 * - print authentication string (-v)
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that: (1) source code
14 * distributions retain the above copyright notice and this paragraph
15 * in its entirety, and (2) distributions including binary code include
16 * the above copyright notice and this paragraph in its entirety in
17 * the documentation or other materials provided with the distribution.
18 * The name of William C. Fenner may not be used to endorse or
19 * promote products derived from this software without specific prior
20 * written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND
21 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
22 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE.
24 */
25
26 #include <sys/cdefs.h>
27 #ifndef lint
28 __RCSID("$NetBSD: print-vrrp.c,v 1.4 2014/11/20 03:05:03 christos Exp $");
29 #endif
30
31 #define NETDISSECT_REWORKED
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <tcpdump-stdinc.h>
37
38 #include "interface.h"
39 #include "extract.h"
40 #include "addrtoname.h"
41
42 #include "ip.h"
43 #include "ipproto.h"
44 /*
45 * RFC 2338 (VRRP v2):
46 *
47 * 0 1 2 3
48 * 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
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs|
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 * | Auth Type | Adver Int | Checksum |
53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 * | IP Address (1) |
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * | . |
57 * | . |
58 * | . |
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * | IP Address (n) |
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * | Authentication Data (1) |
63 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 * | Authentication Data (2) |
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 *
67 *
68 * RFC 5798 (VRRP v3):
69 *
70 * 0 1 2 3
71 * 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
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * | IPv4 Fields or IPv6 Fields |
74 * ... ...
75 * | |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr|
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 * |(rsvd) | Max Adver Int | Checksum |
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 * | |
82 * + +
83 * | IPvX Address(es) |
84 * + +
85 * | |
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 */
88
89 /* Type */
90 #define VRRP_TYPE_ADVERTISEMENT 1
91
92 static const struct tok type2str[] = {
93 { VRRP_TYPE_ADVERTISEMENT, "Advertisement" },
94 { 0, NULL }
95 };
96
97 /* Auth Type */
98 #define VRRP_AUTH_NONE 0
99 #define VRRP_AUTH_SIMPLE 1
100 #define VRRP_AUTH_AH 2
101
102 static const struct tok auth2str[] = {
103 { VRRP_AUTH_NONE, "none" },
104 { VRRP_AUTH_SIMPLE, "simple" },
105 { VRRP_AUTH_AH, "ah" },
106 { 0, NULL }
107 };
108
109 void
vrrp_print(netdissect_options * ndo,register const u_char * bp,register u_int len,register const u_char * bp2,int ttl)110 vrrp_print(netdissect_options *ndo,
111 register const u_char *bp, register u_int len,
112 register const u_char *bp2, int ttl)
113 {
114 int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */
115 const char *type_s;
116
117 ND_TCHECK(bp[0]);
118 version = (bp[0] & 0xf0) >> 4;
119 type = bp[0] & 0x0f;
120 type_s = tok2str(type2str, "unknown type (%u)", type);
121 ND_PRINT((ndo, "VRRPv%u, %s", version, type_s));
122 if (ttl != 255)
123 ND_PRINT((ndo, ", (ttl %u)", ttl));
124 if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT)
125 return;
126 ND_TCHECK(bp[2]);
127 ND_PRINT((ndo, ", vrid %u, prio %u", bp[1], bp[2]));
128 ND_TCHECK(bp[5]);
129
130 if (version == 2) {
131 auth_type = bp[4];
132 ND_PRINT((ndo, ", authtype %s", tok2str(auth2str, NULL, auth_type)));
133 ND_PRINT((ndo, ", intvl %us, length %u", bp[5], len));
134 } else { /* version == 3 */
135 uint16_t intvl = (bp[4] & 0x0f) << 8 | bp[5];
136 ND_PRINT((ndo, ", intvl %ucs, length %u", intvl, len));
137 }
138
139 if (ndo->ndo_vflag) {
140 int naddrs = bp[3];
141 int i;
142 char c;
143
144 if (version == 2 && ND_TTEST2(bp[0], len)) {
145 struct cksum_vec vec[1];
146
147 vec[0].ptr = bp;
148 vec[0].len = len;
149 if (in_cksum(vec, 1))
150 ND_PRINT((ndo, ", (bad vrrp cksum %x)",
151 EXTRACT_16BITS(&bp[6])));
152 }
153
154 if (version == 3 && ND_TTEST2(bp[0], len)) {
155 uint16_t cksum = nextproto4_cksum(ndo, (struct ip *)bp2, bp,
156 len, len, IPPROTO_VRRP);
157 if (cksum)
158 ND_PRINT((ndo, ", (bad vrrp cksum %x)",
159 EXTRACT_16BITS(&bp[6])));
160 }
161
162 ND_PRINT((ndo, ", addrs"));
163 if (naddrs > 1)
164 ND_PRINT((ndo, "(%d)", naddrs));
165 ND_PRINT((ndo, ":"));
166 c = ' ';
167 bp += 8;
168 for (i = 0; i < naddrs; i++) {
169 ND_TCHECK(bp[3]);
170 ND_PRINT((ndo, "%c%s", c, ipaddr_string(ndo, bp)));
171 c = ',';
172 bp += 4;
173 }
174 if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */
175 ND_TCHECK(bp[7]);
176 ND_PRINT((ndo, " auth \""));
177 if (fn_printn(ndo, bp, 8, ndo->ndo_snapend)) {
178 ND_PRINT((ndo, "\""));
179 goto trunc;
180 }
181 ND_PRINT((ndo, "\""));
182 }
183 }
184 return;
185 trunc:
186 ND_PRINT((ndo, "[|vrrp]"));
187 }
188