xref: /openbsd/usr.sbin/tcpdump/print-dhcp6.c (revision 03f38e3c)
1 /*	$OpenBSD: print-dhcp6.c,v 1.12 2019/12/02 22:07:20 dlg Exp $	*/
2 
3 /*
4  * Copyright (c) 2019 David Gwynne <dlg@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/time.h>
20 #include <sys/socket.h>
21 
22 struct mbuf;
23 struct rtentry;
24 #include <net/if.h>
25 
26 #include <netinet/in.h>
27 
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <arpa/inet.h>
32 
33 #include "interface.h"
34 #include "extract.h"
35 #include "addrtoname.h"
36 
37 /* Message type */
38 #define DH6_SOLICIT		1
39 #define DH6_ADVERTISE		2
40 #define DH6_REQUEST		3
41 #define DH6_CONFIRM		4
42 #define DH6_RENEW		5
43 #define DH6_REBIND		6
44 #define DH6_REPLY		7
45 #define DH6_RELEASE		8
46 #define DH6_DECLINE		9
47 #define DH6_RECONFIGURE		10
48 #define DH6_INFORMATION_REQUEST	11
49 #define DH6_RELAY_FORW		12
50 #define DH6_RELAY_REPL		13
51 
52 static void
53 dhcp6opt_print(const u_char *cp, u_int length)
54 {
55 	uint16_t code, len;
56 	u_int i;
57 	int l = snapend - cp;
58 
59 	while (length > 0) {
60 		if (l < sizeof(code))
61 			goto trunc;
62 		if (length < sizeof(code))
63 			goto iptrunc;
64 
65 		code = EXTRACT_16BITS(cp);
66 		cp += sizeof(code);
67 		length -= sizeof(code);
68 		l -= sizeof(code);
69 
70 		if (l < sizeof(len))
71 			goto trunc;
72 		if (length < sizeof(len))
73 			goto iptrunc;
74 
75 		len = EXTRACT_16BITS(cp);
76 		cp += sizeof(len);
77 		length -= sizeof(len);
78 		l -= sizeof(len);
79 
80 		printf("\n\toption %u len %u", code, len);
81 
82 		if (len > 0) {
83 			if (l < len)
84 				goto trunc;
85 			if (length < len)
86 				goto iptrunc;
87 
88 			printf(" ");
89 			for (i = 0; i < len; i++)
90 				printf("%02x", cp[4 + i] & 0xff);
91 
92 			cp += len;
93 			length -= len;
94 			l -= len;
95 		}
96 	}
97 	return;
98 
99 trunc:
100 	printf(" [|dhcp6opt]");
101 	return;
102 iptrunc:
103 	printf(" ip truncated");
104 }
105 
106 static void
107 dhcp6_relay_print(const u_char *cp, u_int length)
108 {
109 	uint8_t msgtype;
110 	const char *msgname = NULL;
111 
112 	msgtype = *cp;
113 
114 	switch (msgtype) {
115 	case DH6_RELAY_FORW:
116 		msgname = "Relay-forward";
117 		break;
118 	case DH6_RELAY_REPL:
119 		msgname = "Relay-reply";
120 		break;
121 	}
122 
123 	printf(" %s", msgname);
124 }
125 
126 void
127 dhcp6_print(const u_char *cp, u_int length)
128 {
129 	uint8_t msgtype;
130 	uint32_t hdr;
131 	int l = snapend - cp;
132 	const char *msgname;
133 
134 	printf("DHCPv6");
135 
136 	if (l < sizeof(msgtype))
137 		goto trunc;
138 	if (length < sizeof(msgtype))
139 		goto iptrunc;
140 
141 	msgtype = *cp;
142 
143 	switch (msgtype) {
144 	case DH6_SOLICIT:
145 		msgname = "Solicit";
146 		break;
147 	case DH6_ADVERTISE:
148 		msgname = "Advertise";
149 		break;
150 	case DH6_REQUEST:
151 		msgname = "Request";
152 		break;
153 	case DH6_CONFIRM:
154 		msgname = "Confirm";
155 		break;
156 	case DH6_RENEW:
157 		msgname = "Renew";
158 		break;
159 	case DH6_REBIND:
160 		msgname = "Rebind";
161 		break;
162 	case DH6_REPLY:
163 		msgname = "Reply";
164 		break;
165 	case DH6_RELEASE:
166 		msgname = "Release";
167 		break;
168 	case DH6_DECLINE:
169 		msgname = "Decline";
170 		break;
171 	case DH6_RECONFIGURE:
172 		msgname = "Reconfigure";
173 		break;
174 	case DH6_INFORMATION_REQUEST:
175 		msgname = "Information-request";
176 		break;
177 	case DH6_RELAY_FORW:
178 	case DH6_RELAY_REPL:
179 		dhcp6_relay_print(cp, length);
180 		return;
181 	default:
182 		printf(" unknown message type %u", msgtype);
183 		return;
184 	}
185 
186 	printf(" %s", msgname);
187 
188 	if (l < sizeof(hdr))
189 		goto trunc;
190 	if (length < sizeof(hdr))
191 		goto iptrunc;
192 
193 	hdr = EXTRACT_32BITS(cp);
194 	printf(" xid %x", hdr & 0xffffff);
195 
196 	if (vflag) {
197 		cp += sizeof(hdr);
198 		length -= sizeof(hdr);
199 
200 		dhcp6opt_print(cp, length);
201 	}
202 	return;
203 
204 trunc:
205 	printf(" [|dhcp6]");
206 	return;
207 iptrunc:
208 	printf(" ip truncated");
209 }
210