xref: /openbsd-src/usr.sbin/tcpdump/print-dhcp6.c (revision 426b943da867de522a7641ed6221b6e97830db2a)
1 /*	$OpenBSD: print-dhcp6.c,v 1.13 2021/12/01 18:28:45 deraadt 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 #include <net/if.h>
23 
24 #include <netinet/in.h>
25 
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <arpa/inet.h>
30 
31 #include "interface.h"
32 #include "extract.h"
33 #include "addrtoname.h"
34 
35 /* Message type */
36 #define DH6_SOLICIT		1
37 #define DH6_ADVERTISE		2
38 #define DH6_REQUEST		3
39 #define DH6_CONFIRM		4
40 #define DH6_RENEW		5
41 #define DH6_REBIND		6
42 #define DH6_REPLY		7
43 #define DH6_RELEASE		8
44 #define DH6_DECLINE		9
45 #define DH6_RECONFIGURE		10
46 #define DH6_INFORMATION_REQUEST	11
47 #define DH6_RELAY_FORW		12
48 #define DH6_RELAY_REPL		13
49 
50 static void
dhcp6opt_print(const u_char * cp,u_int length)51 dhcp6opt_print(const u_char *cp, u_int length)
52 {
53 	uint16_t code, len;
54 	u_int i;
55 	int l = snapend - cp;
56 
57 	while (length > 0) {
58 		if (l < sizeof(code))
59 			goto trunc;
60 		if (length < sizeof(code))
61 			goto iptrunc;
62 
63 		code = EXTRACT_16BITS(cp);
64 		cp += sizeof(code);
65 		length -= sizeof(code);
66 		l -= sizeof(code);
67 
68 		if (l < sizeof(len))
69 			goto trunc;
70 		if (length < sizeof(len))
71 			goto iptrunc;
72 
73 		len = EXTRACT_16BITS(cp);
74 		cp += sizeof(len);
75 		length -= sizeof(len);
76 		l -= sizeof(len);
77 
78 		printf("\n\toption %u len %u", code, len);
79 
80 		if (len > 0) {
81 			if (l < len)
82 				goto trunc;
83 			if (length < len)
84 				goto iptrunc;
85 
86 			printf(" ");
87 			for (i = 0; i < len; i++)
88 				printf("%02x", cp[4 + i] & 0xff);
89 
90 			cp += len;
91 			length -= len;
92 			l -= len;
93 		}
94 	}
95 	return;
96 
97 trunc:
98 	printf(" [|dhcp6opt]");
99 	return;
100 iptrunc:
101 	printf(" ip truncated");
102 }
103 
104 static void
dhcp6_relay_print(const u_char * cp,u_int length)105 dhcp6_relay_print(const u_char *cp, u_int length)
106 {
107 	uint8_t msgtype;
108 	const char *msgname = NULL;
109 
110 	msgtype = *cp;
111 
112 	switch (msgtype) {
113 	case DH6_RELAY_FORW:
114 		msgname = "Relay-forward";
115 		break;
116 	case DH6_RELAY_REPL:
117 		msgname = "Relay-reply";
118 		break;
119 	}
120 
121 	printf(" %s", msgname);
122 }
123 
124 void
dhcp6_print(const u_char * cp,u_int length)125 dhcp6_print(const u_char *cp, u_int length)
126 {
127 	uint8_t msgtype;
128 	uint32_t hdr;
129 	int l = snapend - cp;
130 	const char *msgname;
131 
132 	printf("DHCPv6");
133 
134 	if (l < sizeof(msgtype))
135 		goto trunc;
136 	if (length < sizeof(msgtype))
137 		goto iptrunc;
138 
139 	msgtype = *cp;
140 
141 	switch (msgtype) {
142 	case DH6_SOLICIT:
143 		msgname = "Solicit";
144 		break;
145 	case DH6_ADVERTISE:
146 		msgname = "Advertise";
147 		break;
148 	case DH6_REQUEST:
149 		msgname = "Request";
150 		break;
151 	case DH6_CONFIRM:
152 		msgname = "Confirm";
153 		break;
154 	case DH6_RENEW:
155 		msgname = "Renew";
156 		break;
157 	case DH6_REBIND:
158 		msgname = "Rebind";
159 		break;
160 	case DH6_REPLY:
161 		msgname = "Reply";
162 		break;
163 	case DH6_RELEASE:
164 		msgname = "Release";
165 		break;
166 	case DH6_DECLINE:
167 		msgname = "Decline";
168 		break;
169 	case DH6_RECONFIGURE:
170 		msgname = "Reconfigure";
171 		break;
172 	case DH6_INFORMATION_REQUEST:
173 		msgname = "Information-request";
174 		break;
175 	case DH6_RELAY_FORW:
176 	case DH6_RELAY_REPL:
177 		dhcp6_relay_print(cp, length);
178 		return;
179 	default:
180 		printf(" unknown message type %u", msgtype);
181 		return;
182 	}
183 
184 	printf(" %s", msgname);
185 
186 	if (l < sizeof(hdr))
187 		goto trunc;
188 	if (length < sizeof(hdr))
189 		goto iptrunc;
190 
191 	hdr = EXTRACT_32BITS(cp);
192 	printf(" xid %x", hdr & 0xffffff);
193 
194 	if (vflag) {
195 		cp += sizeof(hdr);
196 		length -= sizeof(hdr);
197 
198 		dhcp6opt_print(cp, length);
199 	}
200 	return;
201 
202 trunc:
203 	printf(" [|dhcp6]");
204 	return;
205 iptrunc:
206 	printf(" ip truncated");
207 }
208