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 #include <config.h> 29 30 #include "netdissect-stdinc.h" 31 32 #include "netdissect.h" 33 #include "extract.h" 34 #include "addrtoname.h" 35 36 #include "ip.h" 37 #include "ipproto.h" 38 /* 39 * RFC 2338 (VRRP v2): 40 * 41 * 0 1 2 3 42 * 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 43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 * |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs| 45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46 * | Auth Type | Adver Int | Checksum | 47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48 * | IP Address (1) | 49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50 * | . | 51 * | . | 52 * | . | 53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 54 * | IP Address (n) | 55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 56 * | Authentication Data (1) | 57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 58 * | Authentication Data (2) | 59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 60 * 61 * 62 * RFC 5798 (VRRP v3): 63 * 64 * 0 1 2 3 65 * 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 66 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 67 * | IPv4 Fields or IPv6 Fields | 68 * ... ... 69 * | | 70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 71 * |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| 72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 73 * |(rsvd) | Max Adver Int | Checksum | 74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 75 * | | 76 * + + 77 * | IPvX Address(es) | 78 * + + 79 * | | 80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 81 */ 82 83 /* Type */ 84 #define VRRP_TYPE_ADVERTISEMENT 1 85 86 static const struct tok type2str[] = { 87 { VRRP_TYPE_ADVERTISEMENT, "Advertisement" }, 88 { 0, NULL } 89 }; 90 91 /* Auth Type */ 92 #define VRRP_AUTH_NONE 0 93 #define VRRP_AUTH_SIMPLE 1 94 #define VRRP_AUTH_AH 2 95 96 static const struct tok auth2str[] = { 97 { VRRP_AUTH_NONE, "none" }, 98 { VRRP_AUTH_SIMPLE, "simple" }, 99 { VRRP_AUTH_AH, "ah" }, 100 { 0, NULL } 101 }; 102 103 void 104 vrrp_print(netdissect_options *ndo, 105 const u_char *bp, u_int len, 106 const u_char *bp2, int ttl, 107 int ver) 108 { 109 int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */ 110 const char *type_s; 111 112 ndo->ndo_protocol = "vrrp"; 113 nd_print_protocol_caps(ndo); 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("v%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; 150 151 if (ver == 4) 152 cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, 153 len, len, IPPROTO_VRRP); 154 else 155 cksum = nextproto6_cksum(ndo, (const struct ip6_hdr *)bp2, bp, 156 len, len, IPPROTO_VRRP); 157 if (cksum) 158 ND_PRINT(", (bad vrrp cksum %x)", 159 GET_BE_U_2(bp + 6)); 160 } 161 162 ND_PRINT(", addrs"); 163 if (naddrs > 1) 164 ND_PRINT("(%u)", naddrs); 165 ND_PRINT(":"); 166 c = ' '; 167 bp += 8; 168 for (i = 0; i < naddrs; i++) { 169 if (ver == 4) { 170 ND_PRINT("%c%s", c, GET_IPADDR_STRING(bp)); 171 bp += 4; 172 } else { 173 ND_PRINT("%c%s", c, GET_IP6ADDR_STRING(bp)); 174 bp += 16; 175 } 176 c = ','; 177 } 178 if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */ 179 ND_PRINT(" auth \""); 180 /* 181 * RFC 2338 Section 5.3.10: "If the configured authentication string 182 * is shorter than 8 bytes, the remaining space MUST be zero-filled. 183 */ 184 nd_printjnp(ndo, bp, 8); 185 ND_PRINT("\""); 186 } 187 } 188 } 189