print-ip6opts.c revision 75115
11553Srgrimes/* 2330897Seadler * Copyright (C) 1998 WIDE Project. 3330897Seadler * All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. Neither the name of the project nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 301553Srgrimes#ifdef HAVE_CONFIG_H 311553Srgrimes#include "config.h" 321553Srgrimes#endif 3330642Scharnier 341553Srgrimes#ifndef lint 3530642Scharnierstatic const char rcsid[] = 3630642Scharnier "@(#) $Header: /tcpdump/master/tcpdump/print-ip6opts.c,v 1.8 2000/12/13 07:57:05 itojun Exp $"; 3750479Speter#endif 381553Srgrimes 391553Srgrimes#ifdef INET6 401553Srgrimes#include <sys/param.h> 411553Srgrimes#include <sys/time.h> 42202204Sed#include <sys/types.h> 431553Srgrimes#include <sys/socket.h> 441553Srgrimes 451553Srgrimes#include <netinet/in.h> 461553Srgrimes#include <stdio.h> 471553Srgrimes 481553Srgrimes#include "ip6.h" 491553Srgrimes 501553Srgrimes#include "interface.h" 5130872Scharnier#include "addrtoname.h" 521553Srgrimes 531553Srgrimes/* items outside of rfc2292bis */ 541553Srgrimes#ifndef IP6OPT_MINLEN 55173412Skevlo#define IP6OPT_MINLEN 2 56173412Skevlo#endif 57173412Skevlo#ifndef IP6OPT_RTALERT_LEN 581553Srgrimes#define IP6OPT_RTALERT_LEN 4 59331090Seadler#endif 60246209Scharnier#ifndef IP6OPT_JUMBO_LEN 611553Srgrimes#define IP6OPT_JUMBO_LEN 6 621553Srgrimes#endif 631553Srgrimes#define IP6OPT_HOMEADDR_MINLEN 18 641553Srgrimes#define IP6OPT_BU_MINLEN 10 651553Srgrimes#define IP6OPT_BA_MINLEN 13 661553Srgrimes#define IP6OPT_BR_MINLEN 2 671553Srgrimes#define IP6SOPT_ALTCOA 0x4 681553Srgrimes#define IP6SOPT_ALTCOA_MINLEN 18 691553Srgrimes#define IP6SOPT_UI 0x2 701553Srgrimes#define IP6SOPT_UI_MINLEN 4 711553Srgrimes 7286644Sjhbstatic void ip6_sopt_print(const u_char *, int); 7337267Sbde 741553Srgrimesstatic void 751553Srgrimesip6_sopt_print(const u_char *bp, int len) 761553Srgrimes{ 771553Srgrimes int i; 781553Srgrimes int optlen; 791553Srgrimes 80202204Sed for (i = 0; i < len; i += optlen) { 811553Srgrimes switch (bp[i]) { 821553Srgrimes case IP6OPT_PAD1: 83299707Spfg printf(", pad1"); 841553Srgrimes optlen = 1; 851553Srgrimes break; 861553Srgrimes case IP6OPT_PADN: 871553Srgrimes if (len - i < IP6OPT_MINLEN) { 88239991Sed printf(", padn: trunc"); 891553Srgrimes goto trunc; 901553Srgrimes } 911553Srgrimes printf(", padn"); 921553Srgrimes optlen = bp[i + 1] + 2; 931553Srgrimes break; 941553Srgrimes case IP6SOPT_ALTCOA: 951553Srgrimes if (len - i < IP6SOPT_ALTCOA_MINLEN) { 961553Srgrimes printf(", altcoa: trunc"); 971553Srgrimes goto trunc; 981553Srgrimes } 991553Srgrimes printf(", alt-CoA: %s", ip6addr_string(&bp[i+2])); 1001553Srgrimes optlen = bp[i + 1] + 2; 1011553Srgrimes break; 1021553Srgrimes case IP6SOPT_UI: 1031553Srgrimes if (len - i < IP6SOPT_UI_MINLEN) { 1041553Srgrimes printf(", ui: trunc"); 1051553Srgrimes goto trunc; 1061553Srgrimes } 1071553Srgrimes printf("(ui: 0x%04x) ", ntohs(*(u_int16_t *)&bp[i + 2])); 108239991Sed optlen = bp[i + 1] + 2; 1091553Srgrimes break; 1101553Srgrimes default: 1111553Srgrimes if (len - i < IP6OPT_MINLEN) { 1121553Srgrimes printf(", sopt_type %d: trunc)", bp[i]); 1131553Srgrimes goto trunc; 1141553Srgrimes } 1151553Srgrimes printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]); 1161553Srgrimes optlen = bp[i + 1] + 2; 1171553Srgrimes break; 1181553Srgrimes } 1191553Srgrimes } 1201553Srgrimes return; 1211553Srgrimes 1221553Srgrimestrunc: 1231553Srgrimes printf("[trunc] "); 1241553Srgrimes} 1251553Srgrimes 1261553Srgrimesvoid 1271553Srgrimesip6_opt_print(const u_char *bp, int len) 1281553Srgrimes{ 1291553Srgrimes int i; 1301553Srgrimes int optlen; 1311553Srgrimes 1321553Srgrimes for (i = 0; i < len; i += optlen) { 1331553Srgrimes switch (bp[i]) { 1341553Srgrimes case IP6OPT_PAD1: 1351553Srgrimes printf("(pad1)"); 1361553Srgrimes optlen = 1; 137239991Sed break; 1381553Srgrimes case IP6OPT_PADN: 1391553Srgrimes if (len - i < IP6OPT_MINLEN) { 1401553Srgrimes printf("(padn: trunc)"); 1411553Srgrimes goto trunc; 1421553Srgrimes } 1431553Srgrimes printf("(padn)"); 1441553Srgrimes optlen = bp[i + 1] + 2; 1451553Srgrimes break; 1461553Srgrimes case IP6OPT_ROUTER_ALERT: 1471553Srgrimes if (len - i < IP6OPT_RTALERT_LEN) { 1481553Srgrimes printf("(rtalert: trunc)"); 14930830Scharnier goto trunc; 1501553Srgrimes } 1511553Srgrimes if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { 1521553Srgrimes printf("(rtalert: invalid len %d)", bp[i + 1]); 1531553Srgrimes goto trunc; 1541553Srgrimes } 1551553Srgrimes printf("(rtalert: 0x%04x) ", ntohs(*(u_int16_t *)&bp[i + 2])); 1561553Srgrimes optlen = IP6OPT_RTALERT_LEN; 1571553Srgrimes break; 158239991Sed case IP6OPT_JUMBO: 1591553Srgrimes if (len - i < IP6OPT_JUMBO_LEN) { 1601553Srgrimes printf("(jumbo: trunc)"); 1611553Srgrimes goto trunc; 1621553Srgrimes } 1631553Srgrimes if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { 1641553Srgrimes printf("(jumbo: invalid len %d)", bp[i + 1]); 1651553Srgrimes goto trunc; 1661553Srgrimes } 1671553Srgrimes printf("(jumbo: %u) ", (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 2])); 1681553Srgrimes optlen = IP6OPT_JUMBO_LEN; 1691553Srgrimes break; 1701553Srgrimes case IP6OPT_HOME_ADDRESS: 1711553Srgrimes if (len - i < IP6OPT_HOMEADDR_MINLEN) { 1721553Srgrimes printf("(homeaddr: trunc)"); 1731553Srgrimes goto trunc; 1741553Srgrimes } 1751553Srgrimes if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { 1761553Srgrimes printf("(homeaddr: invalid len %d)", bp[i + 1]); 1771553Srgrimes goto trunc; 1781553Srgrimes } 1791553Srgrimes printf("(homeaddr: %s", ip6addr_string(&bp[i + 2])); 1801553Srgrimes if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { 1811553Srgrimes ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN], 1821553Srgrimes (optlen-IP6OPT_HOMEADDR_MINLEN)); 1831553Srgrimes } 1841553Srgrimes printf(")"); 1851553Srgrimes optlen = bp[i + 1] + 2; 1861553Srgrimes break; 1871553Srgrimes case IP6OPT_BINDING_UPDATE: 1881553Srgrimes if (len - i < IP6OPT_BU_MINLEN) { 1891553Srgrimes printf("(bu: trunc)"); 1901553Srgrimes goto trunc; 1911553Srgrimes } 1921553Srgrimes if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) { 1931553Srgrimes printf("(bu: invalid len %d)", bp[i + 1]); 1941553Srgrimes goto trunc; 1951553Srgrimes } 1961553Srgrimes printf("(bu: "); 1971553Srgrimes if (bp[i + 2] & 0x80) 1981553Srgrimes printf("A"); 1991553Srgrimes if (bp[i + 2] & 0x40) 2001553Srgrimes printf("H"); 2011553Srgrimes if (bp[i + 2] & 0x20) 2021553Srgrimes printf("R"); 2031553Srgrimes if (bp[i + 2] & 0x10) 2041553Srgrimes printf("D"); 2051553Srgrimes if (bp[i + 2] & 0x0f) 2061553Srgrimes printf("res"); 2071553Srgrimes printf(", prefixlen: %u", bp[i + 3]); 2081553Srgrimes printf(", sequence: %u", 2091553Srgrimes (u_int16_t)ntohs(*(u_int16_t *)&bp[i + 4])); 2101553Srgrimes printf(", lifetime: %u", 2111553Srgrimes (u_int32_t)ntohs(*(u_int32_t *)&bp[i + 8])); 2121553Srgrimes 2131553Srgrimes optlen = bp[i + 1] + 2; 2141553Srgrimes if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) { 2151553Srgrimes ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN], 2161553Srgrimes (optlen - IP6OPT_BU_MINLEN)); 2171553Srgrimes } 2181553Srgrimes printf(")"); 2191553Srgrimes break; 2201553Srgrimes case IP6OPT_BINDING_ACK: 2211553Srgrimes if (len - i < IP6OPT_BA_MINLEN) { 2221553Srgrimes printf("(ba: trunc)"); 2231553Srgrimes goto trunc; 2241553Srgrimes } 2251553Srgrimes if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) { 2261553Srgrimes printf("(ba: invalid len %d)", bp[i + 1]); 2271553Srgrimes goto trunc; 2281553Srgrimes } 2291553Srgrimes printf("(ba: "); 230239991Sed printf("status: %u", bp[i + 2]); 2311553Srgrimes printf(", sequence: %u", 2321553Srgrimes (u_int16_t)ntohs(*(u_int16_t *)&bp[i + 3])); 2331553Srgrimes printf(", lifetime: %u", 2341553Srgrimes (u_int32_t)ntohs(*(u_int32_t *)&bp[i + 7])); 2351553Srgrimes printf(", refresh: %u", 2361553Srgrimes (u_int32_t)ntohs(*(u_int32_t *)&bp[i + 11])); 2371553Srgrimes 2381553Srgrimes if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) { 239239991Sed ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN], 2401553Srgrimes (optlen-IP6OPT_BA_MINLEN)); 2411553Srgrimes } 2421553Srgrimes printf(")"); 2431553Srgrimes optlen = bp[i + 1] + 2; 2441553Srgrimes break; 2451553Srgrimes case IP6OPT_BINDING_REQ: 2461553Srgrimes if (len - i < IP6OPT_BR_MINLEN) { 2471553Srgrimes printf("(br: trunc)"); 2481553Srgrimes goto trunc; 2491553Srgrimes } 2501553Srgrimes printf("(br"); 2511553Srgrimes if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) { 2521553Srgrimes ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN], 253239991Sed (optlen-IP6OPT_BR_MINLEN)); 2541553Srgrimes } 2551553Srgrimes printf(")"); 2561553Srgrimes optlen = bp[i + 1] + 2; 2571553Srgrimes break; 2581553Srgrimes default: 259299709Spfg if (len - i < IP6OPT_MINLEN) { 26037267Sbde printf("(type %d: trunc)", bp[i]); 261299709Spfg goto trunc; 262299709Spfg } 2631553Srgrimes printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]); 2641553Srgrimes optlen = bp[i + 1] + 2; 2651553Srgrimes break; 2661553Srgrimes } 2671553Srgrimes } 2681553Srgrimes 2691553Srgrimes#if 0 2701553Srgrimesend: 2711553Srgrimes#endif 2721553Srgrimes return; 27386644Sjhb 27486644Sjhbtrunc: 27586644Sjhb printf("[trunc] "); 2761553Srgrimes} 2771553Srgrimes 2781553Srgrimesint 2791553Srgrimeshbhopt_print(register const u_char *bp) 2801553Srgrimes{ 2811553Srgrimes const struct ip6_hbh *dp = (struct ip6_hbh *)bp; 282202204Sed register const u_char *ep; 283202204Sed int hbhlen = 0; 284202204Sed 285202204Sed /* 'ep' points to the end of available data. */ 286202204Sed ep = snapend; 287202204Sed TCHECK(dp->ip6h_len); 288202204Sed hbhlen = (int)((dp->ip6h_len + 1) << 3); 2891553Srgrimes TCHECK2(*dp, hbhlen); 2901553Srgrimes printf("HBH "); 2911553Srgrimes if (vflag) 2921553Srgrimes ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp)); 2931553Srgrimes 2941553Srgrimes return(hbhlen); 295239991Sed 2961553Srgrimes trunc: 2971553Srgrimes fputs("[|HBH]", stdout); 2981553Srgrimes return(hbhlen); 2991553Srgrimes} 3001553Srgrimes 3011553Srgrimesint 3021553Srgrimesdstopt_print(register const u_char *bp) 3031553Srgrimes{ 3041553Srgrimes const struct ip6_dest *dp = (struct ip6_dest *)bp; 3051553Srgrimes register const u_char *ep; 3061553Srgrimes int dstoptlen = 0; 3071553Srgrimes 3081553Srgrimes /* 'ep' points to the end of available data. */ 3091553Srgrimes ep = snapend; 3101553Srgrimes TCHECK(dp->ip6d_len); 3111553Srgrimes dstoptlen = (int)((dp->ip6d_len + 1) << 3); 3121553Srgrimes TCHECK2(*dp, dstoptlen); 3131553Srgrimes printf("DSTOPT "); 3141553Srgrimes if (vflag) { 3151553Srgrimes ip6_opt_print((const u_char *)dp + sizeof(*dp), 3161553Srgrimes dstoptlen - sizeof(*dp)); 3171553Srgrimes } 3181553Srgrimes 3191553Srgrimes return(dstoptlen); 3201553Srgrimes 3211553Srgrimes trunc: 3221553Srgrimes fputs("[|DSTOPT]", stdout); 3231553Srgrimes return(dstoptlen); 3241553Srgrimes} 3251553Srgrimes#endif /* INET6 */ 3261553Srgrimes