1 |
|
|
/* $OpenBSD: print-dhcp6.c,v 1.10 2015/11/18 15:36:20 mmcc Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (C) 1998 and 1999 WIDE Project. |
5 |
|
|
* All rights reserved. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that the following conditions |
9 |
|
|
* are met: |
10 |
|
|
* 1. Redistributions of source code must retain the above copyright |
11 |
|
|
* notice, this list of conditions and the following disclaimer. |
12 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer in the |
14 |
|
|
* documentation and/or other materials provided with the distribution. |
15 |
|
|
* 3. Neither the name of the project nor the names of its contributors |
16 |
|
|
* may be used to endorse or promote products derived from this software |
17 |
|
|
* without specific prior written permission. |
18 |
|
|
* |
19 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
20 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
23 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 |
|
|
* SUCH DAMAGE. |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
#ifdef INET6 |
33 |
|
|
|
34 |
|
|
#include <sys/time.h> |
35 |
|
|
#include <sys/socket.h> |
36 |
|
|
|
37 |
|
|
struct mbuf; |
38 |
|
|
struct rtentry; |
39 |
|
|
#include <net/if.h> |
40 |
|
|
|
41 |
|
|
#include <netinet/in.h> |
42 |
|
|
|
43 |
|
|
#include <ctype.h> |
44 |
|
|
#include <stdio.h> |
45 |
|
|
#include <string.h> |
46 |
|
|
#include <arpa/inet.h> |
47 |
|
|
|
48 |
|
|
#include "interface.h" |
49 |
|
|
#include "addrtoname.h" |
50 |
|
|
#include "dhcp6.h" |
51 |
|
|
#include "dhcp6opt.h" |
52 |
|
|
|
53 |
|
|
#if 0 |
54 |
|
|
static void dhcp6opttab_init(void); |
55 |
|
|
static struct dhcp6_opt *dhcp6opttab_byname(char *); |
56 |
|
|
#endif |
57 |
|
|
static struct dhcp6_opt *dhcp6opttab_bycode(u_int); |
58 |
|
|
|
59 |
|
|
static char tstr[] = " [|dhcp6]"; |
60 |
|
|
|
61 |
|
|
static struct dhcp6_opt dh6opttab[] = { |
62 |
|
|
/* IP Address Extension */ |
63 |
|
|
{ 1, OL6_N, "IP Address", OT6_NONE, }, |
64 |
|
|
|
65 |
|
|
/* General Extension */ |
66 |
|
|
{ 2, 4, "Time Offset", OT6_NUM, }, |
67 |
|
|
{ 3, OL6_N, "IEEE 1003.1 POSIX Timezone", OT6_STR, }, |
68 |
|
|
{ 6, OL6_16N, "Domain Name Server", OT6_V6, }, |
69 |
|
|
{ 10, OL6_N, "Domain Name", OT6_STR, }, |
70 |
|
|
|
71 |
|
|
/* Application and Service Parameters */ |
72 |
|
|
{ 16, OL6_N, "Directory Agent", OT6_NONE, }, |
73 |
|
|
{ 17, OL6_N, "Service Scope" , OT6_NONE, }, |
74 |
|
|
{ 18, OL6_16N, "Network Time Protocol Servers", OT6_V6, }, |
75 |
|
|
{ 19, OL6_N, "NIS Domain", OT6_STR, }, |
76 |
|
|
{ 20, OL6_16N, "NIS Servers", OT6_V6, }, |
77 |
|
|
{ 21, OL6_N, "NIS+ Domain", OT6_STR, }, |
78 |
|
|
{ 22, OL6_16N, "NIS+ Servers", OT6_V6, }, |
79 |
|
|
|
80 |
|
|
/* TCP Parameters */ |
81 |
|
|
{ 32, 4, "TCP Keepalive Interval", OT6_NUM, }, |
82 |
|
|
|
83 |
|
|
/* DHCPv6 Extensions */ |
84 |
|
|
{ 40, 4, "Maximum DHCPv6 Message Size", OT6_NUM, }, |
85 |
|
|
{ 41, OL6_N, "DHCP Retransmission and Configuration Parameter", |
86 |
|
|
OT6_NONE, }, |
87 |
|
|
{ 48, OL6_N, "Platform Specific Information", OT6_NONE, }, |
88 |
|
|
{ 49, OL6_N, "Platform Class Identifier", OT6_STR, }, |
89 |
|
|
{ 64, OL6_N, "Class Identifier", OT6_STR, }, |
90 |
|
|
{ 66, 16, "Reconfigure Multicast Address", OT6_V6, }, |
91 |
|
|
{ 67, 16, "Renumber DHCPv6 Server Address", |
92 |
|
|
OT6_V6, }, |
93 |
|
|
{ 68, OL6_N, "DHCP Relay ICMP Error Message", OT6_NONE, }, |
94 |
|
|
{ 84, OL6_N, "Client-Server Authentication", OT6_NONE, }, |
95 |
|
|
{ 85, 4, "Client Key Selection", OT6_NUM, }, |
96 |
|
|
|
97 |
|
|
/* End Extension */ |
98 |
|
|
{ 65536, OL6_Z, "End", OT6_NONE, }, |
99 |
|
|
|
100 |
|
|
{ 0 }, |
101 |
|
|
}; |
102 |
|
|
|
103 |
|
|
#if 0 |
104 |
|
|
static struct dhcp6_opt *dh6o_pad; |
105 |
|
|
static struct dhcp6_opt *dh6o_end; |
106 |
|
|
|
107 |
|
|
static void |
108 |
|
|
dhcp6opttab_init() |
109 |
|
|
{ |
110 |
|
|
dh6o_pad = dhcp6opttab_bycode(0); |
111 |
|
|
dh6o_end = dhcp6opttab_bycode(65536); |
112 |
|
|
} |
113 |
|
|
#endif |
114 |
|
|
|
115 |
|
|
#if 0 |
116 |
|
|
static struct dhcp6_opt * |
117 |
|
|
dhcp6opttab_byname(name) |
118 |
|
|
char *name; |
119 |
|
|
{ |
120 |
|
|
struct dhcp6_opt *p; |
121 |
|
|
|
122 |
|
|
for (p = dh6opttab; p->code; p++) |
123 |
|
|
if (strcmp(name, p->name) == 0) |
124 |
|
|
return p; |
125 |
|
|
return NULL; |
126 |
|
|
} |
127 |
|
|
#endif |
128 |
|
|
|
129 |
|
|
static struct dhcp6_opt * |
130 |
|
|
dhcp6opttab_bycode(code) |
131 |
|
|
u_int code; |
132 |
|
|
{ |
133 |
|
|
struct dhcp6_opt *p; |
134 |
|
|
|
135 |
|
|
for (p = dh6opttab; p->code; p++) |
136 |
|
|
if (p->code == code) |
137 |
|
|
return p; |
138 |
|
|
return NULL; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
static void |
142 |
|
|
dhcp6ext_print(u_char *cp, u_char *ep) |
143 |
|
|
{ |
144 |
|
|
u_int16_t code, len; |
145 |
|
|
struct dhcp6_opt *p; |
146 |
|
|
char buf[BUFSIZ]; |
147 |
|
|
int i; |
148 |
|
|
|
149 |
|
|
if (cp == ep) |
150 |
|
|
return; |
151 |
|
|
printf(" "); |
152 |
|
|
while (cp < ep) { |
153 |
|
|
code = ntohs(*(u_int16_t *)&cp[0]); |
154 |
|
|
if (code != 65535) |
155 |
|
|
len = ntohs(*(u_int16_t *)&cp[2]); |
156 |
|
|
else |
157 |
|
|
len = 0; |
158 |
|
|
p = dhcp6opttab_bycode(code); |
159 |
|
|
if (p == NULL) { |
160 |
|
|
printf("(unknown, len=%d)", len); |
161 |
|
|
cp += len + 4; |
162 |
|
|
continue; |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
/* sanity check on length */ |
166 |
|
|
switch (p->len) { |
167 |
|
|
case OL6_N: |
168 |
|
|
break; |
169 |
|
|
case OL6_16N: |
170 |
|
|
if (len % 16 != 0) |
171 |
|
|
goto trunc; |
172 |
|
|
break; |
173 |
|
|
case OL6_Z: |
174 |
|
|
if (len != 0) |
175 |
|
|
goto trunc; |
176 |
|
|
break; |
177 |
|
|
default: |
178 |
|
|
if (len != p->len) |
179 |
|
|
goto trunc; |
180 |
|
|
break; |
181 |
|
|
} |
182 |
|
|
if (cp + 4 + len > ep) { |
183 |
|
|
printf("[|%s]", p->name); |
184 |
|
|
return; |
185 |
|
|
} |
186 |
|
|
|
187 |
|
|
printf("(%s, ", p->name); |
188 |
|
|
switch (p->type) { |
189 |
|
|
case OT6_V6: |
190 |
|
|
for (i = 0; i < len; i += 16) { |
191 |
|
|
inet_ntop(AF_INET6, &cp[4 + i], buf, |
192 |
|
|
sizeof(buf)); |
193 |
|
|
if (i != 0) |
194 |
|
|
printf(","); |
195 |
|
|
printf("%s", buf); |
196 |
|
|
} |
197 |
|
|
break; |
198 |
|
|
case OT6_STR: |
199 |
|
|
memset(&buf, 0, sizeof(buf)); |
200 |
|
|
strlcpy(buf, &cp[4], len); |
201 |
|
|
printf("%s", buf); |
202 |
|
|
break; |
203 |
|
|
case OT6_NUM: |
204 |
|
|
printf("%d", (u_int32_t)ntohl(*(u_int32_t *)&cp[4])); |
205 |
|
|
break; |
206 |
|
|
default: |
207 |
|
|
for (i = 0; i < len; i++) |
208 |
|
|
printf("%02x", cp[4 + i] & 0xff); |
209 |
|
|
} |
210 |
|
|
printf(")"); |
211 |
|
|
cp += len + 4; |
212 |
|
|
} |
213 |
|
|
return; |
214 |
|
|
|
215 |
|
|
trunc: |
216 |
|
|
printf("[|dhcp6ext]"); |
217 |
|
|
} |
218 |
|
|
|
219 |
|
|
/* |
220 |
|
|
* Print dhcp6 requests |
221 |
|
|
*/ |
222 |
|
|
void |
223 |
|
|
dhcp6_print(const u_char *cp, u_int length, |
224 |
|
|
u_short sport, u_short dport) |
225 |
|
|
{ |
226 |
|
|
union dhcp6 *dh6; |
227 |
|
|
u_char *ep; |
228 |
|
|
u_char *extp; |
229 |
|
|
|
230 |
|
|
printf("dhcp6"); |
231 |
|
|
|
232 |
|
|
ep = (u_char *)snapend; |
233 |
|
|
|
234 |
|
|
dh6 = (union dhcp6 *)cp; |
235 |
|
|
TCHECK(dh6->dh6_msgtype); |
236 |
|
|
switch (dh6->dh6_msgtype) { |
237 |
|
|
case DH6_SOLICIT: |
238 |
|
|
if (vflag && TTEST(dh6->dh6_sol.dh6sol_relayaddr)) { |
239 |
|
|
printf(" solicit("); |
240 |
|
|
if ((dh6->dh6_sol.dh6sol_flags & DH6SOL_CLOSE) != 0) |
241 |
|
|
printf("C"); |
242 |
|
|
if (dh6->dh6_sol.dh6sol_flags != 0) |
243 |
|
|
printf(" "); |
244 |
|
|
printf("cliaddr=%s", |
245 |
|
|
ip6addr_string(&dh6->dh6_sol.dh6sol_cliaddr)); |
246 |
|
|
printf(" relayaddr=%s", |
247 |
|
|
ip6addr_string(&dh6->dh6_sol.dh6sol_relayaddr)); |
248 |
|
|
printf(")"); |
249 |
|
|
} else |
250 |
|
|
printf(" solicit"); |
251 |
|
|
break; |
252 |
|
|
case DH6_ADVERT: |
253 |
|
|
if (!(vflag && TTEST(dh6->dh6_adv.dh6adv_serveraddr))) { |
254 |
|
|
printf(" advert"); |
255 |
|
|
break; |
256 |
|
|
} |
257 |
|
|
printf(" advert("); |
258 |
|
|
if ((dh6->dh6_adv.dh6adv_flags & DH6ADV_SERVPRESENT) != 0) |
259 |
|
|
printf("S"); |
260 |
|
|
if (dh6->dh6_adv.dh6adv_flags != 0) |
261 |
|
|
printf(" "); |
262 |
|
|
printf("pref=%u", dh6->dh6_adv.dh6adv_pref); |
263 |
|
|
printf(" cliaddr=%s", |
264 |
|
|
ip6addr_string(&dh6->dh6_adv.dh6adv_cliaddr)); |
265 |
|
|
printf(" relayaddr=%s", |
266 |
|
|
ip6addr_string(&dh6->dh6_adv.dh6adv_relayaddr)); |
267 |
|
|
printf(" servaddr=%s", |
268 |
|
|
ip6addr_string(&dh6->dh6_adv.dh6adv_serveraddr)); |
269 |
|
|
extp = (u_char *)((&dh6->dh6_adv) + 1); |
270 |
|
|
dhcp6ext_print(extp, ep); |
271 |
|
|
printf(")"); |
272 |
|
|
break; |
273 |
|
|
case DH6_REQUEST: |
274 |
|
|
if (!(vflag && TTEST(dh6->dh6_req.dh6req_relayaddr))) { |
275 |
|
|
printf(" request"); |
276 |
|
|
break; |
277 |
|
|
} |
278 |
|
|
printf(" request("); |
279 |
|
|
if ((dh6->dh6_req.dh6req_flags & DH6REQ_CLOSE) != 0) |
280 |
|
|
printf("C"); |
281 |
|
|
if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) |
282 |
|
|
printf("S"); |
283 |
|
|
if ((dh6->dh6_req.dh6req_flags & DH6REQ_REBOOT) != 0) |
284 |
|
|
printf("R"); |
285 |
|
|
if (dh6->dh6_req.dh6req_flags != 0) |
286 |
|
|
printf(" "); |
287 |
|
|
printf("xid=0x%04x", dh6->dh6_req.dh6req_xid); |
288 |
|
|
printf(" cliaddr=%s", |
289 |
|
|
ip6addr_string(&dh6->dh6_req.dh6req_cliaddr)); |
290 |
|
|
printf(" relayaddr=%s", |
291 |
|
|
ip6addr_string(&dh6->dh6_req.dh6req_relayaddr)); |
292 |
|
|
extp = (char *)((&dh6->dh6_req) + 1); |
293 |
|
|
if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) { |
294 |
|
|
printf(" servaddr=%s", ip6addr_string(extp)); |
295 |
|
|
extp += 16; |
296 |
|
|
} |
297 |
|
|
dhcp6ext_print(extp, ep); |
298 |
|
|
printf(")"); |
299 |
|
|
break; |
300 |
|
|
case DH6_REPLY: |
301 |
|
|
if (!(vflag && TTEST(dh6->dh6_rep.dh6rep_xid))) { |
302 |
|
|
printf(" reply"); |
303 |
|
|
break; |
304 |
|
|
} |
305 |
|
|
printf(" reply("); |
306 |
|
|
if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) |
307 |
|
|
printf("C"); |
308 |
|
|
if (dh6->dh6_rep.dh6rep_flagandstat != 0) |
309 |
|
|
printf(" "); |
310 |
|
|
printf("stat=0x%02x", |
311 |
|
|
dh6->dh6_rep.dh6rep_flagandstat & DH6REP_STATMASK); |
312 |
|
|
extp = (u_char *)((&dh6->dh6_rep) + 1); |
313 |
|
|
if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) { |
314 |
|
|
printf(" cliaddr=%s", ip6addr_string(extp)); |
315 |
|
|
extp += 16; |
316 |
|
|
} |
317 |
|
|
dhcp6ext_print(extp, ep); |
318 |
|
|
printf(")"); |
319 |
|
|
break; |
320 |
|
|
case DH6_RELEASE: |
321 |
|
|
printf(" release"); |
322 |
|
|
break; |
323 |
|
|
case DH6_RECONFIG: |
324 |
|
|
printf(" reconfig"); |
325 |
|
|
break; |
326 |
|
|
} |
327 |
|
|
return; |
328 |
|
|
|
329 |
|
|
trunc: |
330 |
|
|
printf("%s", tstr); |
331 |
|
|
} |
332 |
|
|
|
333 |
|
|
#endif /* INET6 */ |