xref: /freebsd/contrib/tcpdump/print-dhcp6.c (revision 1de50e9f417616cf647a842762944a2301cb1415)
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,
331de50e9fSSam Leffler  *  RFC3633,
341de50e9fSSam Leffler  *  RFC3646,
351de50e9fSSam Leffler  *  draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt,
361de50e9fSSam Leffler  *  draft-ietf-dhc-lifetime-00.txt,
379afd0c29SBill Fenner  */
38b0453382SBill Fenner 
39b0453382SBill Fenner #ifndef lint
405b0fe478SBruce M Simpson static const char rcsid[] _U_ =
411de50e9fSSam Leffler     "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.35 2004/07/06 22:16:03 guy Exp $";
42b0453382SBill Fenner #endif
43b0453382SBill Fenner 
44b0453382SBill Fenner #ifdef HAVE_CONFIG_H
45b0453382SBill Fenner #include "config.h"
46b0453382SBill Fenner #endif
47b0453382SBill Fenner 
485b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
49b0453382SBill Fenner 
50b0453382SBill Fenner #include <stdio.h>
51b0453382SBill Fenner #include <string.h>
52b0453382SBill Fenner 
53b0453382SBill Fenner #include "interface.h"
54b0453382SBill Fenner #include "addrtoname.h"
555b0fe478SBruce M Simpson #include "extract.h"
565b0fe478SBruce M Simpson 
575b0fe478SBruce M Simpson /* lease duration */
585b0fe478SBruce M Simpson #define DHCP6_DURATITION_INFINITE 0xffffffff
59b0453382SBill Fenner 
609afd0c29SBill Fenner /* Error Values */
619afd0c29SBill Fenner #define DH6ERR_FAILURE		16
629afd0c29SBill Fenner #define DH6ERR_AUTHFAIL		17
639afd0c29SBill Fenner #define DH6ERR_POORLYFORMED	18
649afd0c29SBill Fenner #define DH6ERR_UNAVAIL		19
659afd0c29SBill Fenner #define DH6ERR_OPTUNAVAIL	20
66b0453382SBill Fenner 
679afd0c29SBill Fenner /* Message type */
685b0fe478SBruce M Simpson #define DH6_SOLICIT	1
695b0fe478SBruce M Simpson #define DH6_ADVERTISE	2
705b0fe478SBruce M Simpson #define DH6_REQUEST	3
715b0fe478SBruce M Simpson #define DH6_CONFIRM	4
725b0fe478SBruce M Simpson #define DH6_RENEW	5
735b0fe478SBruce M Simpson #define DH6_REBIND	6
749afd0c29SBill Fenner #define DH6_REPLY	7
755b0fe478SBruce M Simpson #define DH6_RELEASE	8
765b0fe478SBruce M Simpson #define DH6_DECLINE	9
775b0fe478SBruce M Simpson #define DH6_RECONFIGURE	10
789afd0c29SBill Fenner #define DH6_INFORM_REQ	11
795b0fe478SBruce M Simpson #define DH6_RELAY_FORW	12
805b0fe478SBruce M Simpson #define DH6_RELAY_REPLY	13
81b0453382SBill Fenner 
829afd0c29SBill Fenner /* DHCP6 base packet format */
839afd0c29SBill Fenner struct dhcp6 {
849afd0c29SBill Fenner 	union {
859afd0c29SBill Fenner 		u_int8_t m;
869afd0c29SBill Fenner 		u_int32_t x;
879afd0c29SBill Fenner 	} dh6_msgtypexid;
889afd0c29SBill Fenner 	/* options follow */
895b0fe478SBruce M Simpson };
909afd0c29SBill Fenner #define dh6_msgtype	dh6_msgtypexid.m
919afd0c29SBill Fenner #define dh6_xid		dh6_msgtypexid.x
929afd0c29SBill Fenner #define DH6_XIDMASK	0x00ffffff
93b0453382SBill Fenner 
945b0fe478SBruce M Simpson /* DHCPv6 relay messages */
955b0fe478SBruce M Simpson struct dhcp6_relay {
965b0fe478SBruce M Simpson 	u_int8_t dh6relay_msgtype;
975b0fe478SBruce M Simpson 	u_int8_t dh6relay_hcnt;
985b0fe478SBruce M Simpson 	u_int8_t dh6relay_linkaddr[16];	/* XXX: badly aligned */
995b0fe478SBruce M Simpson 	u_int8_t dh6relay_peeraddr[16];
1005b0fe478SBruce M Simpson 	/* options follow */
1015b0fe478SBruce M Simpson };
1025b0fe478SBruce M Simpson 
1035b0fe478SBruce M Simpson /* options */
1045b0fe478SBruce M Simpson #define DH6OPT_CLIENTID	1
1055b0fe478SBruce M Simpson #define DH6OPT_SERVERID	2
1065b0fe478SBruce M Simpson #define DH6OPT_IA_NA 3
1075b0fe478SBruce M Simpson #define DH6OPT_IA_TMP 4
1085b0fe478SBruce M Simpson #define DH6OPT_IADDR 5
1095b0fe478SBruce M Simpson #define DH6OPT_ORO 6
1105b0fe478SBruce M Simpson #define DH6OPT_PREFERENCE 7
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
1161de50e9fSSam Leffler #  define DH6OPT_AUTHPROTO_DELAYED 2
1171de50e9fSSam Leffler #  define DH6OPT_AUTHPROTO_RECONFIG 3
1181de50e9fSSam Leffler #  define DH6OPT_AUTHALG_HMACMD5 1
1191de50e9fSSam Leffler #  define DH6OPT_AUTHRDM_MONOCOUNTER 0
1201de50e9fSSam Leffler #  define DH6OPT_AUTHRECONFIG_KEY 1
1211de50e9fSSam Leffler #  define DH6OPT_AUTHRECONFIG_HMACMD5 2
1225b0fe478SBruce M Simpson #define DH6OPT_UNICAST 12
1235b0fe478SBruce M Simpson #define DH6OPT_STATUS_CODE 13
1245b0fe478SBruce M Simpson #  define DH6OPT_STCODE_SUCCESS 0
1255b0fe478SBruce M Simpson #  define DH6OPT_STCODE_UNSPECFAIL 1
1265b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOADDRAVAIL 2
1275b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOBINDING 3
1285b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOTONLINK 4
1295b0fe478SBruce M Simpson #  define DH6OPT_STCODE_USEMULTICAST 5
1305b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOPREFIXAVAIL 6
1315b0fe478SBruce M Simpson #define DH6OPT_RAPID_COMMIT 14
1325b0fe478SBruce M Simpson #define DH6OPT_USER_CLASS 15
1335b0fe478SBruce M Simpson #define DH6OPT_VENDOR_CLASS 16
1345b0fe478SBruce M Simpson #define DH6OPT_VENDOR_OPTS 17
1355b0fe478SBruce M Simpson #define DH6OPT_INTERFACE_ID 18
1365b0fe478SBruce M Simpson #define DH6OPT_RECONF_MSG 19
1375b0fe478SBruce M Simpson #define DH6OPT_RECONF_ACCEPT 20
1385b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_D 21
1395b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_A 22
1405b0fe478SBruce M Simpson #define DH6OPT_DNS 23
1415b0fe478SBruce M Simpson #define DH6OPT_DNSNAME 24
1421de50e9fSSam Leffler #define DH6OPT_IA_PD 25
1431de50e9fSSam Leffler #define DH6OPT_IA_PD_PREFIX 26
1445b0fe478SBruce M Simpson 
1455b0fe478SBruce M Simpson /*
1461de50e9fSSam Leffler  * The old prefix delegation option used in the service specification document
1475b0fe478SBruce M Simpson  * (200206xx version) by NTT Communications.
1485b0fe478SBruce M Simpson  */
1495b0fe478SBruce M Simpson #define DH6OPT_PREFIX_DELEGATION 30
1505b0fe478SBruce M Simpson #define DH6OPT_PREFIX_INFORMATION 31
1515b0fe478SBruce M Simpson #define DH6OPT_PREFIX_REQUEST 32
1525b0fe478SBruce M Simpson 
1535b0fe478SBruce M Simpson /*
1541de50e9fSSam Leffler  * The following one is an unassigned number.
1551de50e9fSSam Leffler  * We temporarily use values as of KAME snap 20040322.
1565b0fe478SBruce M Simpson  */
1575b0fe478SBruce M Simpson #define DH6OPT_NTP_SERVERS 35
1581de50e9fSSam Leffler #define DH6OPT_LIFETIME 36
1595b0fe478SBruce M Simpson 
1609afd0c29SBill Fenner struct dhcp6opt {
1619afd0c29SBill Fenner 	u_int16_t dh6opt_type;
1629afd0c29SBill Fenner 	u_int16_t dh6opt_len;
1639afd0c29SBill Fenner 	/* type-dependent data follows */
1645b0fe478SBruce M Simpson };
1655b0fe478SBruce M Simpson 
1665b0fe478SBruce M Simpson struct dhcp6_ia {
1675b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_type;
1685b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_len;
1695b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_iaid;
1705b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_t1;
1715b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_t2;
1725b0fe478SBruce M Simpson };
1735b0fe478SBruce M Simpson 
1745b0fe478SBruce M Simpson struct dhcp6_ia_prefix {
1755b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_prefix_type;
1765b0fe478SBruce M Simpson 	u_int16_t dh6opt_ia_prefix_len;
1775b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_prefix_pltime;
1785b0fe478SBruce M Simpson 	u_int32_t dh6opt_ia_prefix_vltime;
1795b0fe478SBruce M Simpson 	u_int8_t dh6opt_ia_prefix_plen;
1805b0fe478SBruce M Simpson 	struct in6_addr dh6opt_ia_prefix_addr;
1819afd0c29SBill Fenner }  __attribute__ ((__packed__));
182b0453382SBill Fenner 
1831de50e9fSSam Leffler struct dhcp6_auth {
1841de50e9fSSam Leffler 	u_int16_t dh6opt_auth_type;
1851de50e9fSSam Leffler 	u_int16_t dh6opt_auth_len;
1861de50e9fSSam Leffler 	u_int8_t dh6opt_auth_proto;
1871de50e9fSSam Leffler 	u_int8_t dh6opt_auth_alg;
1881de50e9fSSam Leffler 	u_int8_t dh6opt_auth_rdm;
1891de50e9fSSam Leffler 	u_int8_t dh6opt_auth_rdinfo[8];
1901de50e9fSSam Leffler 	/* authentication information follows */
1911de50e9fSSam Leffler } __attribute__ ((__packed__));
1921de50e9fSSam Leffler 
1935b0fe478SBruce M Simpson static const char *
1945b0fe478SBruce M Simpson dhcp6opt_name(int type)
1955b0fe478SBruce M Simpson {
1965b0fe478SBruce M Simpson 	static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
1975b0fe478SBruce M Simpson 
1985b0fe478SBruce M Simpson 	if (type > 65535)
1995b0fe478SBruce M Simpson 		return "INVALID option";
2005b0fe478SBruce M Simpson 
2015b0fe478SBruce M Simpson 	switch(type) {
2025b0fe478SBruce M Simpson 	case DH6OPT_CLIENTID:
2035b0fe478SBruce M Simpson 		return "client ID";
2045b0fe478SBruce M Simpson 	case DH6OPT_SERVERID:
2055b0fe478SBruce M Simpson 		return "server ID";
2065b0fe478SBruce M Simpson 	case DH6OPT_IA_NA:
2075b0fe478SBruce M Simpson 		return "IA_NA";
2085b0fe478SBruce M Simpson 	case DH6OPT_ORO:
2095b0fe478SBruce M Simpson 		return "option request";
2105b0fe478SBruce M Simpson 	case DH6OPT_PREFERENCE:
2115b0fe478SBruce M Simpson 		return "preference";
2125b0fe478SBruce M Simpson 	case DH6OPT_ELAPSED_TIME:
2135b0fe478SBruce M Simpson 		return "elapsed time";
2145b0fe478SBruce M Simpson 	case DH6OPT_RELAY_MSG:
2155b0fe478SBruce M Simpson 		return "relay message";
2161de50e9fSSam Leffler 	case DH6OPT_AUTH:
2171de50e9fSSam Leffler 		return "authentication";
2181de50e9fSSam Leffler 	case DH6OPT_UNICAST:
2191de50e9fSSam Leffler 		return "server unicast";
2205b0fe478SBruce M Simpson 	case DH6OPT_STATUS_CODE:
2215b0fe478SBruce M Simpson 		return "status code";
2225b0fe478SBruce M Simpson 	case DH6OPT_RAPID_COMMIT:
2235b0fe478SBruce M Simpson 		return "rapid commit";
2241de50e9fSSam Leffler 	case DH6OPT_USER_CLASS:
2251de50e9fSSam Leffler 		return "user class";
2261de50e9fSSam Leffler 	case DH6OPT_VENDOR_CLASS:
2271de50e9fSSam Leffler 		return "vendor class";
2281de50e9fSSam Leffler 	case DH6OPT_VENDOR_OPTS:
2291de50e9fSSam Leffler 		return "vendor-specific info";
2305b0fe478SBruce M Simpson 	case DH6OPT_INTERFACE_ID:
2315b0fe478SBruce M Simpson 		return "interface ID";
2325b0fe478SBruce M Simpson 	case DH6OPT_RECONF_MSG:
2335b0fe478SBruce M Simpson 		return "reconfigure message";
2345b0fe478SBruce M Simpson 	case DH6OPT_RECONF_ACCEPT:
2355b0fe478SBruce M Simpson 		return "reconfigure accept";
2365b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_D:
2371de50e9fSSam Leffler 		return "SIP servers domain";
2385b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_A:
2391de50e9fSSam Leffler 		return "SIP servers address";
2405b0fe478SBruce M Simpson 	case DH6OPT_DNS:
2415b0fe478SBruce M Simpson 		return "DNS";
2421de50e9fSSam Leffler 	case DH6OPT_DNSNAME:
2431de50e9fSSam Leffler 		return "DNS name";
2445b0fe478SBruce M Simpson 	case DH6OPT_PREFIX_DELEGATION:
2455b0fe478SBruce M Simpson 		return "prefix delegation";
2465b0fe478SBruce M Simpson 	case DH6OPT_PREFIX_INFORMATION:
2475b0fe478SBruce M Simpson 		return "prefix information";
2485b0fe478SBruce M Simpson 	case DH6OPT_IA_PD:
2495b0fe478SBruce M Simpson 		return "IA_PD";
2505b0fe478SBruce M Simpson 	case DH6OPT_IA_PD_PREFIX:
2515b0fe478SBruce M Simpson 		return "IA_PD prefix";
2525b0fe478SBruce M Simpson 	case DH6OPT_NTP_SERVERS:
2535b0fe478SBruce M Simpson 		return "NTP Server";
2541de50e9fSSam Leffler 	case DH6OPT_LIFETIME:
2551de50e9fSSam Leffler 		return "lifetime";
2565b0fe478SBruce M Simpson 	default:
2575b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "opt_%d", type);
2585b0fe478SBruce M Simpson 		return(genstr);
2595b0fe478SBruce M Simpson 	}
2605b0fe478SBruce M Simpson }
2615b0fe478SBruce M Simpson 
2625b0fe478SBruce M Simpson static const char *
2635b0fe478SBruce M Simpson dhcp6stcode(int code)
2645b0fe478SBruce M Simpson {
2655b0fe478SBruce M Simpson 	static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
2665b0fe478SBruce M Simpson 
2675b0fe478SBruce M Simpson 	if (code > 255)
2685b0fe478SBruce M Simpson 		return "INVALID code";
2695b0fe478SBruce M Simpson 
2705b0fe478SBruce M Simpson 	switch(code) {
2715b0fe478SBruce M Simpson 	case DH6OPT_STCODE_SUCCESS:
2725b0fe478SBruce M Simpson 		return "success";
2735b0fe478SBruce M Simpson 	case DH6OPT_STCODE_UNSPECFAIL:
2745b0fe478SBruce M Simpson 		return "unspec failure";
2755b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOADDRAVAIL:
2765b0fe478SBruce M Simpson 		return "no addresses";
2775b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOBINDING:
2785b0fe478SBruce M Simpson 		return "no binding";
2795b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOTONLINK:
2805b0fe478SBruce M Simpson 		return "not on-link";
2815b0fe478SBruce M Simpson 	case DH6OPT_STCODE_USEMULTICAST:
2825b0fe478SBruce M Simpson 		return "use multicast";
2835b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOPREFIXAVAIL:
2845b0fe478SBruce M Simpson 		return "no prefixes";
2855b0fe478SBruce M Simpson 	default:
2865b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "code%d", code);
2875b0fe478SBruce M Simpson 		return(genstr);
2885b0fe478SBruce M Simpson 	}
2895b0fe478SBruce M Simpson }
2905b0fe478SBruce M Simpson 
291b0453382SBill Fenner static void
2925b0fe478SBruce M Simpson dhcp6opt_print(const u_char *cp, const u_char *ep)
293b0453382SBill Fenner {
2949afd0c29SBill Fenner 	struct dhcp6opt *dh6o;
2959afd0c29SBill Fenner 	u_char *tp;
2965b0fe478SBruce M Simpson 	size_t i;
2975b0fe478SBruce M Simpson 	u_int16_t opttype;
2989afd0c29SBill Fenner 	size_t optlen;
2995b0fe478SBruce M Simpson 	u_int16_t val16;
3005b0fe478SBruce M Simpson 	u_int32_t val32;
3015b0fe478SBruce M Simpson 	struct in6_addr addr6;
3025b0fe478SBruce M Simpson 	struct dhcp6_ia ia;
3035b0fe478SBruce M Simpson 	struct dhcp6_ia_prefix ia_prefix;
3041de50e9fSSam Leffler 	struct dhcp6_auth authopt;
3051de50e9fSSam Leffler 	u_int authinfolen, authrealmlen;
306b0453382SBill Fenner 
307b0453382SBill Fenner 	if (cp == ep)
308b0453382SBill Fenner 		return;
309b0453382SBill Fenner 	while (cp < ep) {
3105b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o))
311b0453382SBill Fenner 			goto trunc;
3129afd0c29SBill Fenner 		dh6o = (struct dhcp6opt *)cp;
3135b0fe478SBruce M Simpson 		optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
3145b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o) + optlen)
315b0453382SBill Fenner 			goto trunc;
3165b0fe478SBruce M Simpson 		opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
3175b0fe478SBruce M Simpson 		printf(" (%s", dhcp6opt_name(opttype));
3185b0fe478SBruce M Simpson 		switch (opttype) {
3195b0fe478SBruce M Simpson 		case DH6OPT_CLIENTID:
3205b0fe478SBruce M Simpson 		case DH6OPT_SERVERID:
3219afd0c29SBill Fenner 			if (optlen < 2) {
3229afd0c29SBill Fenner 				/*(*/
3235b0fe478SBruce M Simpson 				printf(" ?)");
324b0453382SBill Fenner 				break;
325b0453382SBill Fenner 			}
3269afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
3275b0fe478SBruce M Simpson 			switch (EXTRACT_16BITS(tp)) {
3289afd0c29SBill Fenner 			case 1:
3299afd0c29SBill Fenner 				if (optlen >= 2 + 6) {
3305b0fe478SBruce M Simpson 					printf(" hwaddr/time type %u time %u ",
3315b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]),
3325b0fe478SBruce M Simpson 					    EXTRACT_32BITS(&tp[4]));
3339afd0c29SBill Fenner 					for (i = 8; i < optlen; i++)
3349afd0c29SBill Fenner 						printf("%02x", tp[i]);
3359afd0c29SBill Fenner 					/*(*/
336b0453382SBill Fenner 					printf(")");
3379afd0c29SBill Fenner 				} else {
3389afd0c29SBill Fenner 					/*(*/
3395b0fe478SBruce M Simpson 					printf(" ?)");
3409afd0c29SBill Fenner 				}
3419afd0c29SBill Fenner 				break;
3429afd0c29SBill Fenner 			case 2:
3439afd0c29SBill Fenner 				if (optlen >= 2 + 8) {
3449afd0c29SBill Fenner 					printf(" vid ");
3459afd0c29SBill Fenner 					for (i = 2; i < 2 + 8; i++)
3469afd0c29SBill Fenner 						printf("%02x", tp[i]);
3479afd0c29SBill Fenner 					/*(*/
3489afd0c29SBill Fenner 					printf(")");
3499afd0c29SBill Fenner 				} else {
3509afd0c29SBill Fenner 					/*(*/
3515b0fe478SBruce M Simpson 					printf(" ?)");
3529afd0c29SBill Fenner 				}
3539afd0c29SBill Fenner 				break;
3549afd0c29SBill Fenner 			case 3:
3559afd0c29SBill Fenner 				if (optlen >= 2 + 2) {
3569afd0c29SBill Fenner 					printf(" hwaddr type %u ",
3575b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]));
3589afd0c29SBill Fenner 					for (i = 4; i < optlen; i++)
3599afd0c29SBill Fenner 						printf("%02x", tp[i]);
3609afd0c29SBill Fenner 					/*(*/
3619afd0c29SBill Fenner 					printf(")");
3629afd0c29SBill Fenner 				} else {
3639afd0c29SBill Fenner 					/*(*/
3645b0fe478SBruce M Simpson 					printf(" ?)");
3659afd0c29SBill Fenner 				}
3669afd0c29SBill Fenner 				break;
3675b0fe478SBruce M Simpson 			default:
3685b0fe478SBruce M Simpson 				printf(" type %d)", EXTRACT_16BITS(tp));
3695b0fe478SBruce M Simpson 				break;
3705b0fe478SBruce M Simpson 			}
3715b0fe478SBruce M Simpson 			break;
3725b0fe478SBruce M Simpson 		case DH6OPT_ORO:
3735b0fe478SBruce M Simpson 			if (optlen % 2) {
3745b0fe478SBruce M Simpson 				printf(" ?)");
3755b0fe478SBruce M Simpson 				break;
3765b0fe478SBruce M Simpson 			}
3775b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
3785b0fe478SBruce M Simpson 			for (i = 0; i < optlen; i += 2) {
3795b0fe478SBruce M Simpson 				u_int16_t opt;
3805b0fe478SBruce M Simpson 
3815b0fe478SBruce M Simpson 				memcpy(&opt, &tp[i], sizeof(opt));
3825b0fe478SBruce M Simpson 				printf(" %s", dhcp6opt_name(ntohs(opt)));
3835b0fe478SBruce M Simpson 			}
3845b0fe478SBruce M Simpson 			printf(")");
3855b0fe478SBruce M Simpson 			break;
3865b0fe478SBruce M Simpson 		case DH6OPT_PREFERENCE:
3875b0fe478SBruce M Simpson 			if (optlen != 1) {
3885b0fe478SBruce M Simpson 				printf(" ?)");
3895b0fe478SBruce M Simpson 				break;
3905b0fe478SBruce M Simpson 			}
3915b0fe478SBruce M Simpson 			printf(" %d)", *((u_char *)(dh6o + 1) + 1));
3925b0fe478SBruce M Simpson 			break;
3935b0fe478SBruce M Simpson 		case DH6OPT_ELAPSED_TIME:
3945b0fe478SBruce M Simpson 			if (optlen != 2) {
3955b0fe478SBruce M Simpson 				printf(" ?)");
3965b0fe478SBruce M Simpson 				break;
3975b0fe478SBruce M Simpson 			}
3985b0fe478SBruce M Simpson 			memcpy(&val16, dh6o + 1, sizeof(val16));
3995b0fe478SBruce M Simpson 			val16 = ntohs(val16);
4005b0fe478SBruce M Simpson 			printf(" %d)", (int)val16);
4015b0fe478SBruce M Simpson 			break;
4025b0fe478SBruce M Simpson 		case DH6OPT_RELAY_MSG:
4035b0fe478SBruce M Simpson 			printf(" (");
4045b0fe478SBruce M Simpson 			dhcp6_print((const u_char *)(dh6o + 1), optlen);
4055b0fe478SBruce M Simpson 			printf(")");
4065b0fe478SBruce M Simpson 			break;
4071de50e9fSSam Leffler 		case DH6OPT_AUTH:
4081de50e9fSSam Leffler 			if (optlen < sizeof(authopt) - sizeof(*dh6o)) {
4091de50e9fSSam Leffler 				printf(" ?)");
4101de50e9fSSam Leffler 				break;
4111de50e9fSSam Leffler 			}
4121de50e9fSSam Leffler 			memcpy(&authopt, dh6o, sizeof(authopt));
4131de50e9fSSam Leffler 			switch (authopt.dh6opt_auth_proto) {
4141de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_DELAYED:
4151de50e9fSSam Leffler 				printf(" proto: delayed");
4161de50e9fSSam Leffler 				break;
4171de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_RECONFIG:
4181de50e9fSSam Leffler 				printf(" proto: reconfigure");
4191de50e9fSSam Leffler 				break;
4201de50e9fSSam Leffler 			default:
4211de50e9fSSam Leffler 				printf(" proto: %d",
4221de50e9fSSam Leffler 				    authopt.dh6opt_auth_proto);
4231de50e9fSSam Leffler 				break;
4241de50e9fSSam Leffler 			}
4251de50e9fSSam Leffler 			switch (authopt.dh6opt_auth_alg) {
4261de50e9fSSam Leffler 			case DH6OPT_AUTHALG_HMACMD5:
4271de50e9fSSam Leffler 				/* XXX: may depend on the protocol */
4281de50e9fSSam Leffler 				printf(", alg: HMAC-MD5");
4291de50e9fSSam Leffler 				break;
4301de50e9fSSam Leffler 			default:
4311de50e9fSSam Leffler 				printf(", alg: %d", authopt.dh6opt_auth_alg);
4321de50e9fSSam Leffler 				break;
4331de50e9fSSam Leffler 			}
4341de50e9fSSam Leffler 			switch (authopt.dh6opt_auth_rdm) {
4351de50e9fSSam Leffler 			case DH6OPT_AUTHRDM_MONOCOUNTER:
4361de50e9fSSam Leffler 				printf(", RDM: mono");
4371de50e9fSSam Leffler 				break;
4381de50e9fSSam Leffler 			default:
4391de50e9fSSam Leffler 				printf(", RDM: %d", authopt.dh6opt_auth_rdm);
4401de50e9fSSam Leffler 				break;
4411de50e9fSSam Leffler 			}
4421de50e9fSSam Leffler 			tp = (u_char *)&authopt.dh6opt_auth_rdinfo;
4431de50e9fSSam Leffler 			printf(", RD:");
4441de50e9fSSam Leffler 			for (i = 0; i < 4; i++, tp += sizeof(val16))
4451de50e9fSSam Leffler 				printf(" %04x", EXTRACT_16BITS(tp));
4461de50e9fSSam Leffler 
4471de50e9fSSam Leffler 			/* protocol dependent part */
4481de50e9fSSam Leffler 			tp = (u_char *)dh6o + sizeof(authopt);
4491de50e9fSSam Leffler 			authinfolen =
4501de50e9fSSam Leffler 			    optlen + sizeof(*dh6o) - sizeof(authopt);
4511de50e9fSSam Leffler 			switch (authopt.dh6opt_auth_proto) {
4521de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_DELAYED:
4531de50e9fSSam Leffler 				if (authinfolen == 0)
4541de50e9fSSam Leffler 					break;
4551de50e9fSSam Leffler 				if (authinfolen < 20) {
4561de50e9fSSam Leffler 					printf(" ??");
4571de50e9fSSam Leffler 					break;
4581de50e9fSSam Leffler 				}
4591de50e9fSSam Leffler 				authrealmlen = authinfolen - 20;
4601de50e9fSSam Leffler 				if (authrealmlen > 0) {
4611de50e9fSSam Leffler 					printf(", realm: ");
4621de50e9fSSam Leffler 				}
4631de50e9fSSam Leffler 				for (i = 0; i < authrealmlen; i++, tp++)
4641de50e9fSSam Leffler 					printf("%02x", *tp);
4651de50e9fSSam Leffler 				printf(", key ID: %08x", EXTRACT_32BITS(tp));
4661de50e9fSSam Leffler 				tp += 4;
4671de50e9fSSam Leffler 				printf(", HMAC-MD5:");
4681de50e9fSSam Leffler 				for (i = 0; i < 4; i++, tp+= 4)
4691de50e9fSSam Leffler 					printf(" %08x", EXTRACT_32BITS(tp));
4701de50e9fSSam Leffler 				break;
4711de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_RECONFIG:
4721de50e9fSSam Leffler 				if (authinfolen != 17) {
4731de50e9fSSam Leffler 					printf(" ??");
4741de50e9fSSam Leffler 					break;
4751de50e9fSSam Leffler 				}
4761de50e9fSSam Leffler 				switch (*tp++) {
4771de50e9fSSam Leffler 				case DH6OPT_AUTHRECONFIG_KEY:
4781de50e9fSSam Leffler 					printf(" reconfig-key");
4791de50e9fSSam Leffler 					break;
4801de50e9fSSam Leffler 				case DH6OPT_AUTHRECONFIG_HMACMD5:
4811de50e9fSSam Leffler 					printf(" type: HMAC-MD5");
4821de50e9fSSam Leffler 					break;
4831de50e9fSSam Leffler 				default:
4841de50e9fSSam Leffler 					printf(" type: ??");
4851de50e9fSSam Leffler 					break;
4861de50e9fSSam Leffler 				}
4871de50e9fSSam Leffler 				printf(" value:");
4881de50e9fSSam Leffler 				for (i = 0; i < 4; i++, tp+= 4)
4891de50e9fSSam Leffler 					printf(" %08x", EXTRACT_32BITS(tp));
4901de50e9fSSam Leffler 				break;
4911de50e9fSSam Leffler 			default:
4921de50e9fSSam Leffler 				printf(" ??");
4931de50e9fSSam Leffler 				break;
4941de50e9fSSam Leffler 			}
4951de50e9fSSam Leffler 
4961de50e9fSSam Leffler 			printf(")");
4971de50e9fSSam Leffler 			break;
4985b0fe478SBruce M Simpson 		case DH6OPT_RAPID_COMMIT: /* nothing todo */
4995b0fe478SBruce M Simpson 			printf(")");
5005b0fe478SBruce M Simpson 			break;
5015b0fe478SBruce M Simpson 		case DH6OPT_INTERFACE_ID:
5025b0fe478SBruce M Simpson 			/*
5035b0fe478SBruce M Simpson 			 * Since we cannot predict the encoding, print hex dump
5045b0fe478SBruce M Simpson 			 * at most 10 characters.
5055b0fe478SBruce M Simpson 			 */
5065b0fe478SBruce M Simpson 			for (i = 0; i < optlen && i < 10; i++)
5075b0fe478SBruce M Simpson 				printf("%02x", ((u_char *)(dh6o + 1))[i]);
5085b0fe478SBruce M Simpson 			break;
5095b0fe478SBruce M Simpson 		case DH6OPT_RECONF_MSG:
5105b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
5115b0fe478SBruce M Simpson 			switch (*tp) {
5125b0fe478SBruce M Simpson 			case DH6_RENEW:
5135b0fe478SBruce M Simpson 				printf(" for renew)");
5145b0fe478SBruce M Simpson 				break;
5155b0fe478SBruce M Simpson 			case DH6_INFORM_REQ:
5165b0fe478SBruce M Simpson 				printf(" for inf-req)");
5175b0fe478SBruce M Simpson 				break;
5185b0fe478SBruce M Simpson 			default:
5195b0fe478SBruce M Simpson 				printf(" for ?\?\?(%02x))", *tp);
5205b0fe478SBruce M Simpson 				break;
5215b0fe478SBruce M Simpson 			}
5225b0fe478SBruce M Simpson 			break;
5235b0fe478SBruce M Simpson 		case DH6OPT_RECONF_ACCEPT: /* nothing todo */
5245b0fe478SBruce M Simpson 			printf(")");
5255b0fe478SBruce M Simpson 			break;
5265b0fe478SBruce M Simpson 		case DH6OPT_SIP_SERVER_A:
5279afd0c29SBill Fenner 		case DH6OPT_DNS:
5285b0fe478SBruce M Simpson 		case DH6OPT_NTP_SERVERS:
5299afd0c29SBill Fenner 			if (optlen % 16) {
5305b0fe478SBruce M Simpson 				printf(" ?)");
5319afd0c29SBill Fenner 				break;
5329afd0c29SBill Fenner 			}
5339afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
5349afd0c29SBill Fenner 			for (i = 0; i < optlen; i += 16)
5359afd0c29SBill Fenner 				printf(" %s", ip6addr_string(&tp[i]));
5369afd0c29SBill Fenner 			printf(")");
5375b0fe478SBruce M Simpson 			break;
5385b0fe478SBruce M Simpson 		case DH6OPT_PREFIX_DELEGATION:
5395b0fe478SBruce M Simpson 			dhcp6opt_print((u_char *)(dh6o + 1),
5405b0fe478SBruce M Simpson 			    (u_char *)(dh6o + 1) + optlen);
5415b0fe478SBruce M Simpson 			printf(")");
5425b0fe478SBruce M Simpson 			break;
5435b0fe478SBruce M Simpson 		case DH6OPT_PREFIX_INFORMATION:
5445b0fe478SBruce M Simpson 			if (optlen % 21)
5455b0fe478SBruce M Simpson 				printf(" ?)");
5465b0fe478SBruce M Simpson 			memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
5475b0fe478SBruce M Simpson 			    sizeof(addr6));
5485b0fe478SBruce M Simpson 			printf(" %s/%d", ip6addr_string(&addr6),
5495b0fe478SBruce M Simpson 			    (int)*((u_char *)(dh6o + 1) + 4));
5505b0fe478SBruce M Simpson 			memcpy(&val32, dh6o + 1, sizeof(val32));
5515b0fe478SBruce M Simpson 			val32 = ntohl(val32);
5525b0fe478SBruce M Simpson 			if (val32 == DHCP6_DURATITION_INFINITE)
5535b0fe478SBruce M Simpson 				printf(" lease-duration: infinite)");
5545b0fe478SBruce M Simpson 			else
5555b0fe478SBruce M Simpson 				printf(" lease-duration: %u)", val32);
5565b0fe478SBruce M Simpson 			break;
5575b0fe478SBruce M Simpson 		case DH6OPT_STATUS_CODE:
5585b0fe478SBruce M Simpson 			if (optlen < 2) {
5595b0fe478SBruce M Simpson 				printf(" ?)");
5605b0fe478SBruce M Simpson 				break;
5615b0fe478SBruce M Simpson 			}
5625b0fe478SBruce M Simpson 			memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
5635b0fe478SBruce M Simpson 			val16 = ntohs(val16);
5645b0fe478SBruce M Simpson 			printf(" %s)", dhcp6stcode(val16));
5655b0fe478SBruce M Simpson 			break;
5665b0fe478SBruce M Simpson 		case DH6OPT_IA_NA:
5675b0fe478SBruce M Simpson 		case DH6OPT_IA_PD:
5685b0fe478SBruce M Simpson 			if (optlen < sizeof(ia) - 4) {
5695b0fe478SBruce M Simpson 				printf(" ?)");
5705b0fe478SBruce M Simpson 				break;
5715b0fe478SBruce M Simpson 			}
5725b0fe478SBruce M Simpson 			memcpy(&ia, (u_char *)dh6o, sizeof(ia));
5735b0fe478SBruce M Simpson 			ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid);
5745b0fe478SBruce M Simpson 			ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1);
5755b0fe478SBruce M Simpson 			ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2);
5765b0fe478SBruce M Simpson 			printf(" IAID:%lu T1:%lu T2:%lu",
5775b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_iaid,
5785b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_t1,
5795b0fe478SBruce M Simpson 			    (unsigned long)ia.dh6opt_ia_t2);
5805b0fe478SBruce M Simpson 			if (optlen > sizeof(ia) - 4) {
5815b0fe478SBruce M Simpson 				/* there are sub-options */
5825b0fe478SBruce M Simpson 				dhcp6opt_print((u_char *)dh6o + sizeof(ia),
5835b0fe478SBruce M Simpson 				    (u_char *)(dh6o + 1) + optlen);
5845b0fe478SBruce M Simpson 			}
5855b0fe478SBruce M Simpson 			printf(")");
5865b0fe478SBruce M Simpson 			break;
5875b0fe478SBruce M Simpson 		case DH6OPT_IA_PD_PREFIX:
5885b0fe478SBruce M Simpson 			if (optlen < sizeof(ia_prefix) - 4) {
5895b0fe478SBruce M Simpson 				printf(" ?)");
5905b0fe478SBruce M Simpson 				break;
5915b0fe478SBruce M Simpson 			}
5925b0fe478SBruce M Simpson 			memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix));
5935b0fe478SBruce M Simpson 			printf(" %s/%d",
5945b0fe478SBruce M Simpson 			    ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr),
5955b0fe478SBruce M Simpson 			    ia_prefix.dh6opt_ia_prefix_plen);
5965b0fe478SBruce M Simpson 			ia_prefix.dh6opt_ia_prefix_pltime =
5975b0fe478SBruce M Simpson 			    ntohl(ia_prefix.dh6opt_ia_prefix_pltime);
5985b0fe478SBruce M Simpson 			ia_prefix.dh6opt_ia_prefix_vltime =
5995b0fe478SBruce M Simpson 			    ntohl(ia_prefix.dh6opt_ia_prefix_vltime);
6005b0fe478SBruce M Simpson 			printf(" pltime:%lu vltime:%lu",
6015b0fe478SBruce M Simpson 			    (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime,
6025b0fe478SBruce M Simpson 			    (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime);
6035b0fe478SBruce M Simpson 			if (optlen > sizeof(ia_prefix) - 4) {
6045b0fe478SBruce M Simpson 				/* there are sub-options */
6055b0fe478SBruce M Simpson 				dhcp6opt_print((u_char *)dh6o +
6065b0fe478SBruce M Simpson 				    sizeof(ia_prefix),
6075b0fe478SBruce M Simpson 				    (u_char *)(dh6o + 1) + optlen);
6085b0fe478SBruce M Simpson 			}
6095b0fe478SBruce M Simpson 			printf(")");
6105b0fe478SBruce M Simpson 			break;
6111de50e9fSSam Leffler 		case DH6OPT_LIFETIME:
6121de50e9fSSam Leffler 			if (optlen != 4) {
6131de50e9fSSam Leffler 				printf(" ?)");
6141de50e9fSSam Leffler 				break;
6151de50e9fSSam Leffler 			}
6161de50e9fSSam Leffler 			memcpy(&val32, dh6o + 1, sizeof(val32));
6171de50e9fSSam Leffler 			val32 = ntohl(val32);
6181de50e9fSSam Leffler 			printf(" %d)", (int)val32);
6191de50e9fSSam Leffler 			break;
6209afd0c29SBill Fenner 		default:
6215b0fe478SBruce M Simpson 			printf(")");
6229afd0c29SBill Fenner 			break;
6239afd0c29SBill Fenner 		}
6249afd0c29SBill Fenner 
6259afd0c29SBill Fenner 		cp += sizeof(*dh6o) + optlen;
626b0453382SBill Fenner 	}
627b0453382SBill Fenner 	return;
628b0453382SBill Fenner 
629b0453382SBill Fenner trunc:
630b0453382SBill Fenner 	printf("[|dhcp6ext]");
631b0453382SBill Fenner }
632b0453382SBill Fenner 
633b0453382SBill Fenner /*
6349afd0c29SBill Fenner  * Print dhcp6 packets
635b0453382SBill Fenner  */
636b0453382SBill Fenner void
6375b0fe478SBruce M Simpson dhcp6_print(const u_char *cp, u_int length)
638b0453382SBill Fenner {
6399afd0c29SBill Fenner 	struct dhcp6 *dh6;
6405b0fe478SBruce M Simpson 	struct dhcp6_relay *dh6relay;
6415b0fe478SBruce M Simpson 	const u_char *ep;
642b0453382SBill Fenner 	u_char *extp;
6439afd0c29SBill Fenner 	const char *name;
644b0453382SBill Fenner 
645b0453382SBill Fenner 	printf("dhcp6");
646b0453382SBill Fenner 
647b0453382SBill Fenner 	ep = (u_char *)snapend;
6485b0fe478SBruce M Simpson 	if (cp + length < ep)
6495b0fe478SBruce M Simpson 		ep = cp + length;
650b0453382SBill Fenner 
6519afd0c29SBill Fenner 	dh6 = (struct dhcp6 *)cp;
6525b0fe478SBruce M Simpson 	dh6relay = (struct dhcp6_relay *)cp;
6535b0fe478SBruce M Simpson 	TCHECK(dh6->dh6_xid);
654b0453382SBill Fenner 	switch (dh6->dh6_msgtype) {
6555b0fe478SBruce M Simpson 	case DH6_SOLICIT:
6565b0fe478SBruce M Simpson 		name = "solicit";
6575b0fe478SBruce M Simpson 		break;
6585b0fe478SBruce M Simpson 	case DH6_ADVERTISE:
6595b0fe478SBruce M Simpson 		name = "advertise";
6605b0fe478SBruce M Simpson 		break;
6615b0fe478SBruce M Simpson 	case DH6_REQUEST:
6625b0fe478SBruce M Simpson 		name = "request";
6635b0fe478SBruce M Simpson 		break;
6645b0fe478SBruce M Simpson 	case DH6_CONFIRM:
6655b0fe478SBruce M Simpson 		name = "confirm";
6665b0fe478SBruce M Simpson 		break;
6675b0fe478SBruce M Simpson 	case DH6_RENEW:
6685b0fe478SBruce M Simpson 		name = "renew";
6695b0fe478SBruce M Simpson 		break;
6705b0fe478SBruce M Simpson 	case DH6_REBIND:
6715b0fe478SBruce M Simpson 		name = "rebind";
6725b0fe478SBruce M Simpson 		break;
673b0453382SBill Fenner 	case DH6_REPLY:
6749afd0c29SBill Fenner 		name = "reply";
6759afd0c29SBill Fenner 		break;
6765b0fe478SBruce M Simpson 	case DH6_RELEASE:
6775b0fe478SBruce M Simpson 		name = "release";
6785b0fe478SBruce M Simpson 		break;
6795b0fe478SBruce M Simpson 	case DH6_DECLINE:
6805b0fe478SBruce M Simpson 		name = "decline";
6815b0fe478SBruce M Simpson 		break;
6825b0fe478SBruce M Simpson 	case DH6_RECONFIGURE:
6835b0fe478SBruce M Simpson 		name = "reconfigure";
6845b0fe478SBruce M Simpson 		break;
6859afd0c29SBill Fenner 	case DH6_INFORM_REQ:
6869afd0c29SBill Fenner 		name= "inf-req";
6879afd0c29SBill Fenner 		break;
6885b0fe478SBruce M Simpson 	case DH6_RELAY_FORW:
6895b0fe478SBruce M Simpson 		name= "relay-fwd";
6905b0fe478SBruce M Simpson 		break;
6915b0fe478SBruce M Simpson 	case DH6_RELAY_REPLY:
6925b0fe478SBruce M Simpson 		name= "relay-reply";
6935b0fe478SBruce M Simpson 		break;
6949afd0c29SBill Fenner 	default:
6959afd0c29SBill Fenner 		name = NULL;
696b0453382SBill Fenner 		break;
697b0453382SBill Fenner 	}
6989afd0c29SBill Fenner 
6999afd0c29SBill Fenner 	if (!vflag) {
7009afd0c29SBill Fenner 		if (name)
7019afd0c29SBill Fenner 			printf(" %s", name);
7025b0fe478SBruce M Simpson 		else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
7035b0fe478SBruce M Simpson 		    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
7049afd0c29SBill Fenner 			printf(" msgtype-%u", dh6->dh6_msgtype);
7055b0fe478SBruce M Simpson 		}
7069afd0c29SBill Fenner 		return;
707b0453382SBill Fenner 	}
7089afd0c29SBill Fenner 
7099afd0c29SBill Fenner 	/* XXX relay agent messages have to be handled differently */
7109afd0c29SBill Fenner 
7119afd0c29SBill Fenner 	if (name)
7129afd0c29SBill Fenner 		printf(" %s (", name);	/*)*/
7139afd0c29SBill Fenner 	else
7149afd0c29SBill Fenner 		printf(" msgtype-%u (", dh6->dh6_msgtype);	/*)*/
7155b0fe478SBruce M Simpson 	if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
7165b0fe478SBruce M Simpson 	    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
7175b0fe478SBruce M Simpson 		printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
7189afd0c29SBill Fenner 		extp = (u_char *)(dh6 + 1);
7199afd0c29SBill Fenner 		dhcp6opt_print(extp, ep);
7205b0fe478SBruce M Simpson 	} else {		/* relay messages */
7215b0fe478SBruce M Simpson 		struct in6_addr addr6;
7225b0fe478SBruce M Simpson 
7235b0fe478SBruce M Simpson 		TCHECK(dh6relay->dh6relay_peeraddr);
7245b0fe478SBruce M Simpson 
7255b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
7265b0fe478SBruce M Simpson 		printf("linkaddr=%s", ip6addr_string(&addr6));
7275b0fe478SBruce M Simpson 
7285b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
7295b0fe478SBruce M Simpson 		printf(" peeraddr=%s", ip6addr_string(&addr6));
7305b0fe478SBruce M Simpson 
7315b0fe478SBruce M Simpson 		dhcp6opt_print((u_char *)(dh6relay + 1), ep);
7325b0fe478SBruce M Simpson 	}
733685295f4SBill Fenner 	/*(*/
734b0453382SBill Fenner 	printf(")");
735b0453382SBill Fenner 	return;
736b0453382SBill Fenner 
737b0453382SBill Fenner trunc:
7389afd0c29SBill Fenner 	printf("[|dhcp6]");
739b0453382SBill Fenner }
740