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