xref: /freebsd/contrib/tcpdump/print-dhcp6.c (revision 27df3f5dddcc52e19be97c5e876161208987d4f1)
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,
35b5bfcb5dSMax Laier  *  RFC3898,
36b5bfcb5dSMax Laier  *  RFC4075,
37b5bfcb5dSMax Laier  *  RFC4242,
38b5bfcb5dSMax Laier  *  RFC4280,
399afd0c29SBill Fenner  */
40b0453382SBill Fenner 
41b0453382SBill Fenner #ifndef lint
425b0fe478SBruce M Simpson static const char rcsid[] _U_ =
43*27df3f5dSRui Paulo     "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp $";
44b0453382SBill Fenner #endif
45b0453382SBill Fenner 
46b0453382SBill Fenner #ifdef HAVE_CONFIG_H
47b0453382SBill Fenner #include "config.h"
48b0453382SBill Fenner #endif
49b0453382SBill Fenner 
505b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
51b0453382SBill Fenner 
52b0453382SBill Fenner #include <stdio.h>
53b0453382SBill Fenner #include <string.h>
54b0453382SBill Fenner 
55b0453382SBill Fenner #include "interface.h"
56b0453382SBill Fenner #include "addrtoname.h"
575b0fe478SBruce M Simpson #include "extract.h"
585b0fe478SBruce M Simpson 
595b0fe478SBruce M Simpson /* lease duration */
605b0fe478SBruce M Simpson #define DHCP6_DURATITION_INFINITE 0xffffffff
61b0453382SBill Fenner 
629afd0c29SBill Fenner /* Error Values */
639afd0c29SBill Fenner #define DH6ERR_FAILURE		16
649afd0c29SBill Fenner #define DH6ERR_AUTHFAIL		17
659afd0c29SBill Fenner #define DH6ERR_POORLYFORMED	18
669afd0c29SBill Fenner #define DH6ERR_UNAVAIL		19
679afd0c29SBill Fenner #define DH6ERR_OPTUNAVAIL	20
68b0453382SBill Fenner 
699afd0c29SBill Fenner /* Message type */
705b0fe478SBruce M Simpson #define DH6_SOLICIT	1
715b0fe478SBruce M Simpson #define DH6_ADVERTISE	2
725b0fe478SBruce M Simpson #define DH6_REQUEST	3
735b0fe478SBruce M Simpson #define DH6_CONFIRM	4
745b0fe478SBruce M Simpson #define DH6_RENEW	5
755b0fe478SBruce M Simpson #define DH6_REBIND	6
769afd0c29SBill Fenner #define DH6_REPLY	7
775b0fe478SBruce M Simpson #define DH6_RELEASE	8
785b0fe478SBruce M Simpson #define DH6_DECLINE	9
795b0fe478SBruce M Simpson #define DH6_RECONFIGURE	10
809afd0c29SBill Fenner #define DH6_INFORM_REQ	11
815b0fe478SBruce M Simpson #define DH6_RELAY_FORW	12
825b0fe478SBruce M Simpson #define DH6_RELAY_REPLY	13
83a5779b6eSRui Paulo #define DH6_LEASEQUERY	14
84a5779b6eSRui Paulo #define DH6_LQ_REPLY	15
85b0453382SBill Fenner 
869afd0c29SBill Fenner /* DHCP6 base packet format */
879afd0c29SBill Fenner struct dhcp6 {
889afd0c29SBill Fenner 	union {
899afd0c29SBill Fenner 		u_int8_t m;
909afd0c29SBill Fenner 		u_int32_t x;
919afd0c29SBill Fenner 	} dh6_msgtypexid;
929afd0c29SBill Fenner 	/* options follow */
935b0fe478SBruce M Simpson };
949afd0c29SBill Fenner #define dh6_msgtype	dh6_msgtypexid.m
959afd0c29SBill Fenner #define dh6_xid		dh6_msgtypexid.x
969afd0c29SBill Fenner #define DH6_XIDMASK	0x00ffffff
97b0453382SBill Fenner 
985b0fe478SBruce M Simpson /* DHCPv6 relay messages */
995b0fe478SBruce M Simpson struct dhcp6_relay {
1005b0fe478SBruce M Simpson 	u_int8_t dh6relay_msgtype;
1015b0fe478SBruce M Simpson 	u_int8_t dh6relay_hcnt;
1025b0fe478SBruce M Simpson 	u_int8_t dh6relay_linkaddr[16];	/* XXX: badly aligned */
1035b0fe478SBruce M Simpson 	u_int8_t dh6relay_peeraddr[16];
1045b0fe478SBruce M Simpson 	/* options follow */
1055b0fe478SBruce M Simpson };
1065b0fe478SBruce M Simpson 
1075b0fe478SBruce M Simpson /* options */
1085b0fe478SBruce M Simpson #define DH6OPT_CLIENTID	1
1095b0fe478SBruce M Simpson #define DH6OPT_SERVERID	2
1105b0fe478SBruce M Simpson #define DH6OPT_IA_NA 3
111b5bfcb5dSMax Laier #define DH6OPT_IA_TA 4
112b5bfcb5dSMax Laier #define DH6OPT_IA_ADDR 5
1135b0fe478SBruce M Simpson #define DH6OPT_ORO 6
1145b0fe478SBruce M Simpson #define DH6OPT_PREFERENCE 7
1155b0fe478SBruce M Simpson #  define DH6OPT_PREF_MAX 255
1165b0fe478SBruce M Simpson #define DH6OPT_ELAPSED_TIME 8
1175b0fe478SBruce M Simpson #define DH6OPT_RELAY_MSG 9
1185b0fe478SBruce M Simpson /*#define DH6OPT_SERVER_MSG 10 deprecated */
1195b0fe478SBruce M Simpson #define DH6OPT_AUTH 11
1201de50e9fSSam Leffler #  define DH6OPT_AUTHPROTO_DELAYED 2
1211de50e9fSSam Leffler #  define DH6OPT_AUTHPROTO_RECONFIG 3
1221de50e9fSSam Leffler #  define DH6OPT_AUTHALG_HMACMD5 1
1231de50e9fSSam Leffler #  define DH6OPT_AUTHRDM_MONOCOUNTER 0
1241de50e9fSSam Leffler #  define DH6OPT_AUTHRECONFIG_KEY 1
1251de50e9fSSam Leffler #  define DH6OPT_AUTHRECONFIG_HMACMD5 2
1265b0fe478SBruce M Simpson #define DH6OPT_UNICAST 12
1275b0fe478SBruce M Simpson #define DH6OPT_STATUS_CODE 13
1285b0fe478SBruce M Simpson #  define DH6OPT_STCODE_SUCCESS 0
1295b0fe478SBruce M Simpson #  define DH6OPT_STCODE_UNSPECFAIL 1
1305b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOADDRAVAIL 2
1315b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOBINDING 3
1325b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOTONLINK 4
1335b0fe478SBruce M Simpson #  define DH6OPT_STCODE_USEMULTICAST 5
1345b0fe478SBruce M Simpson #  define DH6OPT_STCODE_NOPREFIXAVAIL 6
135a5779b6eSRui Paulo #  define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
136a5779b6eSRui Paulo #  define DH6OPT_STCODE_MALFORMEDQUERY 8
137a5779b6eSRui Paulo #  define DH6OPT_STCODE_NOTCONFIGURED 9
138a5779b6eSRui Paulo #  define DH6OPT_STCODE_NOTALLOWED 10
1395b0fe478SBruce M Simpson #define DH6OPT_RAPID_COMMIT 14
1405b0fe478SBruce M Simpson #define DH6OPT_USER_CLASS 15
1415b0fe478SBruce M Simpson #define DH6OPT_VENDOR_CLASS 16
1425b0fe478SBruce M Simpson #define DH6OPT_VENDOR_OPTS 17
1435b0fe478SBruce M Simpson #define DH6OPT_INTERFACE_ID 18
1445b0fe478SBruce M Simpson #define DH6OPT_RECONF_MSG 19
1455b0fe478SBruce M Simpson #define DH6OPT_RECONF_ACCEPT 20
1465b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_D 21
1475b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_A 22
1485b0fe478SBruce M Simpson #define DH6OPT_DNS 23
1495b0fe478SBruce M Simpson #define DH6OPT_DNSNAME 24
1501de50e9fSSam Leffler #define DH6OPT_IA_PD 25
1511de50e9fSSam Leffler #define DH6OPT_IA_PD_PREFIX 26
152b5bfcb5dSMax Laier #define DH6OPT_NIS_SERVERS 27
153b5bfcb5dSMax Laier #define DH6OPT_NISP_SERVERS 28
154b5bfcb5dSMax Laier #define DH6OPT_NIS_NAME 29
155b5bfcb5dSMax Laier #define DH6OPT_NISP_NAME 30
156b5bfcb5dSMax Laier #define DH6OPT_NTP_SERVERS 31
157b5bfcb5dSMax Laier #define DH6OPT_LIFETIME 32
158b5bfcb5dSMax Laier #define DH6OPT_BCMCS_SERVER_D 33
159b5bfcb5dSMax Laier #define DH6OPT_BCMCS_SERVER_A 34
160b5bfcb5dSMax Laier #define DH6OPT_GEOCONF_CIVIC 36
161b5bfcb5dSMax Laier #define DH6OPT_REMOTE_ID 37
162b5bfcb5dSMax Laier #define DH6OPT_SUBSCRIBER_ID 38
163b5bfcb5dSMax Laier #define DH6OPT_CLIENT_FQDN 39
164a5779b6eSRui Paulo #define DH6OPT_PANA_AGENT 40
165a5779b6eSRui Paulo #define DH6OPT_NEW_POSIX_TIMEZONE 41
166a5779b6eSRui Paulo #define DH6OPT_NEW_TZDB_TIMEZONE 42
167a5779b6eSRui Paulo #define DH6OPT_ERO 43
168a5779b6eSRui Paulo #define DH6OPT_LQ_QUERY 44
169a5779b6eSRui Paulo #define DH6OPT_CLIENT_DATA 45
170a5779b6eSRui Paulo #define DH6OPT_CLT_TIME 46
171a5779b6eSRui Paulo #define DH6OPT_LQ_RELAY_DATA 47
172a5779b6eSRui Paulo #define DH6OPT_LQ_CLIENT_LINK 48
1735b0fe478SBruce M Simpson 
1749afd0c29SBill Fenner struct dhcp6opt {
1759afd0c29SBill Fenner 	u_int16_t dh6opt_type;
1769afd0c29SBill Fenner 	u_int16_t dh6opt_len;
1779afd0c29SBill Fenner 	/* type-dependent data follows */
1785b0fe478SBruce M Simpson };
1795b0fe478SBruce M Simpson 
1805b0fe478SBruce M Simpson static const char *
1815b0fe478SBruce M Simpson dhcp6opt_name(int type)
1825b0fe478SBruce M Simpson {
1835b0fe478SBruce M Simpson 	static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
1845b0fe478SBruce M Simpson 
1855b0fe478SBruce M Simpson 	if (type > 65535)
186*27df3f5dSRui Paulo 		return "INVALID-option";
1875b0fe478SBruce M Simpson 
1885b0fe478SBruce M Simpson 	switch(type) {
1895b0fe478SBruce M Simpson 	case DH6OPT_CLIENTID:
190*27df3f5dSRui Paulo 		return "client-ID";
1915b0fe478SBruce M Simpson 	case DH6OPT_SERVERID:
192*27df3f5dSRui Paulo 		return "server-ID";
1935b0fe478SBruce M Simpson 	case DH6OPT_IA_NA:
1945b0fe478SBruce M Simpson 		return "IA_NA";
195b5bfcb5dSMax Laier 	case DH6OPT_IA_TA:
196b5bfcb5dSMax Laier 		return "IA_TA";
197b5bfcb5dSMax Laier 	case DH6OPT_IA_ADDR:
198b5bfcb5dSMax Laier 		return "IA_ADDR";
1995b0fe478SBruce M Simpson 	case DH6OPT_ORO:
200*27df3f5dSRui Paulo 		return "option-request";
2015b0fe478SBruce M Simpson 	case DH6OPT_PREFERENCE:
2025b0fe478SBruce M Simpson 		return "preference";
2035b0fe478SBruce M Simpson 	case DH6OPT_ELAPSED_TIME:
204*27df3f5dSRui Paulo 		return "elapsed-time";
2055b0fe478SBruce M Simpson 	case DH6OPT_RELAY_MSG:
206*27df3f5dSRui Paulo 		return "relay-message";
2071de50e9fSSam Leffler 	case DH6OPT_AUTH:
2081de50e9fSSam Leffler 		return "authentication";
2091de50e9fSSam Leffler 	case DH6OPT_UNICAST:
210*27df3f5dSRui Paulo 		return "server-unicast";
2115b0fe478SBruce M Simpson 	case DH6OPT_STATUS_CODE:
212*27df3f5dSRui Paulo 		return "status-code";
2135b0fe478SBruce M Simpson 	case DH6OPT_RAPID_COMMIT:
214*27df3f5dSRui Paulo 		return "rapid-commit";
2151de50e9fSSam Leffler 	case DH6OPT_USER_CLASS:
216*27df3f5dSRui Paulo 		return "user-class";
2171de50e9fSSam Leffler 	case DH6OPT_VENDOR_CLASS:
218*27df3f5dSRui Paulo 		return "vendor-class";
2191de50e9fSSam Leffler 	case DH6OPT_VENDOR_OPTS:
220*27df3f5dSRui Paulo 		return "vendor-specific-info";
2215b0fe478SBruce M Simpson 	case DH6OPT_INTERFACE_ID:
222*27df3f5dSRui Paulo 		return "interface-ID";
2235b0fe478SBruce M Simpson 	case DH6OPT_RECONF_MSG:
224*27df3f5dSRui Paulo 		return "reconfigure-message";
2255b0fe478SBruce M Simpson 	case DH6OPT_RECONF_ACCEPT:
226*27df3f5dSRui Paulo 		return "reconfigure-accept";
2275b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_D:
228*27df3f5dSRui Paulo 		return "SIP-servers-domain";
2295b0fe478SBruce M Simpson 	case DH6OPT_SIP_SERVER_A:
230*27df3f5dSRui Paulo 		return "SIP-servers-address";
2315b0fe478SBruce M Simpson 	case DH6OPT_DNS:
2325b0fe478SBruce M Simpson 		return "DNS";
2331de50e9fSSam Leffler 	case DH6OPT_DNSNAME:
234*27df3f5dSRui Paulo 		return "DNS-name";
2355b0fe478SBruce M Simpson 	case DH6OPT_IA_PD:
2365b0fe478SBruce M Simpson 		return "IA_PD";
2375b0fe478SBruce M Simpson 	case DH6OPT_IA_PD_PREFIX:
238*27df3f5dSRui Paulo 		return "IA_PD-prefix";
2395b0fe478SBruce M Simpson 	case DH6OPT_NTP_SERVERS:
240*27df3f5dSRui Paulo 		return "NTP-Server";
2411de50e9fSSam Leffler 	case DH6OPT_LIFETIME:
2421de50e9fSSam Leffler 		return "lifetime";
243b5bfcb5dSMax Laier 	case DH6OPT_NIS_SERVERS:
244*27df3f5dSRui Paulo 		return "NIS-server";
245b5bfcb5dSMax Laier 	case DH6OPT_NISP_SERVERS:
246*27df3f5dSRui Paulo 		return "NIS+-server";
247b5bfcb5dSMax Laier 	case DH6OPT_NIS_NAME:
248*27df3f5dSRui Paulo 		return "NIS-domain-name";
249b5bfcb5dSMax Laier 	case DH6OPT_NISP_NAME:
250*27df3f5dSRui Paulo 		return "NIS+-domain-name";
251b5bfcb5dSMax Laier 	case DH6OPT_BCMCS_SERVER_D:
252*27df3f5dSRui Paulo 		return "BCMCS-domain-name";
253b5bfcb5dSMax Laier 	case DH6OPT_BCMCS_SERVER_A:
254*27df3f5dSRui Paulo 		return "BCMCS-server";
255b5bfcb5dSMax Laier 	case DH6OPT_GEOCONF_CIVIC:
256*27df3f5dSRui Paulo 		return "Geoconf-Civic";
257b5bfcb5dSMax Laier 	case DH6OPT_REMOTE_ID:
258*27df3f5dSRui Paulo 		return "Remote-ID";
259b5bfcb5dSMax Laier 	case DH6OPT_SUBSCRIBER_ID:
260*27df3f5dSRui Paulo 		return "Subscriber-ID";
261b5bfcb5dSMax Laier 	case DH6OPT_CLIENT_FQDN:
262*27df3f5dSRui Paulo 		return "Client-FQDN";
263a5779b6eSRui Paulo 	case DH6OPT_PANA_AGENT:
264*27df3f5dSRui Paulo 		return "PANA-agent";
265a5779b6eSRui Paulo 	case DH6OPT_NEW_POSIX_TIMEZONE:
266*27df3f5dSRui Paulo 		return "POSIX-timezone";
267a5779b6eSRui Paulo 	case DH6OPT_NEW_TZDB_TIMEZONE:
268*27df3f5dSRui Paulo 		return "POSIX-tz-database";
269a5779b6eSRui Paulo 	case DH6OPT_ERO:
270*27df3f5dSRui Paulo 		return "Echo-request-option";
271a5779b6eSRui Paulo 	case DH6OPT_LQ_QUERY:
272*27df3f5dSRui Paulo 		return "Lease-query";
273a5779b6eSRui Paulo 	case DH6OPT_CLIENT_DATA:
274*27df3f5dSRui Paulo 		return "LQ-client-data";
275a5779b6eSRui Paulo 	case DH6OPT_CLT_TIME:
276*27df3f5dSRui Paulo 		return "Clt-time";
277a5779b6eSRui Paulo 	case DH6OPT_LQ_RELAY_DATA:
278*27df3f5dSRui Paulo 		return "LQ-relay-data";
279a5779b6eSRui Paulo 	case DH6OPT_LQ_CLIENT_LINK:
280*27df3f5dSRui Paulo 		return "LQ-client-link";
2815b0fe478SBruce M Simpson 	default:
2825b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "opt_%d", type);
2835b0fe478SBruce M Simpson 		return(genstr);
2845b0fe478SBruce M Simpson 	}
2855b0fe478SBruce M Simpson }
2865b0fe478SBruce M Simpson 
2875b0fe478SBruce M Simpson static const char *
2885b0fe478SBruce M Simpson dhcp6stcode(int code)
2895b0fe478SBruce M Simpson {
2905b0fe478SBruce M Simpson 	static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
2915b0fe478SBruce M Simpson 
2925b0fe478SBruce M Simpson 	if (code > 255)
2935b0fe478SBruce M Simpson 		return "INVALID code";
2945b0fe478SBruce M Simpson 
2955b0fe478SBruce M Simpson 	switch(code) {
2965b0fe478SBruce M Simpson 	case DH6OPT_STCODE_SUCCESS:
2975b0fe478SBruce M Simpson 		return "success";
2985b0fe478SBruce M Simpson 	case DH6OPT_STCODE_UNSPECFAIL:
2995b0fe478SBruce M Simpson 		return "unspec failure";
3005b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOADDRAVAIL:
3015b0fe478SBruce M Simpson 		return "no addresses";
3025b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOBINDING:
3035b0fe478SBruce M Simpson 		return "no binding";
3045b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOTONLINK:
3055b0fe478SBruce M Simpson 		return "not on-link";
3065b0fe478SBruce M Simpson 	case DH6OPT_STCODE_USEMULTICAST:
3075b0fe478SBruce M Simpson 		return "use multicast";
3085b0fe478SBruce M Simpson 	case DH6OPT_STCODE_NOPREFIXAVAIL:
3095b0fe478SBruce M Simpson 		return "no prefixes";
310a5779b6eSRui Paulo 	case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
311a5779b6eSRui Paulo 		return "unknown query type";
312a5779b6eSRui Paulo 	case DH6OPT_STCODE_MALFORMEDQUERY:
313a5779b6eSRui Paulo 		return "malformed query";
314a5779b6eSRui Paulo 	case DH6OPT_STCODE_NOTCONFIGURED:
315a5779b6eSRui Paulo 		return "not configured";
316a5779b6eSRui Paulo 	case DH6OPT_STCODE_NOTALLOWED:
317a5779b6eSRui Paulo 		return "not allowed";
3185b0fe478SBruce M Simpson 	default:
3195b0fe478SBruce M Simpson 		snprintf(genstr, sizeof(genstr), "code%d", code);
3205b0fe478SBruce M Simpson 		return(genstr);
3215b0fe478SBruce M Simpson 	}
3225b0fe478SBruce M Simpson }
3235b0fe478SBruce M Simpson 
324b0453382SBill Fenner static void
3255b0fe478SBruce M Simpson dhcp6opt_print(const u_char *cp, const u_char *ep)
326b0453382SBill Fenner {
3279afd0c29SBill Fenner 	struct dhcp6opt *dh6o;
3289afd0c29SBill Fenner 	u_char *tp;
3295b0fe478SBruce M Simpson 	size_t i;
3305b0fe478SBruce M Simpson 	u_int16_t opttype;
3319afd0c29SBill Fenner 	size_t optlen;
332*27df3f5dSRui Paulo 	u_int8_t auth_proto;
3331de50e9fSSam Leffler 	u_int authinfolen, authrealmlen;
334b0453382SBill Fenner 
335b0453382SBill Fenner 	if (cp == ep)
336b0453382SBill Fenner 		return;
337b0453382SBill Fenner 	while (cp < ep) {
3385b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o))
339b0453382SBill Fenner 			goto trunc;
3409afd0c29SBill Fenner 		dh6o = (struct dhcp6opt *)cp;
3415b0fe478SBruce M Simpson 		optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
3425b0fe478SBruce M Simpson 		if (ep < cp + sizeof(*dh6o) + optlen)
343b0453382SBill Fenner 			goto trunc;
3445b0fe478SBruce M Simpson 		opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
3455b0fe478SBruce M Simpson 		printf(" (%s", dhcp6opt_name(opttype));
3465b0fe478SBruce M Simpson 		switch (opttype) {
3475b0fe478SBruce M Simpson 		case DH6OPT_CLIENTID:
3485b0fe478SBruce M Simpson 		case DH6OPT_SERVERID:
3499afd0c29SBill Fenner 			if (optlen < 2) {
3509afd0c29SBill Fenner 				/*(*/
3515b0fe478SBruce M Simpson 				printf(" ?)");
352b0453382SBill Fenner 				break;
353b0453382SBill Fenner 			}
3549afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
3555b0fe478SBruce M Simpson 			switch (EXTRACT_16BITS(tp)) {
3569afd0c29SBill Fenner 			case 1:
3579afd0c29SBill Fenner 				if (optlen >= 2 + 6) {
3585b0fe478SBruce M Simpson 					printf(" hwaddr/time type %u time %u ",
3595b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]),
3605b0fe478SBruce M Simpson 					    EXTRACT_32BITS(&tp[4]));
3619afd0c29SBill Fenner 					for (i = 8; i < optlen; i++)
3629afd0c29SBill Fenner 						printf("%02x", tp[i]);
3639afd0c29SBill Fenner 					/*(*/
364b0453382SBill Fenner 					printf(")");
3659afd0c29SBill Fenner 				} else {
3669afd0c29SBill Fenner 					/*(*/
3675b0fe478SBruce M Simpson 					printf(" ?)");
3689afd0c29SBill Fenner 				}
3699afd0c29SBill Fenner 				break;
3709afd0c29SBill Fenner 			case 2:
3719afd0c29SBill Fenner 				if (optlen >= 2 + 8) {
3729afd0c29SBill Fenner 					printf(" vid ");
3739afd0c29SBill Fenner 					for (i = 2; i < 2 + 8; i++)
3749afd0c29SBill Fenner 						printf("%02x", tp[i]);
3759afd0c29SBill Fenner 					/*(*/
3769afd0c29SBill Fenner 					printf(")");
3779afd0c29SBill Fenner 				} else {
3789afd0c29SBill Fenner 					/*(*/
3795b0fe478SBruce M Simpson 					printf(" ?)");
3809afd0c29SBill Fenner 				}
3819afd0c29SBill Fenner 				break;
3829afd0c29SBill Fenner 			case 3:
3839afd0c29SBill Fenner 				if (optlen >= 2 + 2) {
3849afd0c29SBill Fenner 					printf(" hwaddr type %u ",
3855b0fe478SBruce M Simpson 					    EXTRACT_16BITS(&tp[2]));
3869afd0c29SBill Fenner 					for (i = 4; i < optlen; i++)
3879afd0c29SBill Fenner 						printf("%02x", tp[i]);
3889afd0c29SBill Fenner 					/*(*/
3899afd0c29SBill Fenner 					printf(")");
3909afd0c29SBill Fenner 				} else {
3919afd0c29SBill Fenner 					/*(*/
3925b0fe478SBruce M Simpson 					printf(" ?)");
3939afd0c29SBill Fenner 				}
3949afd0c29SBill Fenner 				break;
3955b0fe478SBruce M Simpson 			default:
3965b0fe478SBruce M Simpson 				printf(" type %d)", EXTRACT_16BITS(tp));
3975b0fe478SBruce M Simpson 				break;
3985b0fe478SBruce M Simpson 			}
3995b0fe478SBruce M Simpson 			break;
400b5bfcb5dSMax Laier 		case DH6OPT_IA_ADDR:
401*27df3f5dSRui Paulo 			if (optlen < 24) {
402*27df3f5dSRui Paulo 				/*(*/
403b5bfcb5dSMax Laier 				printf(" ?)");
404b5bfcb5dSMax Laier 				break;
405b5bfcb5dSMax Laier 			}
406*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
407*27df3f5dSRui Paulo 			printf(" %s", ip6addr_string(&tp[0]));
408*27df3f5dSRui Paulo 			printf(" pltime:%u vltime:%u",
409*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[16]),
410*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[20]));
411*27df3f5dSRui Paulo 			if (optlen > 24) {
412b5bfcb5dSMax Laier 				/* there are sub-options */
413*27df3f5dSRui Paulo 				dhcp6opt_print(tp + 24, tp + 24 + optlen);
414b5bfcb5dSMax Laier 			}
415b5bfcb5dSMax Laier 			printf(")");
416b5bfcb5dSMax Laier 			break;
4175b0fe478SBruce M Simpson 		case DH6OPT_ORO:
418a5779b6eSRui Paulo 		case DH6OPT_ERO:
4195b0fe478SBruce M Simpson 			if (optlen % 2) {
4205b0fe478SBruce M Simpson 				printf(" ?)");
4215b0fe478SBruce M Simpson 				break;
4225b0fe478SBruce M Simpson 			}
4235b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
4245b0fe478SBruce M Simpson 			for (i = 0; i < optlen; i += 2) {
425*27df3f5dSRui Paulo 				printf(" %s",
426*27df3f5dSRui Paulo 				    dhcp6opt_name(EXTRACT_16BITS(&tp[i])));
4275b0fe478SBruce M Simpson 			}
4285b0fe478SBruce M Simpson 			printf(")");
4295b0fe478SBruce M Simpson 			break;
4305b0fe478SBruce M Simpson 		case DH6OPT_PREFERENCE:
4315b0fe478SBruce M Simpson 			if (optlen != 1) {
4325b0fe478SBruce M Simpson 				printf(" ?)");
4335b0fe478SBruce M Simpson 				break;
4345b0fe478SBruce M Simpson 			}
435*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
436*27df3f5dSRui Paulo 			printf(" %d)", *tp);
4375b0fe478SBruce M Simpson 			break;
4385b0fe478SBruce M Simpson 		case DH6OPT_ELAPSED_TIME:
4395b0fe478SBruce M Simpson 			if (optlen != 2) {
4405b0fe478SBruce M Simpson 				printf(" ?)");
4415b0fe478SBruce M Simpson 				break;
4425b0fe478SBruce M Simpson 			}
443*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
444*27df3f5dSRui Paulo 			printf(" %d)", EXTRACT_16BITS(tp));
4455b0fe478SBruce M Simpson 			break;
4465b0fe478SBruce M Simpson 		case DH6OPT_RELAY_MSG:
4475b0fe478SBruce M Simpson 			printf(" (");
448*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
449*27df3f5dSRui Paulo 			dhcp6_print(tp, optlen);
4505b0fe478SBruce M Simpson 			printf(")");
4515b0fe478SBruce M Simpson 			break;
4521de50e9fSSam Leffler 		case DH6OPT_AUTH:
453*27df3f5dSRui Paulo 			if (optlen < 11) {
4541de50e9fSSam Leffler 				printf(" ?)");
4551de50e9fSSam Leffler 				break;
4561de50e9fSSam Leffler 			}
457*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
458*27df3f5dSRui Paulo 			auth_proto = *tp;
459*27df3f5dSRui Paulo 			switch (auth_proto) {
4601de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_DELAYED:
4611de50e9fSSam Leffler 				printf(" proto: delayed");
4621de50e9fSSam Leffler 				break;
4631de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_RECONFIG:
4641de50e9fSSam Leffler 				printf(" proto: reconfigure");
4651de50e9fSSam Leffler 				break;
4661de50e9fSSam Leffler 			default:
467*27df3f5dSRui Paulo 				printf(" proto: %d", auth_proto);
4681de50e9fSSam Leffler 				break;
4691de50e9fSSam Leffler 			}
470*27df3f5dSRui Paulo 			tp++;
471*27df3f5dSRui Paulo 			switch (*tp) {
4721de50e9fSSam Leffler 			case DH6OPT_AUTHALG_HMACMD5:
4731de50e9fSSam Leffler 				/* XXX: may depend on the protocol */
4741de50e9fSSam Leffler 				printf(", alg: HMAC-MD5");
4751de50e9fSSam Leffler 				break;
4761de50e9fSSam Leffler 			default:
477*27df3f5dSRui Paulo 				printf(", alg: %d", *tp);
4781de50e9fSSam Leffler 				break;
4791de50e9fSSam Leffler 			}
480*27df3f5dSRui Paulo 			tp++;
481*27df3f5dSRui Paulo 			switch (*tp) {
4821de50e9fSSam Leffler 			case DH6OPT_AUTHRDM_MONOCOUNTER:
4831de50e9fSSam Leffler 				printf(", RDM: mono");
4841de50e9fSSam Leffler 				break;
4851de50e9fSSam Leffler 			default:
486*27df3f5dSRui Paulo 				printf(", RDM: %d", *tp);
4871de50e9fSSam Leffler 				break;
4881de50e9fSSam Leffler 			}
489*27df3f5dSRui Paulo 			tp++;
4901de50e9fSSam Leffler 			printf(", RD:");
491*27df3f5dSRui Paulo 			for (i = 0; i < 4; i++, tp += 2)
4921de50e9fSSam Leffler 				printf(" %04x", EXTRACT_16BITS(tp));
4931de50e9fSSam Leffler 
4941de50e9fSSam Leffler 			/* protocol dependent part */
495*27df3f5dSRui Paulo 			authinfolen = optlen - 11;
496*27df3f5dSRui Paulo 			switch (auth_proto) {
4971de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_DELAYED:
4981de50e9fSSam Leffler 				if (authinfolen == 0)
4991de50e9fSSam Leffler 					break;
5001de50e9fSSam Leffler 				if (authinfolen < 20) {
5011de50e9fSSam Leffler 					printf(" ??");
5021de50e9fSSam Leffler 					break;
5031de50e9fSSam Leffler 				}
5041de50e9fSSam Leffler 				authrealmlen = authinfolen - 20;
5051de50e9fSSam Leffler 				if (authrealmlen > 0) {
5061de50e9fSSam Leffler 					printf(", realm: ");
5071de50e9fSSam Leffler 				}
5081de50e9fSSam Leffler 				for (i = 0; i < authrealmlen; i++, tp++)
5091de50e9fSSam Leffler 					printf("%02x", *tp);
5101de50e9fSSam Leffler 				printf(", key ID: %08x", EXTRACT_32BITS(tp));
5111de50e9fSSam Leffler 				tp += 4;
5121de50e9fSSam Leffler 				printf(", HMAC-MD5:");
5131de50e9fSSam Leffler 				for (i = 0; i < 4; i++, tp+= 4)
5141de50e9fSSam Leffler 					printf(" %08x", EXTRACT_32BITS(tp));
5151de50e9fSSam Leffler 				break;
5161de50e9fSSam Leffler 			case DH6OPT_AUTHPROTO_RECONFIG:
5171de50e9fSSam Leffler 				if (authinfolen != 17) {
5181de50e9fSSam Leffler 					printf(" ??");
5191de50e9fSSam Leffler 					break;
5201de50e9fSSam Leffler 				}
5211de50e9fSSam Leffler 				switch (*tp++) {
5221de50e9fSSam Leffler 				case DH6OPT_AUTHRECONFIG_KEY:
5231de50e9fSSam Leffler 					printf(" reconfig-key");
5241de50e9fSSam Leffler 					break;
5251de50e9fSSam Leffler 				case DH6OPT_AUTHRECONFIG_HMACMD5:
5261de50e9fSSam Leffler 					printf(" type: HMAC-MD5");
5271de50e9fSSam Leffler 					break;
5281de50e9fSSam Leffler 				default:
5291de50e9fSSam Leffler 					printf(" type: ??");
5301de50e9fSSam Leffler 					break;
5311de50e9fSSam Leffler 				}
5321de50e9fSSam Leffler 				printf(" value:");
5331de50e9fSSam Leffler 				for (i = 0; i < 4; i++, tp+= 4)
5341de50e9fSSam Leffler 					printf(" %08x", EXTRACT_32BITS(tp));
5351de50e9fSSam Leffler 				break;
5361de50e9fSSam Leffler 			default:
5371de50e9fSSam Leffler 				printf(" ??");
5381de50e9fSSam Leffler 				break;
5391de50e9fSSam Leffler 			}
5401de50e9fSSam Leffler 
5411de50e9fSSam Leffler 			printf(")");
5421de50e9fSSam Leffler 			break;
5435b0fe478SBruce M Simpson 		case DH6OPT_RAPID_COMMIT: /* nothing todo */
5445b0fe478SBruce M Simpson 			printf(")");
5455b0fe478SBruce M Simpson 			break;
5465b0fe478SBruce M Simpson 		case DH6OPT_INTERFACE_ID:
547a5779b6eSRui Paulo 		case DH6OPT_SUBSCRIBER_ID:
5485b0fe478SBruce M Simpson 			/*
5495b0fe478SBruce M Simpson 			 * Since we cannot predict the encoding, print hex dump
5505b0fe478SBruce M Simpson 			 * at most 10 characters.
5515b0fe478SBruce M Simpson 			 */
552*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
553a5779b6eSRui Paulo 			printf(" ");
5545b0fe478SBruce M Simpson 			for (i = 0; i < optlen && i < 10; i++)
555*27df3f5dSRui Paulo 				printf("%02x", tp[i]);
556a5779b6eSRui Paulo 			printf("...)");
5575b0fe478SBruce M Simpson 			break;
5585b0fe478SBruce M Simpson 		case DH6OPT_RECONF_MSG:
5595b0fe478SBruce M Simpson 			tp = (u_char *)(dh6o + 1);
5605b0fe478SBruce M Simpson 			switch (*tp) {
5615b0fe478SBruce M Simpson 			case DH6_RENEW:
5625b0fe478SBruce M Simpson 				printf(" for renew)");
5635b0fe478SBruce M Simpson 				break;
5645b0fe478SBruce M Simpson 			case DH6_INFORM_REQ:
5655b0fe478SBruce M Simpson 				printf(" for inf-req)");
5665b0fe478SBruce M Simpson 				break;
5675b0fe478SBruce M Simpson 			default:
5685b0fe478SBruce M Simpson 				printf(" for ?\?\?(%02x))", *tp);
5695b0fe478SBruce M Simpson 				break;
5705b0fe478SBruce M Simpson 			}
5715b0fe478SBruce M Simpson 			break;
5725b0fe478SBruce M Simpson 		case DH6OPT_RECONF_ACCEPT: /* nothing todo */
5735b0fe478SBruce M Simpson 			printf(")");
5745b0fe478SBruce M Simpson 			break;
5755b0fe478SBruce M Simpson 		case DH6OPT_SIP_SERVER_A:
5769afd0c29SBill Fenner 		case DH6OPT_DNS:
5775b0fe478SBruce M Simpson 		case DH6OPT_NTP_SERVERS:
578b5bfcb5dSMax Laier 		case DH6OPT_NIS_SERVERS:
579b5bfcb5dSMax Laier 		case DH6OPT_NISP_SERVERS:
580b5bfcb5dSMax Laier 		case DH6OPT_BCMCS_SERVER_A:
581a5779b6eSRui Paulo 		case DH6OPT_PANA_AGENT:
582a5779b6eSRui Paulo 		case DH6OPT_LQ_CLIENT_LINK:
5839afd0c29SBill Fenner 			if (optlen % 16) {
5845b0fe478SBruce M Simpson 				printf(" ?)");
5859afd0c29SBill Fenner 				break;
5869afd0c29SBill Fenner 			}
5879afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
5889afd0c29SBill Fenner 			for (i = 0; i < optlen; i += 16)
5899afd0c29SBill Fenner 				printf(" %s", ip6addr_string(&tp[i]));
5909afd0c29SBill Fenner 			printf(")");
5915b0fe478SBruce M Simpson 			break;
5925b0fe478SBruce M Simpson 		case DH6OPT_STATUS_CODE:
5935b0fe478SBruce M Simpson 			if (optlen < 2) {
5945b0fe478SBruce M Simpson 				printf(" ?)");
5955b0fe478SBruce M Simpson 				break;
5965b0fe478SBruce M Simpson 			}
597*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
598*27df3f5dSRui Paulo 			printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0])));
5995b0fe478SBruce M Simpson 			break;
6005b0fe478SBruce M Simpson 		case DH6OPT_IA_NA:
6015b0fe478SBruce M Simpson 		case DH6OPT_IA_PD:
602*27df3f5dSRui Paulo 			if (optlen < 12) {
6035b0fe478SBruce M Simpson 				printf(" ?)");
6045b0fe478SBruce M Simpson 				break;
6055b0fe478SBruce M Simpson 			}
606*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
607*27df3f5dSRui Paulo 			printf(" IAID:%u T1:%u T2:%u",
608*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[0]),
609*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[4]),
610*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[8]));
611*27df3f5dSRui Paulo 			if (optlen > 12) {
6125b0fe478SBruce M Simpson 				/* there are sub-options */
613*27df3f5dSRui Paulo 				dhcp6opt_print(tp + 12, tp + 12 + optlen);
6145b0fe478SBruce M Simpson 			}
6155b0fe478SBruce M Simpson 			printf(")");
6165b0fe478SBruce M Simpson 			break;
617a5779b6eSRui Paulo 		case DH6OPT_IA_TA:
618a5779b6eSRui Paulo 			if (optlen < 4) {
619a5779b6eSRui Paulo 				printf(" ?)");
620a5779b6eSRui Paulo 				break;
621a5779b6eSRui Paulo 			}
622*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
623*27df3f5dSRui Paulo 			printf(" IAID:%u", EXTRACT_32BITS(tp));
624a5779b6eSRui Paulo 			if (optlen > 4) {
625a5779b6eSRui Paulo 				/* there are sub-options */
626*27df3f5dSRui Paulo 				dhcp6opt_print(tp + 4, tp + 4 + optlen);
627a5779b6eSRui Paulo 			}
628a5779b6eSRui Paulo 			printf(")");
629a5779b6eSRui Paulo 			break;
6305b0fe478SBruce M Simpson 		case DH6OPT_IA_PD_PREFIX:
631*27df3f5dSRui Paulo 			if (optlen < 25) {
6325b0fe478SBruce M Simpson 				printf(" ?)");
6335b0fe478SBruce M Simpson 				break;
6345b0fe478SBruce M Simpson 			}
635*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
636*27df3f5dSRui Paulo 			printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]);
637*27df3f5dSRui Paulo 			printf(" pltime:%u vltime:%u",
638*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[0]),
639*27df3f5dSRui Paulo 			    EXTRACT_32BITS(&tp[4]));
640*27df3f5dSRui Paulo 			if (optlen > 25) {
6415b0fe478SBruce M Simpson 				/* there are sub-options */
642*27df3f5dSRui Paulo 				dhcp6opt_print(tp + 25, tp + 25 + optlen);
6435b0fe478SBruce M Simpson 			}
6445b0fe478SBruce M Simpson 			printf(")");
6455b0fe478SBruce M Simpson 			break;
6461de50e9fSSam Leffler 		case DH6OPT_LIFETIME:
647a5779b6eSRui Paulo 		case DH6OPT_CLT_TIME:
6481de50e9fSSam Leffler 			if (optlen != 4) {
6491de50e9fSSam Leffler 				printf(" ?)");
6501de50e9fSSam Leffler 				break;
6511de50e9fSSam Leffler 			}
652*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
653*27df3f5dSRui Paulo 			printf(" %d)", EXTRACT_32BITS(tp));
6541de50e9fSSam Leffler 			break;
655a5779b6eSRui Paulo 		case DH6OPT_REMOTE_ID:
656a5779b6eSRui Paulo 			if (optlen < 4) {
657a5779b6eSRui Paulo 				printf(" ?)");
658a5779b6eSRui Paulo 				break;
659a5779b6eSRui Paulo 			}
660a5779b6eSRui Paulo 			tp = (u_char *)(dh6o + 1);
661*27df3f5dSRui Paulo 			printf(" %d ", EXTRACT_32BITS(tp));
662a5779b6eSRui Paulo 			/*
663a5779b6eSRui Paulo 			 * Print hex dump first 10 characters.
664a5779b6eSRui Paulo 			 */
665a5779b6eSRui Paulo 			for (i = 4; i < optlen && i < 14; i++)
666a5779b6eSRui Paulo 				printf("%02x", tp[i]);
667a5779b6eSRui Paulo 			printf("...)");
668a5779b6eSRui Paulo 			break;
669a5779b6eSRui Paulo 		case DH6OPT_LQ_QUERY:
670a5779b6eSRui Paulo 			if (optlen < 17) {
671a5779b6eSRui Paulo 				printf(" ?)");
672a5779b6eSRui Paulo 				break;
673a5779b6eSRui Paulo 			}
674a5779b6eSRui Paulo 			tp = (u_char *)(dh6o + 1);
675a5779b6eSRui Paulo 			switch (*tp) {
676a5779b6eSRui Paulo 			case 1:
677a5779b6eSRui Paulo 				printf(" by-address");
678a5779b6eSRui Paulo 				break;
679a5779b6eSRui Paulo 			case 2:
680a5779b6eSRui Paulo 				printf(" by-clientID");
681a5779b6eSRui Paulo 				break;
682a5779b6eSRui Paulo 			default:
683a5779b6eSRui Paulo 				printf(" type_%d", (int)*tp);
684a5779b6eSRui Paulo 				break;
685a5779b6eSRui Paulo 			}
686a5779b6eSRui Paulo 			printf(" %s", ip6addr_string(&tp[1]));
687a5779b6eSRui Paulo 			if (optlen > 17) {
688a5779b6eSRui Paulo 				/* there are query-options */
689a5779b6eSRui Paulo 				dhcp6opt_print(tp + 17, tp + optlen);
690a5779b6eSRui Paulo 			}
691a5779b6eSRui Paulo 			printf(")");
692a5779b6eSRui Paulo 			break;
693a5779b6eSRui Paulo 		case DH6OPT_CLIENT_DATA:
694*27df3f5dSRui Paulo 			tp = (u_char *)(dh6o + 1);
695a5779b6eSRui Paulo 			if (optlen > 0) {
696a5779b6eSRui Paulo 				/* there are encapsulated options */
697*27df3f5dSRui Paulo 				dhcp6opt_print(tp, tp + optlen);
698a5779b6eSRui Paulo 			}
699a5779b6eSRui Paulo 			printf(")");
700a5779b6eSRui Paulo 			break;
701a5779b6eSRui Paulo 		case DH6OPT_LQ_RELAY_DATA:
702a5779b6eSRui Paulo 			if (optlen < 16) {
703a5779b6eSRui Paulo 				printf(" ?)");
704a5779b6eSRui Paulo 				break;
705a5779b6eSRui Paulo 			}
706a5779b6eSRui Paulo 			tp = (u_char *)(dh6o + 1);
707a5779b6eSRui Paulo 			printf(" %s ", ip6addr_string(&tp[0]));
708a5779b6eSRui Paulo 			/*
709a5779b6eSRui Paulo 			 * Print hex dump first 10 characters.
710a5779b6eSRui Paulo 			 */
711a5779b6eSRui Paulo 			for (i = 16; i < optlen && i < 26; i++)
712a5779b6eSRui Paulo 				printf("%02x", tp[i]);
713a5779b6eSRui Paulo 			printf("...)");
714a5779b6eSRui Paulo 			break;
7159afd0c29SBill Fenner 		default:
7165b0fe478SBruce M Simpson 			printf(")");
7179afd0c29SBill Fenner 			break;
7189afd0c29SBill Fenner 		}
7199afd0c29SBill Fenner 
7209afd0c29SBill Fenner 		cp += sizeof(*dh6o) + optlen;
721b0453382SBill Fenner 	}
722b0453382SBill Fenner 	return;
723b0453382SBill Fenner 
724b0453382SBill Fenner trunc:
725b0453382SBill Fenner 	printf("[|dhcp6ext]");
726b0453382SBill Fenner }
727b0453382SBill Fenner 
728b0453382SBill Fenner /*
7299afd0c29SBill Fenner  * Print dhcp6 packets
730b0453382SBill Fenner  */
731b0453382SBill Fenner void
7325b0fe478SBruce M Simpson dhcp6_print(const u_char *cp, u_int length)
733b0453382SBill Fenner {
7349afd0c29SBill Fenner 	struct dhcp6 *dh6;
7355b0fe478SBruce M Simpson 	struct dhcp6_relay *dh6relay;
7365b0fe478SBruce M Simpson 	const u_char *ep;
737b0453382SBill Fenner 	u_char *extp;
7389afd0c29SBill Fenner 	const char *name;
739b0453382SBill Fenner 
740b0453382SBill Fenner 	printf("dhcp6");
741b0453382SBill Fenner 
742b0453382SBill Fenner 	ep = (u_char *)snapend;
7435b0fe478SBruce M Simpson 	if (cp + length < ep)
7445b0fe478SBruce M Simpson 		ep = cp + length;
745b0453382SBill Fenner 
7469afd0c29SBill Fenner 	dh6 = (struct dhcp6 *)cp;
7475b0fe478SBruce M Simpson 	dh6relay = (struct dhcp6_relay *)cp;
7485b0fe478SBruce M Simpson 	TCHECK(dh6->dh6_xid);
749b0453382SBill Fenner 	switch (dh6->dh6_msgtype) {
7505b0fe478SBruce M Simpson 	case DH6_SOLICIT:
7515b0fe478SBruce M Simpson 		name = "solicit";
7525b0fe478SBruce M Simpson 		break;
7535b0fe478SBruce M Simpson 	case DH6_ADVERTISE:
7545b0fe478SBruce M Simpson 		name = "advertise";
7555b0fe478SBruce M Simpson 		break;
7565b0fe478SBruce M Simpson 	case DH6_REQUEST:
7575b0fe478SBruce M Simpson 		name = "request";
7585b0fe478SBruce M Simpson 		break;
7595b0fe478SBruce M Simpson 	case DH6_CONFIRM:
7605b0fe478SBruce M Simpson 		name = "confirm";
7615b0fe478SBruce M Simpson 		break;
7625b0fe478SBruce M Simpson 	case DH6_RENEW:
7635b0fe478SBruce M Simpson 		name = "renew";
7645b0fe478SBruce M Simpson 		break;
7655b0fe478SBruce M Simpson 	case DH6_REBIND:
7665b0fe478SBruce M Simpson 		name = "rebind";
7675b0fe478SBruce M Simpson 		break;
768b0453382SBill Fenner 	case DH6_REPLY:
7699afd0c29SBill Fenner 		name = "reply";
7709afd0c29SBill Fenner 		break;
7715b0fe478SBruce M Simpson 	case DH6_RELEASE:
7725b0fe478SBruce M Simpson 		name = "release";
7735b0fe478SBruce M Simpson 		break;
7745b0fe478SBruce M Simpson 	case DH6_DECLINE:
7755b0fe478SBruce M Simpson 		name = "decline";
7765b0fe478SBruce M Simpson 		break;
7775b0fe478SBruce M Simpson 	case DH6_RECONFIGURE:
7785b0fe478SBruce M Simpson 		name = "reconfigure";
7795b0fe478SBruce M Simpson 		break;
7809afd0c29SBill Fenner 	case DH6_INFORM_REQ:
7819afd0c29SBill Fenner 		name= "inf-req";
7829afd0c29SBill Fenner 		break;
7835b0fe478SBruce M Simpson 	case DH6_RELAY_FORW:
7845b0fe478SBruce M Simpson 		name= "relay-fwd";
7855b0fe478SBruce M Simpson 		break;
7865b0fe478SBruce M Simpson 	case DH6_RELAY_REPLY:
7875b0fe478SBruce M Simpson 		name= "relay-reply";
7885b0fe478SBruce M Simpson 		break;
789a5779b6eSRui Paulo 	case DH6_LEASEQUERY:
790a5779b6eSRui Paulo 		name= "leasequery";
791a5779b6eSRui Paulo 		break;
792a5779b6eSRui Paulo 	case DH6_LQ_REPLY:
793a5779b6eSRui Paulo 		name= "leasequery-reply";
794a5779b6eSRui Paulo 		break;
7959afd0c29SBill Fenner 	default:
7969afd0c29SBill Fenner 		name = NULL;
797b0453382SBill Fenner 		break;
798b0453382SBill Fenner 	}
7999afd0c29SBill Fenner 
8009afd0c29SBill Fenner 	if (!vflag) {
8019afd0c29SBill Fenner 		if (name)
8029afd0c29SBill Fenner 			printf(" %s", name);
8035b0fe478SBruce M Simpson 		else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
8045b0fe478SBruce M Simpson 		    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
8059afd0c29SBill Fenner 			printf(" msgtype-%u", dh6->dh6_msgtype);
8065b0fe478SBruce M Simpson 		}
8079afd0c29SBill Fenner 		return;
808b0453382SBill Fenner 	}
8099afd0c29SBill Fenner 
8109afd0c29SBill Fenner 	/* XXX relay agent messages have to be handled differently */
8119afd0c29SBill Fenner 
8129afd0c29SBill Fenner 	if (name)
8139afd0c29SBill Fenner 		printf(" %s (", name);	/*)*/
8149afd0c29SBill Fenner 	else
8159afd0c29SBill Fenner 		printf(" msgtype-%u (", dh6->dh6_msgtype);	/*)*/
8165b0fe478SBruce M Simpson 	if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
8175b0fe478SBruce M Simpson 	    dh6->dh6_msgtype != DH6_RELAY_REPLY) {
8185b0fe478SBruce M Simpson 		printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
8199afd0c29SBill Fenner 		extp = (u_char *)(dh6 + 1);
8209afd0c29SBill Fenner 		dhcp6opt_print(extp, ep);
8215b0fe478SBruce M Simpson 	} else {		/* relay messages */
8225b0fe478SBruce M Simpson 		struct in6_addr addr6;
8235b0fe478SBruce M Simpson 
8245b0fe478SBruce M Simpson 		TCHECK(dh6relay->dh6relay_peeraddr);
8255b0fe478SBruce M Simpson 
8265b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
8275b0fe478SBruce M Simpson 		printf("linkaddr=%s", ip6addr_string(&addr6));
8285b0fe478SBruce M Simpson 
8295b0fe478SBruce M Simpson 		memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
8305b0fe478SBruce M Simpson 		printf(" peeraddr=%s", ip6addr_string(&addr6));
8315b0fe478SBruce M Simpson 
8325b0fe478SBruce M Simpson 		dhcp6opt_print((u_char *)(dh6relay + 1), ep);
8335b0fe478SBruce M Simpson 	}
834685295f4SBill Fenner 	/*(*/
835b0453382SBill Fenner 	printf(")");
836b0453382SBill Fenner 	return;
837b0453382SBill Fenner 
838b0453382SBill Fenner trunc:
8399afd0c29SBill Fenner 	printf("[|dhcp6]");
840b0453382SBill Fenner }
841