xref: /freebsd/contrib/tcpdump/print-dhcp6.c (revision 9afd0c2902649a0007676d044c6ae7fa099e8cf3)
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 /*
309afd0c29SBill Fenner  * draft-ietf-dhc-dhcpv6-22.txt
319afd0c29SBill Fenner  */
32b0453382SBill Fenner 
33b0453382SBill Fenner #ifndef lint
34b0453382SBill Fenner static const char rcsid[] =
359afd0c29SBill Fenner     "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.14.4.2 2002/06/01 23:51:12 guy Exp $";
36b0453382SBill Fenner #endif
37b0453382SBill Fenner 
38b0453382SBill Fenner #ifdef HAVE_CONFIG_H
39b0453382SBill Fenner #include "config.h"
40b0453382SBill Fenner #endif
41b0453382SBill Fenner 
42b0453382SBill Fenner #include <sys/param.h>
43b0453382SBill Fenner #include <sys/time.h>
44b0453382SBill Fenner #include <sys/socket.h>
45b0453382SBill Fenner 
46b0453382SBill Fenner #include <netinet/in.h>
47b0453382SBill Fenner 
48b0453382SBill Fenner #include <ctype.h>
49b0453382SBill Fenner #include <stdio.h>
50b0453382SBill Fenner #include <string.h>
51b0453382SBill Fenner #include <arpa/inet.h>
52b0453382SBill Fenner 
53b0453382SBill Fenner #include "interface.h"
54b0453382SBill Fenner #include "addrtoname.h"
55b0453382SBill Fenner 
569afd0c29SBill Fenner /* Error Values */
579afd0c29SBill Fenner #define DH6ERR_FAILURE		16
589afd0c29SBill Fenner #define DH6ERR_AUTHFAIL		17
599afd0c29SBill Fenner #define DH6ERR_POORLYFORMED	18
609afd0c29SBill Fenner #define DH6ERR_UNAVAIL		19
619afd0c29SBill Fenner #define DH6ERR_OPTUNAVAIL	20
62b0453382SBill Fenner 
639afd0c29SBill Fenner /* Message type */
649afd0c29SBill Fenner #define DH6_REPLY	7
659afd0c29SBill Fenner #define DH6_INFORM_REQ	11
66b0453382SBill Fenner 
679afd0c29SBill Fenner /* DHCP6 base packet format */
689afd0c29SBill Fenner struct dhcp6 {
699afd0c29SBill Fenner 	union {
709afd0c29SBill Fenner 		u_int8_t m;
719afd0c29SBill Fenner 		u_int32_t x;
729afd0c29SBill Fenner 	} dh6_msgtypexid;
739afd0c29SBill Fenner 	struct in6_addr dh6_servaddr;
749afd0c29SBill Fenner 	/* options follow */
759afd0c29SBill Fenner } __attribute__ ((__packed__));
769afd0c29SBill Fenner #define dh6_msgtype	dh6_msgtypexid.m
779afd0c29SBill Fenner #define dh6_xid		dh6_msgtypexid.x
789afd0c29SBill Fenner #define DH6_XIDMASK	0x00ffffff
79b0453382SBill Fenner 
809afd0c29SBill Fenner /* option */
819afd0c29SBill Fenner #define DH6OPT_DUID	1	/* TBD */
829afd0c29SBill Fenner #define DH6OPT_DNS	11	/* TBD */
839afd0c29SBill Fenner struct dhcp6opt {
849afd0c29SBill Fenner 	u_int16_t dh6opt_type;
859afd0c29SBill Fenner 	u_int16_t dh6opt_len;
869afd0c29SBill Fenner 	/* type-dependent data follows */
879afd0c29SBill Fenner } __attribute__ ((__packed__));
88b0453382SBill Fenner 
89b0453382SBill Fenner static void
909afd0c29SBill Fenner dhcp6opt_print(u_char *cp, u_char *ep)
91b0453382SBill Fenner {
929afd0c29SBill Fenner 	struct dhcp6opt *dh6o;
939afd0c29SBill Fenner 	u_char *tp;
94b0453382SBill Fenner 	int i;
959afd0c29SBill Fenner 	size_t optlen;
96b0453382SBill Fenner 
97b0453382SBill Fenner 	if (cp == ep)
98b0453382SBill Fenner 		return;
99b0453382SBill Fenner 	while (cp < ep) {
1009afd0c29SBill Fenner 		if (ep - cp < sizeof(*dh6o))
101b0453382SBill Fenner 			goto trunc;
1029afd0c29SBill Fenner 		dh6o = (struct dhcp6opt *)cp;
1039afd0c29SBill Fenner 		optlen = ntohs(dh6o->dh6opt_len);
1049afd0c29SBill Fenner 		if (ep - cp < sizeof(*dh6o) + optlen)
105b0453382SBill Fenner 			goto trunc;
1069afd0c29SBill Fenner 		switch (ntohs(dh6o->dh6opt_type)) {
1079afd0c29SBill Fenner 		case DH6OPT_DUID:
1089afd0c29SBill Fenner 			printf(" (duid");	/*)*/
1099afd0c29SBill Fenner 			if (optlen < 2) {
1109afd0c29SBill Fenner 				/*(*/
1119afd0c29SBill Fenner 				printf(" ??)");
112b0453382SBill Fenner 				break;
113b0453382SBill Fenner 			}
1149afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
1159afd0c29SBill Fenner 			switch (ntohs(*(u_int16_t *)tp)) {
1169afd0c29SBill Fenner 			case 1:
1179afd0c29SBill Fenner 				if (optlen >= 2 + 6) {
1189afd0c29SBill Fenner 					printf(" hwaddr/time time %u type %u ",
1199afd0c29SBill Fenner 					    ntohl(*(u_int32_t *)&tp[2]),
1209afd0c29SBill Fenner 					    ntohs(*(u_int16_t *)&tp[6]));
1219afd0c29SBill Fenner 					for (i = 8; i < optlen; i++)
1229afd0c29SBill Fenner 						printf("%02x", tp[i]);
1239afd0c29SBill Fenner 					/*(*/
124b0453382SBill Fenner 					printf(")");
1259afd0c29SBill Fenner 				} else {
1269afd0c29SBill Fenner 					/*(*/
1279afd0c29SBill Fenner 					printf(" ??)");
1289afd0c29SBill Fenner 				}
1299afd0c29SBill Fenner 				break;
1309afd0c29SBill Fenner 			case 2:
1319afd0c29SBill Fenner 				if (optlen >= 2 + 8) {
1329afd0c29SBill Fenner 					printf(" vid ");
1339afd0c29SBill Fenner 					for (i = 2; i < 2 + 8; i++)
1349afd0c29SBill Fenner 						printf("%02x", tp[i]);
1359afd0c29SBill Fenner 					/*(*/
1369afd0c29SBill Fenner 					printf(")");
1379afd0c29SBill Fenner 				} else {
1389afd0c29SBill Fenner 					/*(*/
1399afd0c29SBill Fenner 					printf(" ??)");
1409afd0c29SBill Fenner 				}
1419afd0c29SBill Fenner 				break;
1429afd0c29SBill Fenner 			case 3:
1439afd0c29SBill Fenner 				if (optlen >= 2 + 2) {
1449afd0c29SBill Fenner 					printf(" hwaddr type %u ",
1459afd0c29SBill Fenner 					    ntohs(*(u_int16_t *)&tp[2]));
1469afd0c29SBill Fenner 					for (i = 4; i < optlen; i++)
1479afd0c29SBill Fenner 						printf("%02x", tp[i]);
1489afd0c29SBill Fenner 					/*(*/
1499afd0c29SBill Fenner 					printf(")");
1509afd0c29SBill Fenner 				} else {
1519afd0c29SBill Fenner 					/*(*/
1529afd0c29SBill Fenner 					printf(" ??)");
1539afd0c29SBill Fenner 				}
1549afd0c29SBill Fenner 			}
1559afd0c29SBill Fenner 			break;
1569afd0c29SBill Fenner 		case DH6OPT_DNS:
1579afd0c29SBill Fenner 			printf(" (dnsserver");	/*)*/
1589afd0c29SBill Fenner 			if (optlen % 16) {
1599afd0c29SBill Fenner 				/*(*/
1609afd0c29SBill Fenner 				printf(" ??)");
1619afd0c29SBill Fenner 				break;
1629afd0c29SBill Fenner 			}
1639afd0c29SBill Fenner 			tp = (u_char *)(dh6o + 1);
1649afd0c29SBill Fenner 			for (i = 0; i < optlen; i += 16)
1659afd0c29SBill Fenner 				printf(" %s", ip6addr_string(&tp[i]));
1669afd0c29SBill Fenner 			/*(*/
1679afd0c29SBill Fenner 			printf(")");
1689afd0c29SBill Fenner 		default:
1699afd0c29SBill Fenner 			printf(" (opt-%u)", ntohs(dh6o->dh6opt_type));
1709afd0c29SBill Fenner 			break;
1719afd0c29SBill Fenner 		}
1729afd0c29SBill Fenner 
1739afd0c29SBill Fenner 		cp += sizeof(*dh6o) + optlen;
174b0453382SBill Fenner 	}
175b0453382SBill Fenner 	return;
176b0453382SBill Fenner 
177b0453382SBill Fenner trunc:
178b0453382SBill Fenner 	printf("[|dhcp6ext]");
179b0453382SBill Fenner }
180b0453382SBill Fenner 
181b0453382SBill Fenner /*
1829afd0c29SBill Fenner  * Print dhcp6 packets
183b0453382SBill Fenner  */
184b0453382SBill Fenner void
185b0453382SBill Fenner dhcp6_print(register const u_char *cp, u_int length,
186685295f4SBill Fenner 	    u_int16_t sport, u_int16_t dport)
187b0453382SBill Fenner {
1889afd0c29SBill Fenner 	struct dhcp6 *dh6;
189b0453382SBill Fenner 	u_char *ep;
190b0453382SBill Fenner 	u_char *extp;
1919afd0c29SBill Fenner 	const char *name;
192b0453382SBill Fenner 
193b0453382SBill Fenner 	printf("dhcp6");
194b0453382SBill Fenner 
195b0453382SBill Fenner 	ep = (u_char *)snapend;
196b0453382SBill Fenner 
1979afd0c29SBill Fenner 	dh6 = (struct dhcp6 *)cp;
1989afd0c29SBill Fenner 	TCHECK(dh6->dh6_servaddr);
199b0453382SBill Fenner 	switch (dh6->dh6_msgtype) {
200b0453382SBill Fenner 	case DH6_REPLY:
2019afd0c29SBill Fenner 		name = "reply";
2029afd0c29SBill Fenner 		break;
2039afd0c29SBill Fenner 	case DH6_INFORM_REQ:
2049afd0c29SBill Fenner 		name= "inf-req";
2059afd0c29SBill Fenner 		break;
2069afd0c29SBill Fenner 	default:
2079afd0c29SBill Fenner 		name = NULL;
208b0453382SBill Fenner 		break;
209b0453382SBill Fenner 	}
2109afd0c29SBill Fenner 
2119afd0c29SBill Fenner 	if (!vflag) {
2129afd0c29SBill Fenner 		if (name)
2139afd0c29SBill Fenner 			printf(" %s", name);
2149afd0c29SBill Fenner 		else
2159afd0c29SBill Fenner 			printf(" msgtype-%u", dh6->dh6_msgtype);
2169afd0c29SBill Fenner 		return;
217b0453382SBill Fenner 	}
2189afd0c29SBill Fenner 
2199afd0c29SBill Fenner 	/* XXX relay agent messages have to be handled differently */
2209afd0c29SBill Fenner 
2219afd0c29SBill Fenner 	if (name)
2229afd0c29SBill Fenner 		printf(" %s (", name);	/*)*/
2239afd0c29SBill Fenner 	else
2249afd0c29SBill Fenner 		printf(" msgtype-%u (", dh6->dh6_msgtype);	/*)*/
2259afd0c29SBill Fenner 	printf("xid=%x", ntohl(dh6->dh6_xid) & DH6_XIDMASK);
2269afd0c29SBill Fenner 	printf(" server=%s", ip6addr_string(&dh6->dh6_servaddr));
2279afd0c29SBill Fenner 	extp = (u_char *)(dh6 + 1);
2289afd0c29SBill Fenner 	dhcp6opt_print(extp, ep);
229685295f4SBill Fenner 	/*(*/
230b0453382SBill Fenner 	printf(")");
231b0453382SBill Fenner 	return;
232b0453382SBill Fenner 
233b0453382SBill Fenner trunc:
2349afd0c29SBill Fenner 	printf("[|dhcp6]");
235b0453382SBill Fenner }
236