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 { 110 int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */ 111 const char *type_s; 112 113 ndo->ndo_protocol = "vrrp"; 114 version = (GET_U_1(bp) & 0xf0) >> 4; 115 type = GET_U_1(bp) & 0x0f; 116 type_s = tok2str(type2str, "unknown type (%u)", type); 117 ND_PRINT("VRRPv%u, %s", version, type_s); 118 if (ttl != 255) 119 ND_PRINT(", (ttl %u)", ttl); 120 if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT) 121 return; 122 ND_PRINT(", vrid %u, prio %u", GET_U_1(bp + 1), GET_U_1(bp + 2)); 123 124 if (version == 2) { 125 auth_type = GET_U_1(bp + 4); 126 ND_PRINT(", authtype %s", tok2str(auth2str, NULL, auth_type)); 127 ND_PRINT(", intvl %us, length %u", GET_U_1(bp + 5), len); 128 } else { /* version == 3 */ 129 uint16_t intvl = (GET_U_1(bp + 4) & 0x0f) << 8 | GET_U_1(bp + 5); 130 ND_PRINT(", intvl %ucs, length %u", intvl, len); 131 } 132 133 if (ndo->ndo_vflag) { 134 u_int naddrs = GET_U_1(bp + 3); 135 u_int i; 136 char c; 137 138 if (version == 2 && ND_TTEST_LEN(bp, len)) { 139 struct cksum_vec vec[1]; 140 141 vec[0].ptr = bp; 142 vec[0].len = len; 143 if (in_cksum(vec, 1)) 144 ND_PRINT(", (bad vrrp cksum %x)", 145 GET_BE_U_2(bp + 6)); 146 } 147 148 if (version == 3 && ND_TTEST_LEN(bp, len)) { 149 uint16_t cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, 150 len, len, IPPROTO_VRRP); 151 if (cksum) 152 ND_PRINT(", (bad vrrp cksum %x)", 153 GET_BE_U_2(bp + 6)); 154 } 155 156 ND_PRINT(", addrs"); 157 if (naddrs > 1) 158 ND_PRINT("(%u)", naddrs); 159 ND_PRINT(":"); 160 c = ' '; 161 bp += 8; 162 for (i = 0; i < naddrs; i++) { 163 ND_PRINT("%c%s", c, GET_IPADDR_STRING(bp)); 164 c = ','; 165 bp += 4; 166 } 167 if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */ 168 ND_PRINT(" auth \""); 169 /* 170 * RFC 2338 Section 5.3.10: "If the configured authentication string 171 * is shorter than 8 bytes, the remaining space MUST be zero-filled. 172 */ 173 nd_printjnp(ndo, bp, 8); 174 ND_PRINT("\""); 175 } 176 } 177 } 178