xref: /freebsd/contrib/tcpdump/print-dhcp6.c (revision 5b0fe47811aa43b75fc69dbf7338cace232a4d48)
1b0453382SBill Fenner /*
2b0453382SBill Fenner  * Copyright (C) 1998 and 1999 WIDE Project.
3b0453382SBill Fenner  * All rights reserved.
4b0453382SBill Fenner  *
5b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
6b0453382SBill Fenner  * modification, are permitted provided that the following conditions
7b0453382SBill Fenner  * are met:
8b0453382SBill Fenner  * 1. Redistributions of source code must retain the above copyright
9b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer.
10b0453382SBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
11b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer in the
12b0453382SBill Fenner  *    documentation and/or other materials provided with the distribution.
13b0453382SBill Fenner  * 3. Neither the name of the project nor the names of its contributors
14b0453382SBill Fenner  *    may be used to endorse or promote products derived from this software
15b0453382SBill Fenner  *    without specific prior written permission.
16b0453382SBill Fenner  *
17b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18b0453382SBill Fenner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19b0453382SBill Fenner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20b0453382SBill Fenner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21b0453382SBill Fenner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22b0453382SBill Fenner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23b0453382SBill Fenner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24b0453382SBill Fenner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25b0453382SBill Fenner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26b0453382SBill Fenner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27b0453382SBill Fenner  * SUCH DAMAGE.
28b0453382SBill Fenner  */
299afd0c29SBill Fenner /*
305b0fe478SBruce M Simpson  * RFC3315: DHCPv6
315b0fe478SBruce M Simpson  * supported DHCPv6 options:
325b0fe478SBruce M Simpson  *  RFC3319,
335b0fe478SBruce M Simpson  *  draft-ietf-dhc-dhcpv6-opt-dnsconfig-04.txt,
345b0fe478SBruce M Simpson  *  draft-ietf-dhc-dhcpv6-opt-prefix-delegation-05.txt
355b0fe478SBruce M Simpson  *  draft-ietf-dhc-dhcpv6-opt-timeconfig-02.txt,
369afd0c29SBill Fenner  */
37b0453382SBill Fenner 
38b0453382SBill Fenner #ifndef lint
395b0fe478SBruce M Simpson static const char rcsid[] _U_ =
405b0fe478SBruce M Simpson     "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.27.2.4 2003/11/18 23:26:14 guy Exp $";
41b0453382SBill Fenner #endif
42b0453382SBill Fenner 
43b0453382SBill Fenner #ifdef HAVE_CONFIG_H
44b0453382SBill Fenner #include "config.h"
45b0453382SBill Fenner #endif
46b0453382SBill Fenner 
475b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
48b0453382SBill Fenner 
49b0453382SBill Fenner #include <stdio.h>
50b0453382SBill Fenner #include <string.h>
51b0453382SBill Fenner 
52b0453382SBill Fenner #include "interface.h"
53b0453382SBill Fenner #include "addrtoname.h"
545b0fe478SBruce M Simpson #include "extract.h"
555b0fe478SBruce M Simpson 
565b0fe478SBruce M Simpson /* lease duration */
575b0fe478SBruce M Simpson #define DHCP6_DURATITION_INFINITE 0xffffffff
58b0453382SBill Fenner 
599afd0c29SBill Fenner /* Error Values */
609afd0c29SBill Fenner #define DH6ERR_FAILURE		16
619afd0c29SBill Fenner #define DH6ERR_AUTHFAIL		17
629afd0c29SBill Fenner #define DH6ERR_POORLYFORMED	18
639afd0c29SBill Fenner #define DH6ERR_UNAVAIL		19
649afd0c29SBill Fenner #define DH6ERR_OPTUNAVAIL	20
65b0453382SBill Fenner 
669afd0c29SBill Fenner /* Message type */
675b0fe478SBruce M Simpson #define DH6_SOLICIT	1
685b0fe478SBruce M Simpson #define DH6_ADVERTISE	2
695b0fe478SBruce M Simpson #define DH6_REQUEST	3
705b0fe478SBruce M Simpson #define DH6_CONFIRM	4
715b0fe478SBruce M Simpson #define DH6_RENEW	5
725b0fe478SBruce M Simpson #define DH6_REBIND	6
739afd0c29SBill Fenner #define DH6_REPLY	7
745b0fe478SBruce M Simpson #define DH6_RELEASE	8
755b0fe478SBruce M Simpson #define DH6_DECLINE	9
765b0fe478SBruce M Simpson #define DH6_RECONFIGURE	10
779afd0c29SBill Fenner #define DH6_INFORM_REQ	11
785b0fe478SBruce M Simpson #define DH6_RELAY_FORW	12
795b0fe478SBruce M Simpson #define DH6_RELAY_REPLY	13
80b0453382SBill Fenner 
819afd0c29SBill Fenner /* DHCP6 base packet format */
829afd0c29SBill Fenner struct dhcp6 {
839afd0c29SBill Fenner 	union {
849afd0c29SBill Fenner 		u_int8_t m;
859afd0c29SBill Fenner 		u_int32_t x;
869afd0c29SBill Fenner 	} dh6_msgtypexid;
879afd0c29SBill Fenner 	/* options follow */
885b0fe478SBruce M Simpson };
899afd0c29SBill Fenner #define dh6_msgtype	dh6_msgtypexid.m
909afd0c29SBill Fenner #define dh6_xid		dh6_msgtypexid.x
919afd0c29SBill Fenner #define DH6_XIDMASK	0x00ffffff
92b0453382SBill Fenner 
935b0fe478SBruce M Simpson /* DHCPv6 relay messages */
945b0fe478SBruce M Simpson struct dhcp6_relay {
955b0fe478SBruce M Simpson 	u_int8_t dh6relay_msgtype;
965b0fe478SBruce M Simpson 	u_int8_t dh6relay_hcnt;
975b0fe478SBruce M Simpson 	u_int8_t dh6relay_linkaddr[16];	/* XXX: badly aligned */
985b0fe478SBruce M Simpson 	u_int8_t dh6relay_peeraddr[16];
995b0fe478SBruce M Simpson 	/* options follow */
1005b0fe478SBruce M Simpson };
1015b0fe478SBruce M Simpson 
1025b0fe478SBruce M Simpson /* options */
1035b0fe478SBruce M Simpson #define DH6OPT_CLIENTID	1
1045b0fe478SBruce M Simpson #define DH6OPT_SERVERID	2
1055b0fe478SBruce M Simpson #define DH6OPT_IA_NA 3
1065b0fe478SBruce M Simpson #define DH6OPT_IA_TMP 4
1075b0fe478SBruce M Simpson #define DH6OPT_IADDR 5
1085b0fe478SBruce M Simpson #define DH6OPT_ORO 6
1095b0fe478SBruce M Simpson #define DH6OPT_PREFERENCE 7
1105b0fe478SBruce M Simpson #  define DH6OPT_PREF_UNDEF -1
1115b0fe478SBruce M Simpson #  define DH6OPT_PREF_MAX 255
1125b0fe478SBruce M Simpson #define DH6OPT_ELAPSED_TIME 8
1135b0fe478SBruce M Simpson #define DH6OPT_RELAY_MSG 9
1145b0fe478SBruce M Simpson /*#define DH6OPT_SERVER_MSG 10 deprecated */
1155b0fe478SBruce M Simpson #define DH6OPT_AUTH 11
1165b0fe478SBruce M Simpson #define DH6OPT_UNICAST 12
1175b0fe478SBruce M Simpson #define DH6OPT_STATUS_CODE 13
1185b0fe478SBruce M Simpson #  define DH6OPT_STCODE_SUCCESS 0
1195b0fe478SBruce M Simpson #  define DH6OPT_STCODE_UNSPECFAIL 1
1205b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOADDRAVAIL 2
1215b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOBINDING 3
1225b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOTONLINK 4
1235b0fe478SBruce M Simpson #  define DH6OPT_STCODE_USEMULTICAST 5
1245b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOPREFIXAVAIL 6
1255b0fe478SBruce M Simpson #define DH6OPT_RAPID_COMMIT 14
1265b0fe478SBruce M Simpson #define DH6OPT_USER_CLASS 15
1275b0fe478SBruce M Simpson #define DH6OPT_VENDOR_CLASS 16
1285b0fe478SBruce M Simpson #define DH6OPT_VENDOR_OPTS 17
1295b0fe478SBruce M Simpson #define DH6OPT_INTERFACE_ID 18
1305b0fe478SBruce M Simpson #define DH6OPT_RECONF_MSG 19
1315b0fe478SBruce M Simpson #define DH6OPT_RECONF_ACCEPT 20
1325b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_D 21
1335b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_A 22
1345b0fe478SBruce M Simpson #define DH6OPT_DNS 23
1355b0fe478SBruce M Simpson #define DH6OPT_DNSNAME 24
1365b0fe478SBruce M Simpson 
1375b0fe478SBruce M Simpson /*
1385b0fe478SBruce M Simpson  * The option type has not been assigned for the following options.
1395b0fe478SBruce M Simpson  * We temporarily adopt values used in the service specification document
1405b0fe478SBruce M Simpson  * (200206xx version) by NTT Communications.
1415b0fe478SBruce M Simpson  * Note that we'll change the following definitions if different type values
1425b0fe478SBruce M Simpson  * are officially assigned.
1435b0fe478SBruce M Simpson  */
1445b0fe478SBruce M Simpson #define DH6OPT_PREFIX_DELEGATION 30
1455b0fe478SBruce M Simpson #define DH6OPT_PREFIX_INFORMATION 31
1465b0fe478SBruce M Simpson #define DH6OPT_PREFIX_REQUEST 32
1475b0fe478SBruce M Simpson 
1485b0fe478SBruce M Simpson /*
1495b0fe478SBruce M Simpson  * The followings are also unassigned numbers.
1505b0fe478SBruce M Simpson  * We temporarily use values as of KAME snap 20031013.
1515b0fe478SBruce M Simpson  */
1525b0fe478SBruce M Simpson #define DH6OPT_IA_PD 33
1535b0fe478SBruce M Simpson #define DH6OPT_IA_PD_PREFIX 34
1545b0fe478SBruce M Simpson #define DH6OPT_NTP_SERVERS 35
1555b0fe478SBruce M Simpson 
1569afd0c29SBill Fenner struct dhcp6opt {
1579afd0c29SBill Fenner 	u_int16_t dh6opt_type;
1589afd0c29SBill Fenner 	u_int16_t dh6opt_len;
1599afd0c29SBill Fenner 	/* type-dependent data follows */
1605b0fe478SBruce M Simpson };
1615b0fe478SBruce M Simpson 
1625b0fe478SBruce M Simpson struct dhcp6_ia {
1635b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_type;
1645b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_len;
1655b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_iaid;
1665b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_t1;
1675b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_t2;
1685b0fe478SBruce M Simpson };
1695b0fe478SBruce M Simpson 
1705b0fe478SBruce M Simpson struct dhcp6_ia_prefix {
1715b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_prefix_type;
1725b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_prefix_len;
1735b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_prefix_pltime;
1745b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_prefix_vltime;
1755b0fe478SBruce M Simpson 	u_int8_t dh6opt_ia_prefix_plen;
1765b0fe478SBruce M Simpson 	struct in6_addr dh6opt_ia_prefix_addr;
1779afd0c29SBill Fenner }  __attribute__ ((__packed__));
178b0453382SBill Fenner 
1795b0fe478SBruce M Simpson static const char *
1805b0fe478SBruce M Simpson dhcp6opt_name(int type)
1815b0fe478SBruce M Simpson {
1825b0fe478SBruce M Simpson 	static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
1835b0fe478SBruce M Simpson 
1845b0fe478SBruce M Simpson 	if (type > 65535)
1855b0fe478SBruce M Simpson 		return "INVALID option";
1865b0fe478SBruce M Simpson 
1875b0fe478SBruce M Simpson 	switch(type) {
1885b0fe478SBruce M Simpson 	case DH6OPT_CLIENTID:
1895b0fe478SBruce M Simpson 		return "client ID";
1905b0fe478SBruce M Simpson 	case DH6OPT_SERVERID:
1915b0fe478SBruce M Simpson 		return "server ID";
1925b0fe478SBruce M Simpson 	case DH6OPT_IA_NA:
1935b0fe478SBruce M Simpson 		return "IA_NA";
1945b0fe478SBruce M Simpson 	case DH6OPT_ORO:
1955b0fe478SBruce M Simpson 		return "option request";
1965b0fe478SBruce M Simpson 	case DH6OPT_PREFERENCE:
1975b0fe478SBruce M Simpson 		return "preference";
1985b0fe478SBruce M Simpson 	case DH6OPT_ELAPSED_TIME:
1995b0fe478SBruce M Simpson 		return "elapsed time";
2005b0fe478SBruce M Simpson 	case DH6OPT_RELAY_MSG:
2015b0fe478SBruce M Simpson 		return "relay message";
2025b0fe478SBruce M Simpson 	case DH6OPT_STATUS_CODE:
2035b0fe478SBruce M Simpson 		return "status code";
2045b0fe478SBruce M Simpson 	case DH6OPT_RAPID_COMMIT:
2055b0fe478SBruce M Simpson 		return "rapid commit";
2065b0fe478SBruce M Simpson 	case DH6OPT_INTERFACE_ID:
2075b0fe478SBruce M Simpson 		return "interface ID";
2085b0fe478SBruce M Simpson 	case DH6OPT_RECONF_MSG:
2095b0fe478SBruce M Simpson 		return "reconfigure message";
2105b0fe478SBruce M Simpson 	case DH6OPT_RECONF_ACCEPT:
2115b0fe478SBruce M Simpson 		return "reconfigure accept";
2125b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_D:
2135b0fe478SBruce M Simpson 		return "SIP Servers Domain";
2145b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_A:
2155b0fe478SBruce M Simpson 		return "SIP Servers Address";
2165b0fe478SBruce M Simpson 	case DH6OPT_DNS:
2175b0fe478SBruce M Simpson 		return "DNS";
2185b0fe478SBruce M Simpson 	case DH6OPT_PREFIX_DELEGATION:
2195b0fe478SBruce M Simpson 		return "prefix delegation";
2205b0fe478SBruce M Simpson 	case DH6OPT_PREFIX_INFORMATION:
2215b0fe478SBruce M Simpson 		return "prefix information";
2225b0fe478SBruce M Simpson 	case DH6OPT_IA_PD:
2235b0fe478SBruce M Simpson 		return "IA_PD";
2245b0fe478SBruce M Simpson 	case DH6OPT_IA_PD_PREFIX:
2255b0fe478SBruce M Simpson 		return "IA_PD prefix";
2265b0fe478SBruce M Simpson 	case DH6OPT_NTP_SERVERS:
2275b0fe478SBruce M Simpson 		return "NTP Server";
2285b0fe478SBruce M Simpson 	default:
2295b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "opt_%d", type);
2305b0fe478SBruce M Simpson 		return(genstr);
2315b0fe478SBruce M Simpson 	}
2325b0fe478SBruce M Simpson }
2335b0fe478SBruce M Simpson 
2345b0fe478SBruce M Simpson static const char *
2355b0fe478SBruce M Simpson dhcp6stcode(int code)
2365b0fe478SBruce M Simpson {
2375b0fe478SBruce M Simpson 	static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
2385b0fe478SBruce M Simpson 
2395b0fe478SBruce M Simpson 	if (code > 255)
2405b0fe478SBruce M Simpson 		return "INVALID code";
2415b0fe478SBruce M Simpson 
2425b0fe478SBruce M Simpson 	switch(code) {
2435b0fe478SBruce M Simpson 	case DH6OPT_STCODE_SUCCESS:
2445b0fe478SBruce M Simpson 		return "success";
2455b0fe478SBruce M Simpson 	case DH6OPT_STCODE_UNSPECFAIL:
2465b0fe478SBruce M Simpson 		return "unspec failure";
2475b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOADDRAVAIL:
2485b0fe478SBruce M Simpson 		return "no addresses";
2495b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOBINDING:
2505b0fe478SBruce M Simpson 		return "no binding";
2515b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOTONLINK:
2525b0fe478SBruce M Simpson 		return "not on-link";
2535b0fe478SBruce M Simpson 	case DH6OPT_STCODE_USEMULTICAST:
2545b0fe478SBruce M Simpson 		return "use multicast";
2555b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOPREFIXAVAIL:
2565b0fe478SBruce M Simpson 		return "no prefixes";
2575b0fe478SBruce M Simpson 	default:
2585b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "code%d", code);
2595b0fe478SBruce M Simpson 		return(genstr);
2605b0fe478SBruce M Simpson 	}
2615b0fe478SBruce M Simpson }
2625b0fe478SBruce M Simpson 
263b0453382SBill Fenner static void
2645b0fe478SBruce M Simpson dhcp6opt_print(const u_char *cp, const u_char *ep)
265b0453382SBill Fenner {
2669afd0c29SBill Fenner 	struct dhcp6opt *dh6o;
2679afd0c29SBill Fenner 	u_char *tp;
2685b0fe478SBruce M Simpson 	size_t i;
2695b0fe478SBruce M Simpson 	u_int16_t opttype;
2709afd0c29SBill Fenner 	size_t optlen;
2715b0fe478SBruce M Simpson 	u_int16_t val16;
2725b0fe478SBruce M Simpson 	u_int32_t val32;
2735b0fe478SBruce M Simpson 	struct in6_addr addr6;
2745b0fe478SBruce M Simpson 	struct dhcp6_ia ia;
2755b0fe478SBruce M Simpson 	struct dhcp6_ia_prefix ia_prefix;
276b0453382SBill Fenner 
277b0453382SBill Fenner 	if (cp == ep)
278b0453382SBill Fenner 		return;
279b0453382SBill Fenner 	while (cp < ep) {
2805b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o))
281b0453382SBill Fenner 			goto trunc;
2829afd0c29SBill Fenner 		dh6o = (struct dhcp6opt *)cp;
2835b0fe478SBruce M Simpson 		optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
2845b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o) + optlen)
285b0453382SBill Fenner 			goto trunc;
2865b0fe478SBruce M Simpson 		opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
2875b0fe478SBruce M Simpson 		printf(" (%s", dhcp6opt_name(opttype));
2885b0fe478SBruce M Simpson 		switch (opttype) {
2895b0fe478SBruce M Simpson 		case DH6OPT_CLIENTID:
2905b0fe478SBruce M Simpson 		case DH6OPT_SERVERID:
2919afd0c29SBill Fenner 			if (optlen < 2) {
2929afd0c29SBill Fenner 				/*(*/
2935b0fe478SBruce M Simpson 				printf(" ?)");
294b0453382SBill Fenner 				break;
295b0453382SBill Fenner 			}
2969afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
2975b0fe478SBruce M Simpson 			switch (EXTRACT_16BITS(tp)) {
2989afd0c29SBill Fenner 			case 1:
2999afd0c29SBill Fenner 				if (optlen >= 2 + 6) {
3005b0fe478SBruce M Simpson 					printf(" hwaddr/time type %u time %u ",
3015b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]),
3025b0fe478SBruce M Simpson 					    EXTRACT_32BITS(&tp[4]));
3039afd0c29SBill Fenner 					for (i = 8; i < optlen; i++)
3049afd0c29SBill Fenner 						printf("%02x", tp[i]);
3059afd0c29SBill Fenner 					/*(*/
306b0453382SBill Fenner 					printf(")");
3079afd0c29SBill Fenner 				} else {
3089afd0c29SBill Fenner 					/*(*/
3095b0fe478SBruce M Simpson 					printf(" ?)");
3109afd0c29SBill Fenner 				}
3119afd0c29SBill Fenner 				break;
3129afd0c29SBill Fenner 			case 2:
3139afd0c29SBill Fenner 				if (optlen >= 2 + 8) {
3149afd0c29SBill Fenner 					printf(" vid ");
3159afd0c29SBill Fenner 					for (i = 2; i < 2 + 8; i++)
3169afd0c29SBill Fenner 						printf("%02x", tp[i]);
3179afd0c29SBill Fenner 					/*(*/
3189afd0c29SBill Fenner 					printf(")");
3199afd0c29SBill Fenner 				} else {
3209afd0c29SBill Fenner 					/*(*/
3215b0fe478SBruce M Simpson 					printf(" ?)");
3229afd0c29SBill Fenner 				}
3239afd0c29SBill Fenner 				break;
3249afd0c29SBill Fenner 			case 3:
3259afd0c29SBill Fenner 				if (optlen >= 2 + 2) {
3269afd0c29SBill Fenner 					printf(" hwaddr type %u ",
3275b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]));
3289afd0c29SBill Fenner 					for (i = 4; i < optlen; i++)
3299afd0c29SBill Fenner 						printf("%02x", tp[i]);
3309afd0c29SBill Fenner 					/*(*/
3319afd0c29SBill Fenner 					printf(")");
3329afd0c29SBill Fenner 				} else {
3339afd0c29SBill Fenner 					/*(*/
3345b0fe478SBruce M Simpson 					printf(" ?)");
3359afd0c29SBill Fenner 				}
3369afd0c29SBill Fenner 				break;
3375b0fe478SBruce M Simpson 			default:
3385b0fe478SBruce M Simpson 				printf(" type %d)", EXTRACT_16BITS(tp));
3395b0fe478SBruce M Simpson 				break;
3405b0fe478SBruce M Simpson 			}
3415b0fe478SBruce M Simpson 			break;
3425b0fe478SBruce M Simpson 		case DH6OPT_ORO:
3435b0fe478SBruce M Simpson 			if (optlen % 2) {
3445b0fe478SBruce M Simpson 				printf(" ?)");
3455b0fe478SBruce M Simpson 				break;
3465b0fe478SBruce M Simpson 			}
3475b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
3485b0fe478SBruce M Simpson 			for (i = 0; i < optlen; i += 2) {
3495b0fe478SBruce M Simpson 				u_int16_t opt;
3505b0fe478SBruce M Simpson 
3515b0fe478SBruce M Simpson 				memcpy(&opt, &tp[i], sizeof(opt));
3525b0fe478SBruce M Simpson 				printf(" %s", dhcp6opt_name(ntohs(opt)));
3535b0fe478SBruce M Simpson 			}
3545b0fe478SBruce M Simpson 			printf(")");
3555b0fe478SBruce M Simpson 			break;
3565b0fe478SBruce M Simpson 		case DH6OPT_PREFERENCE:
3575b0fe478SBruce M Simpson 			if (optlen != 1) {
3585b0fe478SBruce M Simpson 				printf(" ?)");
3595b0fe478SBruce M Simpson 				break;
3605b0fe478SBruce M Simpson 			}
3615b0fe478SBruce M Simpson 			printf(" %d)", *((u_char *)(dh6o + 1) + 1));
3625b0fe478SBruce M Simpson 			break;
3635b0fe478SBruce M Simpson 		case DH6OPT_ELAPSED_TIME:
3645b0fe478SBruce M Simpson 			if (optlen != 2) {
3655b0fe478SBruce M Simpson 				printf(" ?)");
3665b0fe478SBruce M Simpson 				break;
3675b0fe478SBruce M Simpson 			}
3685b0fe478SBruce M Simpson 			memcpy(&val16, dh6o + 1, sizeof(val16));
3695b0fe478SBruce M Simpson 			val16 = ntohs(val16);
3705b0fe478SBruce M Simpson 			printf(" %d)", (int)val16);
3715b0fe478SBruce M Simpson 			break;
3725b0fe478SBruce M Simpson 		case DH6OPT_RELAY_MSG:
3735b0fe478SBruce M Simpson 			printf(" (");
3745b0fe478SBruce M Simpson 			dhcp6_print((const u_char *)(dh6o + 1), optlen);
3755b0fe478SBruce M Simpson 			printf(")");
3765b0fe478SBruce M Simpson 			break;
3775b0fe478SBruce M Simpson 		case DH6OPT_RAPID_COMMIT: /* nothing todo */
3785b0fe478SBruce M Simpson 			printf(")");
3795b0fe478SBruce M Simpson 			break;
3805b0fe478SBruce M Simpson 		case DH6OPT_INTERFACE_ID:
3815b0fe478SBruce M Simpson 			/*
3825b0fe478SBruce M Simpson 			 * Since we cannot predict the encoding, print hex dump
3835b0fe478SBruce M Simpson 			 * at most 10 characters.
3845b0fe478SBruce M Simpson 			 */
3855b0fe478SBruce M Simpson 			for (i = 0; i < optlen && i < 10; i++)
3865b0fe478SBruce M Simpson 				printf("%02x", ((u_char *)(dh6o + 1))[i]);
3875b0fe478SBruce M Simpson 			break;
3885b0fe478SBruce M Simpson 		case DH6OPT_RECONF_MSG:
3895b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
3905b0fe478SBruce M Simpson 			switch (*tp) {
3915b0fe478SBruce M Simpson 			case DH6_RENEW:
3925b0fe478SBruce M Simpson 				printf(" for renew)");
3935b0fe478SBruce M Simpson 				break;
3945b0fe478SBruce M Simpson 			case DH6_INFORM_REQ:
3955b0fe478SBruce M Simpson 				printf(" for inf-req)");
3965b0fe478SBruce M Simpson 				break;
3975b0fe478SBruce M Simpson 			default:
3985b0fe478SBruce M Simpson 				printf(" for ?\?\?(%02x))", *tp);
3995b0fe478SBruce M Simpson 				break;
4005b0fe478SBruce M Simpson 			}
4015b0fe478SBruce M Simpson 			break;
4025b0fe478SBruce M Simpson 		case DH6OPT_RECONF_ACCEPT: /* nothing todo */
4035b0fe478SBruce M Simpson 			printf(")");
4045b0fe478SBruce M Simpson 			break;
4055b0fe478SBruce M Simpson 		case DH6OPT_SIP_SERVER_A:
4069afd0c29SBill Fenner 		case DH6OPT_DNS:
4075b0fe478SBruce M Simpson 		case DH6OPT_NTP_SERVERS:
4089afd0c29SBill Fenner 			if (optlen % 16) {
4095b0fe478SBruce M Simpson 				printf(" ?)");
4109afd0c29SBill Fenner 				break;
4119afd0c29SBill Fenner 			}
4129afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
4139afd0c29SBill Fenner 			for (i = 0; i < optlen; i += 16)
4149afd0c29SBill Fenner 				printf(" %s", ip6addr_string(&tp[i]));
4159afd0c29SBill Fenner 			printf(")");
4165b0fe478SBruce M Simpson 			break;
4175b0fe478SBruce M Simpson 		case DH6OPT_PREFIX_DELEGATION:
4185b0fe478SBruce M Simpson 			dhcp6opt_print((u_char *)(dh6o + 1),
4195b0fe478SBruce M Simpson 			    (u_char *)(dh6o + 1) + optlen);
4205b0fe478SBruce M Simpson 			printf(")");
4215b0fe478SBruce M Simpson 			break;
4225b0fe478SBruce M Simpson 		case DH6OPT_PREFIX_INFORMATION:
4235b0fe478SBruce M Simpson 			if (optlen % 21)
4245b0fe478SBruce M Simpson 				printf(" ?)");
4255b0fe478SBruce M Simpson 			memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
4265b0fe478SBruce M Simpson 			    sizeof(addr6));
4275b0fe478SBruce M Simpson 			printf(" %s/%d", ip6addr_string(&addr6),
4285b0fe478SBruce M Simpson 			    (int)*((u_char *)(dh6o + 1) + 4));
4295b0fe478SBruce M Simpson 			memcpy(&val32, dh6o + 1, sizeof(val32));
4305b0fe478SBruce M Simpson 			val32 = ntohl(val32);
4315b0fe478SBruce M Simpson 			if (val32 == DHCP6_DURATITION_INFINITE)
4325b0fe478SBruce M Simpson 				printf(" lease-duration: infinite)");
4335b0fe478SBruce M Simpson 			else
4345b0fe478SBruce M Simpson 				printf(" lease-duration: %u)", val32);
4355b0fe478SBruce M Simpson 			break;
4365b0fe478SBruce M Simpson 		case DH6OPT_STATUS_CODE:
4375b0fe478SBruce M Simpson 			if (optlen < 2) {
4385b0fe478SBruce M Simpson 				printf(" ?)");
4395b0fe478SBruce M Simpson 				break;
4405b0fe478SBruce M Simpson 			}
4415b0fe478SBruce M Simpson 			memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
4425b0fe478SBruce M Simpson 			val16 = ntohs(val16);
4435b0fe478SBruce M Simpson 			printf(" %s)", dhcp6stcode(val16));
4445b0fe478SBruce M Simpson 			break;
4455b0fe478SBruce M Simpson 		case DH6OPT_IA_NA:
4465b0fe478SBruce M Simpson 		case DH6OPT_IA_PD:
4475b0fe478SBruce M Simpson 			if (optlen < sizeof(ia) - 4) {
4485b0fe478SBruce M Simpson 				printf(" ?)");
4495b0fe478SBruce M Simpson 				break;
4505b0fe478SBruce M Simpson 			}
4515b0fe478SBruce M Simpson 			memcpy(&ia, (u_char *)dh6o, sizeof(ia));
4525b0fe478SBruce M Simpson 			ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid);
4535b0fe478SBruce M Simpson 			ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1);
4545b0fe478SBruce M Simpson 			ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2);
4555b0fe478SBruce M Simpson 			printf(" IAID:%lu T1:%lu T2:%lu",
4565b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_iaid,
4575b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_t1,
4585b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_t2);
4595b0fe478SBruce M Simpson 			if (optlen > sizeof(ia) - 4) {
4605b0fe478SBruce M Simpson 				/* there are sub-options */
4615b0fe478SBruce M Simpson 				dhcp6opt_print((u_char *)dh6o + sizeof(ia),
4625b0fe478SBruce M Simpson 				    (u_char *)(dh6o + 1) + optlen);
4635b0fe478SBruce M Simpson 			}
4645b0fe478SBruce M Simpson 			printf(")");
4655b0fe478SBruce M Simpson 			break;
4665b0fe478SBruce M Simpson 		case DH6OPT_IA_PD_PREFIX:
4675b0fe478SBruce M Simpson 			if (optlen < sizeof(ia_prefix) - 4) {
4685b0fe478SBruce M Simpson 				printf(" ?)");
4695b0fe478SBruce M Simpson 				break;
4705b0fe478SBruce M Simpson 			}
4715b0fe478SBruce M Simpson 			memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix));
4725b0fe478SBruce M Simpson 			printf(" %s/%d",
4735b0fe478SBruce M Simpson 			    ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr),
4745b0fe478SBruce M Simpson 			    ia_prefix.dh6opt_ia_prefix_plen);
4755b0fe478SBruce M Simpson 			ia_prefix.dh6opt_ia_prefix_pltime =
4765b0fe478SBruce M Simpson 			    ntohl(ia_prefix.dh6opt_ia_prefix_pltime);
4775b0fe478SBruce M Simpson 			ia_prefix.dh6opt_ia_prefix_vltime =
4785b0fe478SBruce M Simpson 			    ntohl(ia_prefix.dh6opt_ia_prefix_vltime);
4795b0fe478SBruce M Simpson 			printf(" pltime:%lu vltime:%lu",
4805b0fe478SBruce M Simpson 			    (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime,
4815b0fe478SBruce M Simpson 			    (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime);
4825b0fe478SBruce M Simpson 			if (optlen > sizeof(ia_prefix) - 4) {
4835b0fe478SBruce M Simpson 				/* there are sub-options */
4845b0fe478SBruce M Simpson 				dhcp6opt_print((u_char *)dh6o +
4855b0fe478SBruce M Simpson 				    sizeof(ia_prefix),
4865b0fe478SBruce M Simpson 				    (u_char *)(dh6o + 1) + optlen);
4875b0fe478SBruce M Simpson 			}
4885b0fe478SBruce M Simpson 			printf(")");
4895b0fe478SBruce M Simpson 			break;
4909afd0c29SBill Fenner 		default:
4915b0fe478SBruce M Simpson 			printf(")");
4929afd0c29SBill Fenner 			break;
4939afd0c29SBill Fenner 		}
4949afd0c29SBill Fenner 
4959afd0c29SBill Fenner 		cp += sizeof(*dh6o) + optlen;
496b0453382SBill Fenner 	}
497b0453382SBill Fenner 	return;
498b0453382SBill Fenner 
499b0453382SBill Fenner trunc:
500b0453382SBill Fenner 	printf("[|dhcp6ext]");
501b0453382SBill Fenner }
502b0453382SBill Fenner 
503b0453382SBill Fenner /*
5049afd0c29SBill Fenner  * Print dhcp6 packets
505b0453382SBill Fenner  */
506b0453382SBill Fenner void
5075b0fe478SBruce M Simpson dhcp6_print(const u_char *cp, u_int length)
508b0453382SBill Fenner {
5099afd0c29SBill Fenner 	struct dhcp6 *dh6;
5105b0fe478SBruce M Simpson 	struct dhcp6_relay *dh6relay;
5115b0fe478SBruce M Simpson 	const u_char *ep;
512b0453382SBill Fenner 	u_char *extp;
5139afd0c29SBill Fenner 	const char *name;
514b0453382SBill Fenner 
515b0453382SBill Fenner 	printf("dhcp6");
516b0453382SBill Fenner 
517b0453382SBill Fenner 	ep = (u_char *)snapend;
5185b0fe478SBruce M Simpson 	if (cp + length < ep)
5195b0fe478SBruce M Simpson 		ep = cp + length;
520b0453382SBill Fenner 
5219afd0c29SBill Fenner 	dh6 = (struct dhcp6 *)cp;
5225b0fe478SBruce M Simpson 	dh6relay = (struct dhcp6_relay *)cp;
5235b0fe478SBruce M Simpson 	TCHECK(dh6->dh6_xid);
524b0453382SBill Fenner 	switch (dh6->dh6_msgtype) {
5255b0fe478SBruce M Simpson 	case DH6_SOLICIT:
5265b0fe478SBruce M Simpson 		name = "solicit";
5275b0fe478SBruce M Simpson 		break;
5285b0fe478SBruce M Simpson 	case DH6_ADVERTISE:
5295b0fe478SBruce M Simpson 		name = "advertise";
5305b0fe478SBruce M Simpson 		break;
5315b0fe478SBruce M Simpson 	case DH6_REQUEST:
5325b0fe478SBruce M Simpson 		name = "request";
5335b0fe478SBruce M Simpson 		break;
5345b0fe478SBruce M Simpson 	case DH6_CONFIRM:
5355b0fe478SBruce M Simpson 		name = "confirm";
5365b0fe478SBruce M Simpson 		break;
5375b0fe478SBruce M Simpson 	case DH6_RENEW:
5385b0fe478SBruce M Simpson 		name = "renew";
5395b0fe478SBruce M Simpson 		break;
5405b0fe478SBruce M Simpson 	case DH6_REBIND:
5415b0fe478SBruce M Simpson 		name = "rebind";
5425b0fe478SBruce M Simpson 		break;
543b0453382SBill Fenner 	case DH6_REPLY:
5449afd0c29SBill Fenner 		name = "reply";
5459afd0c29SBill Fenner 		break;
5465b0fe478SBruce M Simpson 	case DH6_RELEASE:
5475b0fe478SBruce M Simpson 		name = "release";
5485b0fe478SBruce M Simpson 		break;
5495b0fe478SBruce M Simpson 	case DH6_DECLINE:
5505b0fe478SBruce M Simpson 		name = "decline";
5515b0fe478SBruce M Simpson 		break;
5525b0fe478SBruce M Simpson 	case DH6_RECONFIGURE:
5535b0fe478SBruce M Simpson 		name = "reconfigure";
5545b0fe478SBruce M Simpson 		break;
5559afd0c29SBill Fenner 	case DH6_INFORM_REQ:
5569afd0c29SBill Fenner 		name= "inf-req";
5579afd0c29SBill Fenner 		break;
5585b0fe478SBruce M Simpson 	case DH6_RELAY_FORW:
5595b0fe478SBruce M Simpson 		name= "relay-fwd";
5605b0fe478SBruce M Simpson 		break;
5615b0fe478SBruce M Simpson 	case DH6_RELAY_REPLY:
5625b0fe478SBruce M Simpson 		name= "relay-reply";
5635b0fe478SBruce M Simpson 		break;
5649afd0c29SBill Fenner 	default:
5659afd0c29SBill Fenner 		name = NULL;
566b0453382SBill Fenner 		break;
567b0453382SBill Fenner 	}
5689afd0c29SBill Fenner 
5699afd0c29SBill Fenner 	if (!vflag) {
5709afd0c29SBill Fenner 		if (name)
5719afd0c29SBill Fenner 			printf(" %s", name);
5725b0fe478SBruce M Simpson 		else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
5735b0fe478SBruce M Simpson 		    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
5749afd0c29SBill Fenner 			printf(" msgtype-%u", dh6->dh6_msgtype);
5755b0fe478SBruce M Simpson 		}
5769afd0c29SBill Fenner 		return;
577b0453382SBill Fenner 	}
5789afd0c29SBill Fenner 
5799afd0c29SBill Fenner 	/* XXX relay agent messages have to be handled differently */
5809afd0c29SBill Fenner 
5819afd0c29SBill Fenner 	if (name)
5829afd0c29SBill Fenner 		printf(" %s (", name);	/*)*/
5839afd0c29SBill Fenner 	else
5849afd0c29SBill Fenner 		printf(" msgtype-%u (", dh6->dh6_msgtype);	/*)*/
5855b0fe478SBruce M Simpson 	if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
5865b0fe478SBruce M Simpson 	    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
5875b0fe478SBruce M Simpson 		printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
5889afd0c29SBill Fenner 		extp = (u_char *)(dh6 + 1);
5899afd0c29SBill Fenner 		dhcp6opt_print(extp, ep);
5905b0fe478SBruce M Simpson 	} else {		/* relay messages */
5915b0fe478SBruce M Simpson 		struct in6_addr addr6;
5925b0fe478SBruce M Simpson 
5935b0fe478SBruce M Simpson 		TCHECK(dh6relay->dh6relay_peeraddr);
5945b0fe478SBruce M Simpson 
5955b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
5965b0fe478SBruce M Simpson 		printf("linkaddr=%s", ip6addr_string(&addr6));
5975b0fe478SBruce M Simpson 
5985b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
5995b0fe478SBruce M Simpson 		printf(" peeraddr=%s", ip6addr_string(&addr6));
6005b0fe478SBruce M Simpson 
6015b0fe478SBruce M Simpson 		dhcp6opt_print((u_char *)(dh6relay + 1), ep);
6025b0fe478SBruce M Simpson 	}
603685295f4SBill Fenner 	/*(*/
604b0453382SBill Fenner 	printf(")");
605b0453382SBill Fenner 	return;
606b0453382SBill Fenner 
607b0453382SBill Fenner trunc:
6089afd0c29SBill Fenner 	printf("[|dhcp6]");
609b0453382SBill Fenner }
610