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.8 2023/08/17 20:19:40 christos Exp $"); 29 #endif 30 31 /* \summary: Virtual Router Redundancy Protocol (VRRP) printer */ 32 33 #ifdef HAVE_CONFIG_H 34 #include <config.h> 35 #endif 36 37 #include "netdissect-stdinc.h" 38 39 #include "netdissect.h" 40 #include "extract.h" 41 #include "addrtoname.h" 42 43 #include "ip.h" 44 #include "ipproto.h" 45 /* 46 * RFC 2338 (VRRP v2): 47 * 48 * 0 1 2 3 49 * 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 50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51 * |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs| 52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 53 * | Auth Type | Adver Int | Checksum | 54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 55 * | IP Address (1) | 56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 57 * | . | 58 * | . | 59 * | . | 60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61 * | IP Address (n) | 62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 63 * | Authentication Data (1) | 64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 65 * | Authentication Data (2) | 66 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 67 * 68 * 69 * RFC 5798 (VRRP v3): 70 * 71 * 0 1 2 3 72 * 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 73 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 74 * | IPv4 Fields or IPv6 Fields | 75 * ... ... 76 * | | 77 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 78 * |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| 79 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 80 * |(rsvd) | Max Adver Int | Checksum | 81 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 82 * | | 83 * + + 84 * | IPvX Address(es) | 85 * + + 86 * | | 87 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 88 */ 89 90 /* Type */ 91 #define VRRP_TYPE_ADVERTISEMENT 1 92 93 static const struct tok type2str[] = { 94 { VRRP_TYPE_ADVERTISEMENT, "Advertisement" }, 95 { 0, NULL } 96 }; 97 98 /* Auth Type */ 99 #define VRRP_AUTH_NONE 0 100 #define VRRP_AUTH_SIMPLE 1 101 #define VRRP_AUTH_AH 2 102 103 static const struct tok auth2str[] = { 104 { VRRP_AUTH_NONE, "none" }, 105 { VRRP_AUTH_SIMPLE, "simple" }, 106 { VRRP_AUTH_AH, "ah" }, 107 { 0, NULL } 108 }; 109 110 void 111 vrrp_print(netdissect_options *ndo, 112 const u_char *bp, u_int len, 113 const u_char *bp2, int ttl, 114 int ver) 115 { 116 int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */ 117 const char *type_s; 118 119 ndo->ndo_protocol = "vrrp"; 120 nd_print_protocol_caps(ndo); 121 version = (GET_U_1(bp) & 0xf0) >> 4; 122 type = GET_U_1(bp) & 0x0f; 123 type_s = tok2str(type2str, "unknown type (%u)", type); 124 ND_PRINT("v%u, %s", version, type_s); 125 if (ttl != 255) 126 ND_PRINT(", (ttl %u)", ttl); 127 if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT) 128 return; 129 ND_PRINT(", vrid %u, prio %u", GET_U_1(bp + 1), GET_U_1(bp + 2)); 130 131 if (version == 2) { 132 auth_type = GET_U_1(bp + 4); 133 ND_PRINT(", authtype %s", tok2str(auth2str, NULL, auth_type)); 134 ND_PRINT(", intvl %us, length %u", GET_U_1(bp + 5), len); 135 } else { /* version == 3 */ 136 uint16_t intvl = (GET_U_1(bp + 4) & 0x0f) << 8 | GET_U_1(bp + 5); 137 ND_PRINT(", intvl %ucs, length %u", intvl, len); 138 } 139 140 if (ndo->ndo_vflag) { 141 u_int naddrs = GET_U_1(bp + 3); 142 u_int i; 143 char c; 144 145 if (version == 2 && ND_TTEST_LEN(bp, len)) { 146 struct cksum_vec vec[1]; 147 148 vec[0].ptr = bp; 149 vec[0].len = len; 150 if (in_cksum(vec, 1)) 151 ND_PRINT(", (bad vrrp cksum %x)", 152 GET_BE_U_2(bp + 6)); 153 } 154 155 if (version == 3 && ND_TTEST_LEN(bp, len)) { 156 uint16_t cksum; 157 158 if (ver == 4) 159 cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, 160 len, len, IPPROTO_VRRP); 161 else 162 cksum = nextproto6_cksum(ndo, (const struct ip6_hdr *)bp2, bp, 163 len, len, IPPROTO_VRRP); 164 if (cksum) 165 ND_PRINT(", (bad vrrp cksum %x)", 166 GET_BE_U_2(bp + 6)); 167 } 168 169 ND_PRINT(", addrs"); 170 if (naddrs > 1) 171 ND_PRINT("(%u)", naddrs); 172 ND_PRINT(":"); 173 c = ' '; 174 bp += 8; 175 for (i = 0; i < naddrs; i++) { 176 if (ver == 4) { 177 ND_PRINT("%c%s", c, GET_IPADDR_STRING(bp)); 178 bp += 4; 179 } else { 180 ND_PRINT("%c%s", c, GET_IP6ADDR_STRING(bp)); 181 bp += 16; 182 } 183 c = ','; 184 } 185 if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */ 186 ND_PRINT(" auth \""); 187 /* 188 * RFC 2338 Section 5.3.10: "If the configured authentication string 189 * is shorter than 8 bytes, the remaining space MUST be zero-filled. 190 */ 191 nd_printjnp(ndo, bp, 8); 192 ND_PRINT("\""); 193 } 194 } 195 } 196