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