xref: /dflybsd-src/contrib/tcpdump/print-ip6opts.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (C) 1998 WIDE Project.
341c99275SPeter Avalos  * All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that the following conditions
741c99275SPeter Avalos  * are met:
841c99275SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
941c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1041c99275SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1141c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1241c99275SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1341c99275SPeter Avalos  * 3. Neither the name of the project nor the names of its contributors
1441c99275SPeter Avalos  *    may be used to endorse or promote products derived from this software
1541c99275SPeter Avalos  *    without specific prior written permission.
1641c99275SPeter Avalos  *
1741c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1841c99275SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1941c99275SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2041c99275SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2141c99275SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2241c99275SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2341c99275SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2441c99275SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2541c99275SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2641c99275SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2741c99275SPeter Avalos  * SUCH DAMAGE.
2841c99275SPeter Avalos  */
2941c99275SPeter Avalos 
30411677aeSAaron LI /* \summary: IPv6 header option printer */
31411677aeSAaron LI 
3241c99275SPeter Avalos #ifdef HAVE_CONFIG_H
33*ed775ee7SAntonio Huete Jimenez #include <config.h>
3441c99275SPeter Avalos #endif
3541c99275SPeter Avalos 
36*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3741c99275SPeter Avalos 
38411677aeSAaron LI #include "netdissect.h"
3941c99275SPeter Avalos #include "addrtoname.h"
4041c99275SPeter Avalos #include "extract.h"
4141c99275SPeter Avalos 
42411677aeSAaron LI #include "ip6.h"
4341c99275SPeter Avalos 
44*ed775ee7SAntonio Huete Jimenez static int
ip6_sopt_print(netdissect_options * ndo,const u_char * bp,int len)45411677aeSAaron LI ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len)
4641c99275SPeter Avalos {
4741c99275SPeter Avalos     int i;
4841c99275SPeter Avalos     int optlen;
4941c99275SPeter Avalos 
5041c99275SPeter Avalos     for (i = 0; i < len; i += optlen) {
51*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(bp + i) == IP6OPT_PAD1)
5241c99275SPeter Avalos 	    optlen = 1;
5341c99275SPeter Avalos 	else {
5441c99275SPeter Avalos 	    if (i + 1 < len)
55*ed775ee7SAntonio Huete Jimenez 		optlen = GET_U_1(bp + i + 1) + 2;
5641c99275SPeter Avalos 	    else
5741c99275SPeter Avalos 		goto trunc;
5841c99275SPeter Avalos 	}
5941c99275SPeter Avalos 	if (i + optlen > len)
6041c99275SPeter Avalos 	    goto trunc;
6141c99275SPeter Avalos 
62*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(bp + i)) {
6341c99275SPeter Avalos 	case IP6OPT_PAD1:
64*ed775ee7SAntonio Huete Jimenez             ND_PRINT(", pad1");
6541c99275SPeter Avalos 	    break;
6641c99275SPeter Avalos 	case IP6OPT_PADN:
6741c99275SPeter Avalos 	    if (len - i < IP6OPT_MINLEN) {
68*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", padn: trunc");
6941c99275SPeter Avalos 		goto trunc;
7041c99275SPeter Avalos 	    }
71*ed775ee7SAntonio Huete Jimenez             ND_PRINT(", padn");
7241c99275SPeter Avalos 	    break;
7341c99275SPeter Avalos 	default:
7441c99275SPeter Avalos 	    if (len - i < IP6OPT_MINLEN) {
75*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", sopt_type %u: trunc)", GET_U_1(bp + i));
7641c99275SPeter Avalos 		goto trunc;
7741c99275SPeter Avalos 	    }
78*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(", sopt_type 0x%02x: len=%u", GET_U_1(bp + i),
79*ed775ee7SAntonio Huete Jimenez                      GET_U_1(bp + i + 1));
8041c99275SPeter Avalos 	    break;
8141c99275SPeter Avalos 	}
8241c99275SPeter Avalos     }
83*ed775ee7SAntonio Huete Jimenez     return 0;
8441c99275SPeter Avalos 
8541c99275SPeter Avalos trunc:
86*ed775ee7SAntonio Huete Jimenez     return -1;
8741c99275SPeter Avalos }
8841c99275SPeter Avalos 
89*ed775ee7SAntonio Huete Jimenez static int
ip6_opt_process(netdissect_options * ndo,const u_char * bp,int len,int * found_jumbop,uint32_t * payload_len)90*ed775ee7SAntonio Huete Jimenez ip6_opt_process(netdissect_options *ndo, const u_char *bp, int len,
91*ed775ee7SAntonio Huete Jimenez 		int *found_jumbop, uint32_t *payload_len)
9241c99275SPeter Avalos {
9341c99275SPeter Avalos     int i;
9441c99275SPeter Avalos     int optlen = 0;
95*ed775ee7SAntonio Huete Jimenez     int found_jumbo = 0;
96*ed775ee7SAntonio Huete Jimenez     uint32_t jumbolen = 0;
9741c99275SPeter Avalos 
986263709fSPeter Avalos     if (len == 0)
99*ed775ee7SAntonio Huete Jimenez         return 0;
10041c99275SPeter Avalos     for (i = 0; i < len; i += optlen) {
101*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(bp + i) == IP6OPT_PAD1)
10241c99275SPeter Avalos 	    optlen = 1;
10341c99275SPeter Avalos 	else {
10441c99275SPeter Avalos 	    if (i + 1 < len)
105*ed775ee7SAntonio Huete Jimenez 		optlen = GET_U_1(bp + i + 1) + 2;
10641c99275SPeter Avalos 	    else
10741c99275SPeter Avalos 		goto trunc;
10841c99275SPeter Avalos 	}
10941c99275SPeter Avalos 	if (i + optlen > len)
11041c99275SPeter Avalos 	    goto trunc;
11141c99275SPeter Avalos 
112*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(bp + i)) {
11341c99275SPeter Avalos 	case IP6OPT_PAD1:
114*ed775ee7SAntonio Huete Jimenez 	    if (ndo->ndo_vflag)
115*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("(pad1)");
11641c99275SPeter Avalos 	    break;
11741c99275SPeter Avalos 	case IP6OPT_PADN:
11841c99275SPeter Avalos 	    if (len - i < IP6OPT_MINLEN) {
119*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(padn: trunc)");
12041c99275SPeter Avalos 		goto trunc;
12141c99275SPeter Avalos 	    }
122*ed775ee7SAntonio Huete Jimenez 	    if (ndo->ndo_vflag)
123*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("(padn)");
12441c99275SPeter Avalos 	    break;
12541c99275SPeter Avalos 	case IP6OPT_ROUTER_ALERT:
12641c99275SPeter Avalos 	    if (len - i < IP6OPT_RTALERT_LEN) {
127*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(rtalert: trunc)");
12841c99275SPeter Avalos 		goto trunc;
12941c99275SPeter Avalos 	    }
130*ed775ee7SAntonio Huete Jimenez 	    if (GET_U_1(bp + i + 1) != IP6OPT_RTALERT_LEN - 2) {
131*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(rtalert: invalid len %u)", GET_U_1(bp + i + 1));
13241c99275SPeter Avalos 		goto trunc;
13341c99275SPeter Avalos 	    }
134*ed775ee7SAntonio Huete Jimenez 	    if (ndo->ndo_vflag)
135*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(rtalert: 0x%04x) ", GET_BE_U_2(bp + i + 2));
13641c99275SPeter Avalos 	    break;
13741c99275SPeter Avalos 	case IP6OPT_JUMBO:
13841c99275SPeter Avalos 	    if (len - i < IP6OPT_JUMBO_LEN) {
139*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(jumbo: trunc)");
14041c99275SPeter Avalos 		goto trunc;
14141c99275SPeter Avalos 	    }
142*ed775ee7SAntonio Huete Jimenez 	    if (GET_U_1(bp + i + 1) != IP6OPT_JUMBO_LEN - 2) {
143*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(jumbo: invalid len %u)", GET_U_1(bp + i + 1));
14441c99275SPeter Avalos 		goto trunc;
14541c99275SPeter Avalos 	    }
146*ed775ee7SAntonio Huete Jimenez 	    jumbolen = GET_BE_U_4(bp + i + 2);
147*ed775ee7SAntonio Huete Jimenez 	    if (found_jumbo) {
148*ed775ee7SAntonio Huete Jimenez 		/* More than one Jumbo Payload option */
149*ed775ee7SAntonio Huete Jimenez 		if (ndo->ndo_vflag)
150*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("(jumbo: %u - already seen) ", jumbolen);
151*ed775ee7SAntonio Huete Jimenez 	    } else {
152*ed775ee7SAntonio Huete Jimenez 		found_jumbo = 1;
153*ed775ee7SAntonio Huete Jimenez 		if (payload_len == NULL) {
154*ed775ee7SAntonio Huete Jimenez 		    /* Not a hop-by-hop option - not valid */
155*ed775ee7SAntonio Huete Jimenez 		    if (ndo->ndo_vflag)
156*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("(jumbo: %u - not a hop-by-hop option) ", jumbolen);
157*ed775ee7SAntonio Huete Jimenez 		} else if (*payload_len != 0) {
158*ed775ee7SAntonio Huete Jimenez 		    /* Payload length was non-zero - not valid */
159*ed775ee7SAntonio Huete Jimenez 		    if (ndo->ndo_vflag)
160*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("(jumbo: %u - payload len != 0) ", jumbolen);
161*ed775ee7SAntonio Huete Jimenez 		} else {
162*ed775ee7SAntonio Huete Jimenez 		    /*
163*ed775ee7SAntonio Huete Jimenez 		     * This is a hop-by-hop option, and Payload length
164*ed775ee7SAntonio Huete Jimenez 		     * was zero in the IPv6 header.
165*ed775ee7SAntonio Huete Jimenez 		     */
166*ed775ee7SAntonio Huete Jimenez 		    if (jumbolen < 65536) {
167*ed775ee7SAntonio Huete Jimenez 			/* Too short */
168*ed775ee7SAntonio Huete Jimenez 			if (ndo->ndo_vflag)
169*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("(jumbo: %u - < 65536) ", jumbolen);
170*ed775ee7SAntonio Huete Jimenez 		    } else {
171*ed775ee7SAntonio Huete Jimenez 			/* OK, this is valid */
172*ed775ee7SAntonio Huete Jimenez 			*found_jumbop = 1;
173*ed775ee7SAntonio Huete Jimenez 			*payload_len = jumbolen;
174*ed775ee7SAntonio Huete Jimenez 			if (ndo->ndo_vflag)
175*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("(jumbo: %u) ", jumbolen);
176*ed775ee7SAntonio Huete Jimenez 		    }
177*ed775ee7SAntonio Huete Jimenez 		}
178*ed775ee7SAntonio Huete Jimenez 	    }
17941c99275SPeter Avalos 	    break;
18041c99275SPeter Avalos         case IP6OPT_HOME_ADDRESS:
18141c99275SPeter Avalos 	    if (len - i < IP6OPT_HOMEADDR_MINLEN) {
182*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(homeaddr: trunc)");
18341c99275SPeter Avalos 		goto trunc;
18441c99275SPeter Avalos 	    }
185*ed775ee7SAntonio Huete Jimenez 	    if (GET_U_1(bp + i + 1) < IP6OPT_HOMEADDR_MINLEN - 2) {
186*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(homeaddr: invalid len %u)", GET_U_1(bp + i + 1));
18741c99275SPeter Avalos 		goto trunc;
18841c99275SPeter Avalos 	    }
189*ed775ee7SAntonio Huete Jimenez 	    if (ndo->ndo_vflag) {
190*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(homeaddr: %s", GET_IP6ADDR_STRING(bp + i + 2));
191*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
192*ed775ee7SAntonio Huete Jimenez 		    if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
193*ed775ee7SAntonio Huete Jimenez 				       (optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
194*ed775ee7SAntonio Huete Jimenez 			goto trunc;
19541c99275SPeter Avalos 		}
196*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(")");
197*ed775ee7SAntonio Huete Jimenez 	    }
19841c99275SPeter Avalos 	    break;
19941c99275SPeter Avalos 	default:
20041c99275SPeter Avalos 	    if (len - i < IP6OPT_MINLEN) {
201*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(type %u: trunc)", GET_U_1(bp + i));
20241c99275SPeter Avalos 		goto trunc;
20341c99275SPeter Avalos 	    }
204*ed775ee7SAntonio Huete Jimenez 	    if (ndo->ndo_vflag)
205*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("(opt_type 0x%02x: len=%u)", GET_U_1(bp + i),
206*ed775ee7SAntonio Huete Jimenez 			 GET_U_1(bp + i + 1));
20741c99275SPeter Avalos 	    break;
20841c99275SPeter Avalos 	}
20941c99275SPeter Avalos     }
210*ed775ee7SAntonio Huete Jimenez     if (ndo->ndo_vflag)
211*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" ");
212*ed775ee7SAntonio Huete Jimenez     return 0;
21341c99275SPeter Avalos 
21441c99275SPeter Avalos trunc:
215*ed775ee7SAntonio Huete Jimenez     return -1;
21641c99275SPeter Avalos }
21741c99275SPeter Avalos 
21841c99275SPeter Avalos int
hbhopt_process(netdissect_options * ndo,const u_char * bp,int * found_jumbo,uint32_t * jumbolen)219*ed775ee7SAntonio Huete Jimenez hbhopt_process(netdissect_options *ndo, const u_char *bp, int *found_jumbo,
220*ed775ee7SAntonio Huete Jimenez 	       uint32_t *jumbolen)
22141c99275SPeter Avalos {
222411677aeSAaron LI     const struct ip6_hbh *dp = (const struct ip6_hbh *)bp;
223*ed775ee7SAntonio Huete Jimenez     u_int hbhlen = 0;
22441c99275SPeter Avalos 
225*ed775ee7SAntonio Huete Jimenez     ndo->ndo_protocol = "hbhopt";
226*ed775ee7SAntonio Huete Jimenez     hbhlen = (GET_U_1(dp->ip6h_len) + 1) << 3;
227*ed775ee7SAntonio Huete Jimenez     ND_TCHECK_LEN(dp, hbhlen);
228*ed775ee7SAntonio Huete Jimenez     ND_PRINT("HBH ");
229*ed775ee7SAntonio Huete Jimenez     if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
230*ed775ee7SAntonio Huete Jimenez 			hbhlen - sizeof(*dp), found_jumbo, jumbolen) == -1)
231*ed775ee7SAntonio Huete Jimenez 	goto trunc;
232*ed775ee7SAntonio Huete Jimenez     return hbhlen;
23341c99275SPeter Avalos 
23441c99275SPeter Avalos trunc:
235*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
236*ed775ee7SAntonio Huete Jimenez     return -1;
23741c99275SPeter Avalos }
23841c99275SPeter Avalos 
23941c99275SPeter Avalos int
dstopt_process(netdissect_options * ndo,const u_char * bp)240*ed775ee7SAntonio Huete Jimenez dstopt_process(netdissect_options *ndo, const u_char *bp)
24141c99275SPeter Avalos {
242411677aeSAaron LI     const struct ip6_dest *dp = (const struct ip6_dest *)bp;
243*ed775ee7SAntonio Huete Jimenez     u_int dstoptlen = 0;
24441c99275SPeter Avalos 
245*ed775ee7SAntonio Huete Jimenez     ndo->ndo_protocol = "dstopt";
246*ed775ee7SAntonio Huete Jimenez     dstoptlen = (GET_U_1(dp->ip6d_len) + 1) << 3;
247*ed775ee7SAntonio Huete Jimenez     ND_TCHECK_LEN(dp, dstoptlen);
248*ed775ee7SAntonio Huete Jimenez     ND_PRINT("DSTOPT ");
249411677aeSAaron LI     if (ndo->ndo_vflag) {
250*ed775ee7SAntonio Huete Jimenez 	/*
251*ed775ee7SAntonio Huete Jimenez 	 * The Jumbo Payload option is a hop-by-hop option; we don't
252*ed775ee7SAntonio Huete Jimenez 	 * honor Jumbo Payload destination options, reporting them
253*ed775ee7SAntonio Huete Jimenez 	 * as invalid.
254*ed775ee7SAntonio Huete Jimenez 	 */
255*ed775ee7SAntonio Huete Jimenez 	if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
256*ed775ee7SAntonio Huete Jimenez 			    dstoptlen - sizeof(*dp), NULL, NULL) == -1)
257*ed775ee7SAntonio Huete Jimenez 	    goto trunc;
25841c99275SPeter Avalos     }
25941c99275SPeter Avalos 
260*ed775ee7SAntonio Huete Jimenez     return dstoptlen;
26141c99275SPeter Avalos 
26241c99275SPeter Avalos trunc:
263*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
264*ed775ee7SAntonio Huete Jimenez     return -1;
26541c99275SPeter Avalos }
266