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