1 /* 2 * Copyright (C) 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <sys/cdefs.h> 35 #ifndef lint 36 #if 0 37 static const char rcsid[] _U_ = 38 "@(#) Header: /tcpdump/master/tcpdump/print-ip6opts.c,v 1.18 2005-04-20 22:18:50 guy Exp"; 39 #else 40 __RCSID("$NetBSD: print-ip6opts.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 41 #endif 42 #endif 43 44 #ifdef INET6 45 #include <tcpdump-stdinc.h> 46 47 #include <stdio.h> 48 49 #include "ip6.h" 50 51 #include "interface.h" 52 #include "addrtoname.h" 53 #include "extract.h" 54 55 /* items outside of rfc2292bis */ 56 #ifndef IP6OPT_MINLEN 57 #define IP6OPT_MINLEN 2 58 #endif 59 #ifndef IP6OPT_RTALERT_LEN 60 #define IP6OPT_RTALERT_LEN 4 61 #endif 62 #ifndef IP6OPT_JUMBO_LEN 63 #define IP6OPT_JUMBO_LEN 6 64 #endif 65 #define IP6OPT_HOMEADDR_MINLEN 18 66 #define IP6OPT_BU_MINLEN 10 67 #define IP6OPT_BA_MINLEN 13 68 #define IP6OPT_BR_MINLEN 2 69 #define IP6SOPT_UI 0x2 70 #define IP6SOPT_UI_MINLEN 4 71 #define IP6SOPT_ALTCOA 0x3 72 #define IP6SOPT_ALTCOA_MINLEN 18 73 #define IP6SOPT_AUTH 0x4 74 #define IP6SOPT_AUTH_MINLEN 6 75 76 static void ip6_sopt_print(const u_char *, int); 77 78 static void 79 ip6_sopt_print(const u_char *bp, int len) 80 { 81 int i; 82 int optlen; 83 84 for (i = 0; i < len; i += optlen) { 85 if (bp[i] == IP6OPT_PAD1) 86 optlen = 1; 87 else { 88 if (i + 1 < len) 89 optlen = bp[i + 1] + 2; 90 else 91 goto trunc; 92 } 93 if (i + optlen > len) 94 goto trunc; 95 96 switch (bp[i]) { 97 case IP6OPT_PAD1: 98 printf(", pad1"); 99 break; 100 case IP6OPT_PADN: 101 if (len - i < IP6OPT_MINLEN) { 102 printf(", padn: trunc"); 103 goto trunc; 104 } 105 printf(", padn"); 106 break; 107 case IP6SOPT_UI: 108 if (len - i < IP6SOPT_UI_MINLEN) { 109 printf(", ui: trunc"); 110 goto trunc; 111 } 112 printf(", ui: 0x%04x ", EXTRACT_16BITS(&bp[i + 2])); 113 break; 114 case IP6SOPT_ALTCOA: 115 if (len - i < IP6SOPT_ALTCOA_MINLEN) { 116 printf(", altcoa: trunc"); 117 goto trunc; 118 } 119 printf(", alt-CoA: %s", ip6addr_string(&bp[i+2])); 120 break; 121 case IP6SOPT_AUTH: 122 if (len - i < IP6SOPT_AUTH_MINLEN) { 123 printf(", auth: trunc"); 124 goto trunc; 125 } 126 printf(", auth spi: 0x%08x", EXTRACT_32BITS(&bp[i + 2])); 127 break; 128 default: 129 if (len - i < IP6OPT_MINLEN) { 130 printf(", sopt_type %d: trunc)", bp[i]); 131 goto trunc; 132 } 133 printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]); 134 break; 135 } 136 } 137 return; 138 139 trunc: 140 printf("[trunc] "); 141 } 142 143 void 144 ip6_opt_print(const u_char *bp, int len) 145 { 146 int i; 147 int optlen = 0; 148 149 for (i = 0; i < len; i += optlen) { 150 if (bp[i] == IP6OPT_PAD1) 151 optlen = 1; 152 else { 153 if (i + 1 < len) 154 optlen = bp[i + 1] + 2; 155 else 156 goto trunc; 157 } 158 if (i + optlen > len) 159 goto trunc; 160 161 switch (bp[i]) { 162 case IP6OPT_PAD1: 163 printf("(pad1)"); 164 break; 165 case IP6OPT_PADN: 166 if (len - i < IP6OPT_MINLEN) { 167 printf("(padn: trunc)"); 168 goto trunc; 169 } 170 printf("(padn)"); 171 break; 172 case IP6OPT_ROUTER_ALERT: 173 if (len - i < IP6OPT_RTALERT_LEN) { 174 printf("(rtalert: trunc)"); 175 goto trunc; 176 } 177 if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { 178 printf("(rtalert: invalid len %d)", bp[i + 1]); 179 goto trunc; 180 } 181 printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2])); 182 break; 183 case IP6OPT_JUMBO: 184 if (len - i < IP6OPT_JUMBO_LEN) { 185 printf("(jumbo: trunc)"); 186 goto trunc; 187 } 188 if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { 189 printf("(jumbo: invalid len %d)", bp[i + 1]); 190 goto trunc; 191 } 192 printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2])); 193 break; 194 case IP6OPT_HOME_ADDRESS: 195 if (len - i < IP6OPT_HOMEADDR_MINLEN) { 196 printf("(homeaddr: trunc)"); 197 goto trunc; 198 } 199 if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { 200 printf("(homeaddr: invalid len %d)", bp[i + 1]); 201 goto trunc; 202 } 203 printf("(homeaddr: %s", ip6addr_string(&bp[i + 2])); 204 if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { 205 ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN], 206 (optlen - IP6OPT_HOMEADDR_MINLEN)); 207 } 208 printf(")"); 209 break; 210 case IP6OPT_BINDING_UPDATE: 211 if (len - i < IP6OPT_BU_MINLEN) { 212 printf("(bu: trunc)"); 213 goto trunc; 214 } 215 if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) { 216 printf("(bu: invalid len %d)", bp[i + 1]); 217 goto trunc; 218 } 219 printf("(bu: "); 220 if (bp[i + 2] & 0x80) 221 printf("A"); 222 if (bp[i + 2] & 0x40) 223 printf("H"); 224 if (bp[i + 2] & 0x20) 225 printf("S"); 226 if (bp[i + 2] & 0x10) 227 printf("D"); 228 if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4]) 229 printf("res"); 230 printf(", sequence: %u", bp[i + 5]); 231 printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6])); 232 233 if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) { 234 ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN], 235 (optlen - IP6OPT_BU_MINLEN)); 236 } 237 printf(")"); 238 break; 239 case IP6OPT_BINDING_ACK: 240 if (len - i < IP6OPT_BA_MINLEN) { 241 printf("(ba: trunc)"); 242 goto trunc; 243 } 244 if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) { 245 printf("(ba: invalid len %d)", bp[i + 1]); 246 goto trunc; 247 } 248 printf("(ba: "); 249 printf("status: %u", bp[i + 2]); 250 if (bp[i + 3]) 251 printf("res"); 252 printf(", sequence: %u", bp[i + 4]); 253 printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5])); 254 printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9])); 255 256 if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) { 257 ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN], 258 (optlen - IP6OPT_BA_MINLEN)); 259 } 260 printf(")"); 261 break; 262 case IP6OPT_BINDING_REQ: 263 if (len - i < IP6OPT_BR_MINLEN) { 264 printf("(br: trunc)"); 265 goto trunc; 266 } 267 printf("(br"); 268 if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) { 269 ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN], 270 (optlen - IP6OPT_BR_MINLEN)); 271 } 272 printf(")"); 273 break; 274 default: 275 if (len - i < IP6OPT_MINLEN) { 276 printf("(type %d: trunc)", bp[i]); 277 goto trunc; 278 } 279 printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]); 280 break; 281 } 282 } 283 284 #if 0 285 end: 286 #endif 287 return; 288 289 trunc: 290 printf("[trunc] "); 291 } 292 293 int 294 hbhopt_print(register const u_char *bp) 295 { 296 const struct ip6_hbh *dp = (struct ip6_hbh *)bp; 297 int hbhlen = 0; 298 299 TCHECK(dp->ip6h_len); 300 hbhlen = (int)((dp->ip6h_len + 1) << 3); 301 TCHECK2(*dp, hbhlen); 302 printf("HBH "); 303 if (vflag) 304 ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp)); 305 306 return(hbhlen); 307 308 trunc: 309 fputs("[|HBH]", stdout); 310 return(-1); 311 } 312 313 int 314 dstopt_print(register const u_char *bp) 315 { 316 const struct ip6_dest *dp = (struct ip6_dest *)bp; 317 int dstoptlen = 0; 318 319 TCHECK(dp->ip6d_len); 320 dstoptlen = (int)((dp->ip6d_len + 1) << 3); 321 TCHECK2(*dp, dstoptlen); 322 printf("DSTOPT "); 323 if (vflag) { 324 ip6_opt_print((const u_char *)dp + sizeof(*dp), 325 dstoptlen - sizeof(*dp)); 326 } 327 328 return(dstoptlen); 329 330 trunc: 331 fputs("[|DSTOPT]", stdout); 332 return(-1); 333 } 334 #endif /* INET6 */ 335