156893Sfenner/*
256893Sfenner * Copyright (C) 1998 WIDE Project.
356893Sfenner * All rights reserved.
4127668Sbms *
556893Sfenner * Redistribution and use in source and binary forms, with or without
656893Sfenner * modification, are permitted provided that the following conditions
756893Sfenner * are met:
856893Sfenner * 1. Redistributions of source code must retain the above copyright
956893Sfenner *    notice, this list of conditions and the following disclaimer.
1056893Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1156893Sfenner *    notice, this list of conditions and the following disclaimer in the
1256893Sfenner *    documentation and/or other materials provided with the distribution.
1356893Sfenner * 3. Neither the name of the project nor the names of its contributors
1456893Sfenner *    may be used to endorse or promote products derived from this software
1556893Sfenner *    without specific prior written permission.
16127668Sbms *
1756893Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1856893Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1956893Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2056893Sfenner * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2156893Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2256893Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2356893Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2456893Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2556893Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2656893Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2756893Sfenner * SUCH DAMAGE.
2856893Sfenner */
2956893Sfenner
30276788Sdelphij#define NETDISSECT_REWORKED
3156893Sfenner#ifdef HAVE_CONFIG_H
3256893Sfenner#include "config.h"
3356893Sfenner#endif
3456893Sfenner
3556893Sfenner#ifdef INET6
36127668Sbms#include <tcpdump-stdinc.h>
3756893Sfenner
3875115Sfenner#include "ip6.h"
3975115Sfenner
4056893Sfenner#include "interface.h"
4156893Sfenner#include "addrtoname.h"
42127668Sbms#include "extract.h"
4356893Sfenner
4475115Sfennerstatic void
45276788Sdelphijip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len)
4675115Sfenner{
4775115Sfenner    int i;
4875115Sfenner    int optlen;
4975115Sfenner
5075115Sfenner    for (i = 0; i < len; i += optlen) {
5198524Sfenner	if (bp[i] == IP6OPT_PAD1)
5298524Sfenner	    optlen = 1;
5398524Sfenner	else {
5498524Sfenner	    if (i + 1 < len)
5598524Sfenner		optlen = bp[i + 1] + 2;
5698524Sfenner	    else
5798524Sfenner		goto trunc;
5898524Sfenner	}
5998524Sfenner	if (i + optlen > len)
6098524Sfenner	    goto trunc;
6198524Sfenner
6275115Sfenner	switch (bp[i]) {
6375115Sfenner	case IP6OPT_PAD1:
64276788Sdelphij            ND_PRINT((ndo, ", pad1"));
6575115Sfenner	    break;
6675115Sfenner	case IP6OPT_PADN:
6775115Sfenner	    if (len - i < IP6OPT_MINLEN) {
68276788Sdelphij		ND_PRINT((ndo, ", padn: trunc"));
6975115Sfenner		goto trunc;
7075115Sfenner	    }
71276788Sdelphij            ND_PRINT((ndo, ", padn"));
7275115Sfenner	    break;
7375115Sfenner	default:
7475115Sfenner	    if (len - i < IP6OPT_MINLEN) {
75276788Sdelphij		ND_PRINT((ndo, ", sopt_type %d: trunc)", bp[i]));
7675115Sfenner		goto trunc;
7775115Sfenner	    }
78276788Sdelphij	    ND_PRINT((ndo, ", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]));
7975115Sfenner	    break;
8075115Sfenner	}
8175115Sfenner    }
8275115Sfenner    return;
8375115Sfenner
8475115Sfennertrunc:
85276788Sdelphij    ND_PRINT((ndo, "[trunc] "));
8675115Sfenner}
8775115Sfenner
88276788Sdelphijstatic void
89276788Sdelphijip6_opt_print(netdissect_options *ndo, const u_char *bp, int len)
9056893Sfenner{
9156893Sfenner    int i;
92127668Sbms    int optlen = 0;
9356893Sfenner
94241235Sdelphij    if (len == 0)
95241235Sdelphij        return;
9656893Sfenner    for (i = 0; i < len; i += optlen) {
9798524Sfenner	if (bp[i] == IP6OPT_PAD1)
9898524Sfenner	    optlen = 1;
9998524Sfenner	else {
10098524Sfenner	    if (i + 1 < len)
10198524Sfenner		optlen = bp[i + 1] + 2;
10298524Sfenner	    else
10398524Sfenner		goto trunc;
10498524Sfenner	}
10598524Sfenner	if (i + optlen > len)
10698524Sfenner	    goto trunc;
10798524Sfenner
10856893Sfenner	switch (bp[i]) {
10956893Sfenner	case IP6OPT_PAD1:
110276788Sdelphij            ND_PRINT((ndo, "(pad1)"));
11156893Sfenner	    break;
11256893Sfenner	case IP6OPT_PADN:
11356893Sfenner	    if (len - i < IP6OPT_MINLEN) {
114276788Sdelphij		ND_PRINT((ndo, "(padn: trunc)"));
11556893Sfenner		goto trunc;
11656893Sfenner	    }
117276788Sdelphij            ND_PRINT((ndo, "(padn)"));
11856893Sfenner	    break;
11975115Sfenner	case IP6OPT_ROUTER_ALERT:
12056893Sfenner	    if (len - i < IP6OPT_RTALERT_LEN) {
121276788Sdelphij		ND_PRINT((ndo, "(rtalert: trunc)"));
12256893Sfenner		goto trunc;
12356893Sfenner	    }
12456893Sfenner	    if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
125276788Sdelphij		ND_PRINT((ndo, "(rtalert: invalid len %d)", bp[i + 1]));
12656893Sfenner		goto trunc;
12756893Sfenner	    }
128276788Sdelphij	    ND_PRINT((ndo, "(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2])));
12956893Sfenner	    break;
13056893Sfenner	case IP6OPT_JUMBO:
13156893Sfenner	    if (len - i < IP6OPT_JUMBO_LEN) {
132276788Sdelphij		ND_PRINT((ndo, "(jumbo: trunc)"));
13356893Sfenner		goto trunc;
13456893Sfenner	    }
13556893Sfenner	    if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
136276788Sdelphij		ND_PRINT((ndo, "(jumbo: invalid len %d)", bp[i + 1]));
13756893Sfenner		goto trunc;
13856893Sfenner	    }
139276788Sdelphij	    ND_PRINT((ndo, "(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2])));
14056893Sfenner	    break;
14175115Sfenner        case IP6OPT_HOME_ADDRESS:
14275115Sfenner	    if (len - i < IP6OPT_HOMEADDR_MINLEN) {
143276788Sdelphij		ND_PRINT((ndo, "(homeaddr: trunc)"));
14475115Sfenner		goto trunc;
14575115Sfenner	    }
14675115Sfenner	    if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
147276788Sdelphij		ND_PRINT((ndo, "(homeaddr: invalid len %d)", bp[i + 1]));
14875115Sfenner		goto trunc;
14975115Sfenner	    }
150276788Sdelphij	    ND_PRINT((ndo, "(homeaddr: %s", ip6addr_string(ndo, &bp[i + 2])));
15175115Sfenner            if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
152276788Sdelphij		ip6_sopt_print(ndo, &bp[i + IP6OPT_HOMEADDR_MINLEN],
15398524Sfenner		    (optlen - IP6OPT_HOMEADDR_MINLEN));
15475115Sfenner	    }
155276788Sdelphij            ND_PRINT((ndo, ")"));
15675115Sfenner	    break;
15756893Sfenner	default:
15856893Sfenner	    if (len - i < IP6OPT_MINLEN) {
159276788Sdelphij		ND_PRINT((ndo, "(type %d: trunc)", bp[i]));
16056893Sfenner		goto trunc;
16156893Sfenner	    }
162276788Sdelphij	    ND_PRINT((ndo, "(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1]));
16356893Sfenner	    break;
16456893Sfenner	}
16556893Sfenner    }
166276788Sdelphij    ND_PRINT((ndo, " "));
16756893Sfenner    return;
16856893Sfenner
16956893Sfennertrunc:
170276788Sdelphij    ND_PRINT((ndo, "[trunc] "));
17156893Sfenner}
17256893Sfenner
17356893Sfennerint
174276788Sdelphijhbhopt_print(netdissect_options *ndo, register const u_char *bp)
17556893Sfenner{
17656893Sfenner    const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
17756893Sfenner    int hbhlen = 0;
17856893Sfenner
179276788Sdelphij    ND_TCHECK(dp->ip6h_len);
18056893Sfenner    hbhlen = (int)((dp->ip6h_len + 1) << 3);
181276788Sdelphij    ND_TCHECK2(*dp, hbhlen);
182276788Sdelphij    ND_PRINT((ndo, "HBH "));
183276788Sdelphij    if (ndo->ndo_vflag)
184276788Sdelphij	ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
18556893Sfenner
18656893Sfenner    return(hbhlen);
18756893Sfenner
18856893Sfenner  trunc:
189276788Sdelphij    ND_PRINT((ndo, "[|HBH]"));
190127668Sbms    return(-1);
19156893Sfenner}
19256893Sfenner
19356893Sfennerint
194276788Sdelphijdstopt_print(netdissect_options *ndo, register const u_char *bp)
19556893Sfenner{
19656893Sfenner    const struct ip6_dest *dp = (struct ip6_dest *)bp;
19756893Sfenner    int dstoptlen = 0;
19856893Sfenner
199276788Sdelphij    ND_TCHECK(dp->ip6d_len);
20056893Sfenner    dstoptlen = (int)((dp->ip6d_len + 1) << 3);
201276788Sdelphij    ND_TCHECK2(*dp, dstoptlen);
202276788Sdelphij    ND_PRINT((ndo, "DSTOPT "));
203276788Sdelphij    if (ndo->ndo_vflag) {
204276788Sdelphij	ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp),
20556893Sfenner	    dstoptlen - sizeof(*dp));
20656893Sfenner    }
20756893Sfenner
20856893Sfenner    return(dstoptlen);
20956893Sfenner
21056893Sfenner  trunc:
211276788Sdelphij    ND_PRINT((ndo, "[|DSTOPT]"));
212127668Sbms    return(-1);
21356893Sfenner}
21456893Sfenner#endif /* INET6 */
215