]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
Fix typo.
[tcpdump] / print-dhcp6.c
1 /*
2 * Copyright (C) 1998 and 1999 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 /*
30 * RFC3315: DHCPv6
31 * supported DHCPv6 options:
32 * RFC3319: Session Initiation Protocol (SIP) Servers options,
33 * RFC3633: IPv6 Prefix options,
34 * RFC3646: DNS Configuration options,
35 * RFC3898: Network Information Service (NIS) Configuration options,
36 * RFC4075: Simple Network Time Protocol (SNTP) Configuration option,
37 * RFC4242: Information Refresh Time option,
38 * RFC4280: Broadcast and Multicast Control Servers options,
39 * RFC5908: Network Time Protocol (NTP) Server Option for DHCPv6
40 * RFC6334: Dual-Stack Lite option,
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include <tcpdump-stdinc.h>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #include "interface.h"
53 #include "addrtoname.h"
54 #include "extract.h"
55
56 /* lease duration */
57 #define DHCP6_DURATION_INFINITE 0xffffffff
58
59 /* Error Values */
60 #define DH6ERR_FAILURE 16
61 #define DH6ERR_AUTHFAIL 17
62 #define DH6ERR_POORLYFORMED 18
63 #define DH6ERR_UNAVAIL 19
64 #define DH6ERR_OPTUNAVAIL 20
65
66 /* Message type */
67 #define DH6_SOLICIT 1
68 #define DH6_ADVERTISE 2
69 #define DH6_REQUEST 3
70 #define DH6_CONFIRM 4
71 #define DH6_RENEW 5
72 #define DH6_REBIND 6
73 #define DH6_REPLY 7
74 #define DH6_RELEASE 8
75 #define DH6_DECLINE 9
76 #define DH6_RECONFIGURE 10
77 #define DH6_INFORM_REQ 11
78 #define DH6_RELAY_FORW 12
79 #define DH6_RELAY_REPLY 13
80 #define DH6_LEASEQUERY 14
81 #define DH6_LQ_REPLY 15
82
83 /* DHCP6 base packet format */
84 struct dhcp6 {
85 union {
86 u_int8_t m;
87 u_int32_t x;
88 } dh6_msgtypexid;
89 /* options follow */
90 };
91 #define dh6_msgtype dh6_msgtypexid.m
92 #define dh6_xid dh6_msgtypexid.x
93 #define DH6_XIDMASK 0x00ffffff
94
95 /* DHCPv6 relay messages */
96 struct dhcp6_relay {
97 u_int8_t dh6relay_msgtype;
98 u_int8_t dh6relay_hcnt;
99 u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */
100 u_int8_t dh6relay_peeraddr[16];
101 /* options follow */
102 };
103
104 /* options */
105 #define DH6OPT_CLIENTID 1
106 #define DH6OPT_SERVERID 2
107 #define DH6OPT_IA_NA 3
108 #define DH6OPT_IA_TA 4
109 #define DH6OPT_IA_ADDR 5
110 #define DH6OPT_ORO 6
111 #define DH6OPT_PREFERENCE 7
112 # define DH6OPT_PREF_MAX 255
113 #define DH6OPT_ELAPSED_TIME 8
114 #define DH6OPT_RELAY_MSG 9
115 /*#define DH6OPT_SERVER_MSG 10 deprecated */
116 #define DH6OPT_AUTH 11
117 # define DH6OPT_AUTHPROTO_DELAYED 2
118 # define DH6OPT_AUTHPROTO_RECONFIG 3
119 # define DH6OPT_AUTHALG_HMACMD5 1
120 # define DH6OPT_AUTHRDM_MONOCOUNTER 0
121 # define DH6OPT_AUTHRECONFIG_KEY 1
122 # define DH6OPT_AUTHRECONFIG_HMACMD5 2
123 #define DH6OPT_UNICAST 12
124 #define DH6OPT_STATUS_CODE 13
125 # define DH6OPT_STCODE_SUCCESS 0
126 # define DH6OPT_STCODE_UNSPECFAIL 1
127 # define DH6OPT_STCODE_NOADDRAVAIL 2
128 # define DH6OPT_STCODE_NOBINDING 3
129 # define DH6OPT_STCODE_NOTONLINK 4
130 # define DH6OPT_STCODE_USEMULTICAST 5
131 # define DH6OPT_STCODE_NOPREFIXAVAIL 6
132 # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
133 # define DH6OPT_STCODE_MALFORMEDQUERY 8
134 # define DH6OPT_STCODE_NOTCONFIGURED 9
135 # define DH6OPT_STCODE_NOTALLOWED 10
136 #define DH6OPT_RAPID_COMMIT 14
137 #define DH6OPT_USER_CLASS 15
138 #define DH6OPT_VENDOR_CLASS 16
139 #define DH6OPT_VENDOR_OPTS 17
140 #define DH6OPT_INTERFACE_ID 18
141 #define DH6OPT_RECONF_MSG 19
142 #define DH6OPT_RECONF_ACCEPT 20
143 #define DH6OPT_SIP_SERVER_D 21
144 #define DH6OPT_SIP_SERVER_A 22
145 #define DH6OPT_DNS_SERVERS 23
146 #define DH6OPT_DOMAIN_LIST 24
147 #define DH6OPT_IA_PD 25
148 #define DH6OPT_IA_PD_PREFIX 26
149 #define DH6OPT_NIS_SERVERS 27
150 #define DH6OPT_NISP_SERVERS 28
151 #define DH6OPT_NIS_NAME 29
152 #define DH6OPT_NISP_NAME 30
153 #define DH6OPT_SNTP_SERVERS 31
154 #define DH6OPT_LIFETIME 32
155 #define DH6OPT_BCMCS_SERVER_D 33
156 #define DH6OPT_BCMCS_SERVER_A 34
157 #define DH6OPT_GEOCONF_CIVIC 36
158 #define DH6OPT_REMOTE_ID 37
159 #define DH6OPT_SUBSCRIBER_ID 38
160 #define DH6OPT_CLIENT_FQDN 39
161 #define DH6OPT_PANA_AGENT 40
162 #define DH6OPT_NEW_POSIX_TIMEZONE 41
163 #define DH6OPT_NEW_TZDB_TIMEZONE 42
164 #define DH6OPT_ERO 43
165 #define DH6OPT_LQ_QUERY 44
166 #define DH6OPT_CLIENT_DATA 45
167 #define DH6OPT_CLT_TIME 46
168 #define DH6OPT_LQ_RELAY_DATA 47
169 #define DH6OPT_LQ_CLIENT_LINK 48
170 #define DH6OPT_NTP_SERVER 56
171 # define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
172 # define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
173 # define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
174 #define DH6OPT_AFTR_NAME 64
175
176 struct dhcp6opt {
177 u_int16_t dh6opt_type;
178 u_int16_t dh6opt_len;
179 /* type-dependent data follows */
180 };
181
182 static const char *
183 dhcp6opt_name(int type)
184 {
185 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
186
187 if (type > 65535)
188 return "INVALID-option";
189
190 switch(type) {
191 case DH6OPT_CLIENTID:
192 return "client-ID";
193 case DH6OPT_SERVERID:
194 return "server-ID";
195 case DH6OPT_IA_NA:
196 return "IA_NA";
197 case DH6OPT_IA_TA:
198 return "IA_TA";
199 case DH6OPT_IA_ADDR:
200 return "IA_ADDR";
201 case DH6OPT_ORO:
202 return "option-request";
203 case DH6OPT_PREFERENCE:
204 return "preference";
205 case DH6OPT_ELAPSED_TIME:
206 return "elapsed-time";
207 case DH6OPT_RELAY_MSG:
208 return "relay-message";
209 case DH6OPT_AUTH:
210 return "authentication";
211 case DH6OPT_UNICAST:
212 return "server-unicast";
213 case DH6OPT_STATUS_CODE:
214 return "status-code";
215 case DH6OPT_RAPID_COMMIT:
216 return "rapid-commit";
217 case DH6OPT_USER_CLASS:
218 return "user-class";
219 case DH6OPT_VENDOR_CLASS:
220 return "vendor-class";
221 case DH6OPT_VENDOR_OPTS:
222 return "vendor-specific-info";
223 case DH6OPT_INTERFACE_ID:
224 return "interface-ID";
225 case DH6OPT_RECONF_MSG:
226 return "reconfigure-message";
227 case DH6OPT_RECONF_ACCEPT:
228 return "reconfigure-accept";
229 case DH6OPT_SIP_SERVER_D:
230 return "SIP-servers-domain";
231 case DH6OPT_SIP_SERVER_A:
232 return "SIP-servers-address";
233 case DH6OPT_DNS_SERVERS:
234 return "DNS-server";
235 case DH6OPT_DOMAIN_LIST:
236 return "DNS-search-list";
237 case DH6OPT_IA_PD:
238 return "IA_PD";
239 case DH6OPT_IA_PD_PREFIX:
240 return "IA_PD-prefix";
241 case DH6OPT_SNTP_SERVERS:
242 return "SNTP-servers";
243 case DH6OPT_LIFETIME:
244 return "lifetime";
245 case DH6OPT_NIS_SERVERS:
246 return "NIS-server";
247 case DH6OPT_NISP_SERVERS:
248 return "NIS+-server";
249 case DH6OPT_NIS_NAME:
250 return "NIS-domain-name";
251 case DH6OPT_NISP_NAME:
252 return "NIS+-domain-name";
253 case DH6OPT_BCMCS_SERVER_D:
254 return "BCMCS-domain-name";
255 case DH6OPT_BCMCS_SERVER_A:
256 return "BCMCS-server";
257 case DH6OPT_GEOCONF_CIVIC:
258 return "Geoconf-Civic";
259 case DH6OPT_REMOTE_ID:
260 return "Remote-ID";
261 case DH6OPT_SUBSCRIBER_ID:
262 return "Subscriber-ID";
263 case DH6OPT_CLIENT_FQDN:
264 return "Client-FQDN";
265 case DH6OPT_PANA_AGENT:
266 return "PANA-agent";
267 case DH6OPT_NEW_POSIX_TIMEZONE:
268 return "POSIX-timezone";
269 case DH6OPT_NEW_TZDB_TIMEZONE:
270 return "POSIX-tz-database";
271 case DH6OPT_ERO:
272 return "Echo-request-option";
273 case DH6OPT_LQ_QUERY:
274 return "Lease-query";
275 case DH6OPT_CLIENT_DATA:
276 return "LQ-client-data";
277 case DH6OPT_CLT_TIME:
278 return "Clt-time";
279 case DH6OPT_LQ_RELAY_DATA:
280 return "LQ-relay-data";
281 case DH6OPT_LQ_CLIENT_LINK:
282 return "LQ-client-link";
283 case DH6OPT_NTP_SERVER:
284 return "NTP-server";
285 case DH6OPT_AFTR_NAME:
286 return "AFTR-Name";
287 default:
288 snprintf(genstr, sizeof(genstr), "opt_%d", type);
289 return(genstr);
290 }
291 }
292
293 static const char *
294 dhcp6stcode(int code)
295 {
296 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
297
298 if (code > 255)
299 return "INVALID code";
300
301 switch(code) {
302 case DH6OPT_STCODE_SUCCESS:
303 return "success";
304 case DH6OPT_STCODE_UNSPECFAIL:
305 return "unspec failure";
306 case DH6OPT_STCODE_NOADDRAVAIL:
307 return "no addresses";
308 case DH6OPT_STCODE_NOBINDING:
309 return "no binding";
310 case DH6OPT_STCODE_NOTONLINK:
311 return "not on-link";
312 case DH6OPT_STCODE_USEMULTICAST:
313 return "use multicast";
314 case DH6OPT_STCODE_NOPREFIXAVAIL:
315 return "no prefixes";
316 case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
317 return "unknown query type";
318 case DH6OPT_STCODE_MALFORMEDQUERY:
319 return "malformed query";
320 case DH6OPT_STCODE_NOTCONFIGURED:
321 return "not configured";
322 case DH6OPT_STCODE_NOTALLOWED:
323 return "not allowed";
324 default:
325 snprintf(genstr, sizeof(genstr), "code%d", code);
326 return(genstr);
327 }
328 }
329
330 static void
331 dhcp6opt_print(const u_char *cp, const u_char *ep)
332 {
333 const struct dhcp6opt *dh6o;
334 const u_char *tp;
335 size_t i;
336 u_int16_t opttype;
337 size_t optlen;
338 u_int8_t auth_proto;
339 u_int authinfolen, authrealmlen;
340 int remain_len; /* Length of remaining options */
341 int label_len; /* Label length */
342 u_int16_t subopt_code;
343 u_int16_t subopt_len;
344
345 if (cp == ep)
346 return;
347 while (cp < ep) {
348 if (ep < cp + sizeof(*dh6o))
349 goto trunc;
350 dh6o = (struct dhcp6opt *)cp;
351 TCHECK(*dh6o);
352 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
353 if (ep < cp + sizeof(*dh6o) + optlen)
354 goto trunc;
355 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
356 printf(" (%s", dhcp6opt_name(opttype));
357 switch (opttype) {
358 case DH6OPT_CLIENTID:
359 case DH6OPT_SERVERID:
360 if (optlen < 2) {
361 /*(*/
362 printf(" ?)");
363 break;
364 }
365 tp = (u_char *)(dh6o + 1);
366 switch (EXTRACT_16BITS(tp)) {
367 case 1:
368 if (optlen >= 2 + 6) {
369 printf(" hwaddr/time type %u time %u ",
370 EXTRACT_16BITS(&tp[2]),
371 EXTRACT_32BITS(&tp[4]));
372 for (i = 8; i < optlen; i++)
373 printf("%02x", tp[i]);
374 /*(*/
375 printf(")");
376 } else {
377 /*(*/
378 printf(" ?)");
379 }
380 break;
381 case 2:
382 if (optlen >= 2 + 8) {
383 printf(" vid ");
384 for (i = 2; i < 2 + 8; i++)
385 printf("%02x", tp[i]);
386 /*(*/
387 printf(")");
388 } else {
389 /*(*/
390 printf(" ?)");
391 }
392 break;
393 case 3:
394 if (optlen >= 2 + 2) {
395 printf(" hwaddr type %u ",
396 EXTRACT_16BITS(&tp[2]));
397 for (i = 4; i < optlen; i++)
398 printf("%02x", tp[i]);
399 /*(*/
400 printf(")");
401 } else {
402 /*(*/
403 printf(" ?)");
404 }
405 break;
406 default:
407 printf(" type %d)", EXTRACT_16BITS(tp));
408 break;
409 }
410 break;
411 case DH6OPT_IA_ADDR:
412 if (optlen < 24) {
413 /*(*/
414 printf(" ?)");
415 break;
416 }
417 tp = (u_char *)(dh6o + 1);
418 printf(" %s", ip6addr_string(&tp[0]));
419 printf(" pltime:%u vltime:%u",
420 EXTRACT_32BITS(&tp[16]),
421 EXTRACT_32BITS(&tp[20]));
422 if (optlen > 24) {
423 /* there are sub-options */
424 dhcp6opt_print(tp + 24, tp + optlen);
425 }
426 printf(")");
427 break;
428 case DH6OPT_ORO:
429 case DH6OPT_ERO:
430 if (optlen % 2) {
431 printf(" ?)");
432 break;
433 }
434 tp = (u_char *)(dh6o + 1);
435 for (i = 0; i < optlen; i += 2) {
436 printf(" %s",
437 dhcp6opt_name(EXTRACT_16BITS(&tp[i])));
438 }
439 printf(")");
440 break;
441 case DH6OPT_PREFERENCE:
442 if (optlen != 1) {
443 printf(" ?)");
444 break;
445 }
446 tp = (u_char *)(dh6o + 1);
447 printf(" %d)", *tp);
448 break;
449 case DH6OPT_ELAPSED_TIME:
450 if (optlen != 2) {
451 printf(" ?)");
452 break;
453 }
454 tp = (u_char *)(dh6o + 1);
455 printf(" %d)", EXTRACT_16BITS(tp));
456 break;
457 case DH6OPT_RELAY_MSG:
458 printf(" (");
459 tp = (u_char *)(dh6o + 1);
460 dhcp6_print(tp, optlen);
461 printf(")");
462 break;
463 case DH6OPT_AUTH:
464 if (optlen < 11) {
465 printf(" ?)");
466 break;
467 }
468 tp = (u_char *)(dh6o + 1);
469 auth_proto = *tp;
470 switch (auth_proto) {
471 case DH6OPT_AUTHPROTO_DELAYED:
472 printf(" proto: delayed");
473 break;
474 case DH6OPT_AUTHPROTO_RECONFIG:
475 printf(" proto: reconfigure");
476 break;
477 default:
478 printf(" proto: %d", auth_proto);
479 break;
480 }
481 tp++;
482 switch (*tp) {
483 case DH6OPT_AUTHALG_HMACMD5:
484 /* XXX: may depend on the protocol */
485 printf(", alg: HMAC-MD5");
486 break;
487 default:
488 printf(", alg: %d", *tp);
489 break;
490 }
491 tp++;
492 switch (*tp) {
493 case DH6OPT_AUTHRDM_MONOCOUNTER:
494 printf(", RDM: mono");
495 break;
496 default:
497 printf(", RDM: %d", *tp);
498 break;
499 }
500 tp++;
501 printf(", RD:");
502 for (i = 0; i < 4; i++, tp += 2)
503 printf(" %04x", EXTRACT_16BITS(tp));
504
505 /* protocol dependent part */
506 authinfolen = optlen - 11;
507 switch (auth_proto) {
508 case DH6OPT_AUTHPROTO_DELAYED:
509 if (authinfolen == 0)
510 break;
511 if (authinfolen < 20) {
512 printf(" ??");
513 break;
514 }
515 authrealmlen = authinfolen - 20;
516 if (authrealmlen > 0) {
517 printf(", realm: ");
518 }
519 for (i = 0; i < authrealmlen; i++, tp++)
520 printf("%02x", *tp);
521 printf(", key ID: %08x", EXTRACT_32BITS(tp));
522 tp += 4;
523 printf(", HMAC-MD5:");
524 for (i = 0; i < 4; i++, tp+= 4)
525 printf(" %08x", EXTRACT_32BITS(tp));
526 break;
527 case DH6OPT_AUTHPROTO_RECONFIG:
528 if (authinfolen != 17) {
529 printf(" ??");
530 break;
531 }
532 switch (*tp++) {
533 case DH6OPT_AUTHRECONFIG_KEY:
534 printf(" reconfig-key");
535 break;
536 case DH6OPT_AUTHRECONFIG_HMACMD5:
537 printf(" type: HMAC-MD5");
538 break;
539 default:
540 printf(" type: ??");
541 break;
542 }
543 printf(" value:");
544 for (i = 0; i < 4; i++, tp+= 4)
545 printf(" %08x", EXTRACT_32BITS(tp));
546 break;
547 default:
548 printf(" ??");
549 break;
550 }
551
552 printf(")");
553 break;
554 case DH6OPT_RAPID_COMMIT: /* nothing todo */
555 printf(")");
556 break;
557 case DH6OPT_INTERFACE_ID:
558 case DH6OPT_SUBSCRIBER_ID:
559 /*
560 * Since we cannot predict the encoding, print hex dump
561 * at most 10 characters.
562 */
563 tp = (u_char *)(dh6o + 1);
564 printf(" ");
565 for (i = 0; i < optlen && i < 10; i++)
566 printf("%02x", tp[i]);
567 printf("...)");
568 break;
569 case DH6OPT_RECONF_MSG:
570 tp = (u_char *)(dh6o + 1);
571 switch (*tp) {
572 case DH6_RENEW:
573 printf(" for renew)");
574 break;
575 case DH6_INFORM_REQ:
576 printf(" for inf-req)");
577 break;
578 default:
579 printf(" for ?\?\?(%02x))", *tp);
580 break;
581 }
582 break;
583 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
584 printf(")");
585 break;
586 case DH6OPT_SIP_SERVER_A:
587 case DH6OPT_DNS_SERVERS:
588 case DH6OPT_SNTP_SERVERS:
589 case DH6OPT_NIS_SERVERS:
590 case DH6OPT_NISP_SERVERS:
591 case DH6OPT_BCMCS_SERVER_A:
592 case DH6OPT_PANA_AGENT:
593 case DH6OPT_LQ_CLIENT_LINK:
594 if (optlen % 16) {
595 printf(" ?)");
596 break;
597 }
598 tp = (u_char *)(dh6o + 1);
599 for (i = 0; i < optlen; i += 16)
600 printf(" %s", ip6addr_string(&tp[i]));
601 printf(")");
602 break;
603 case DH6OPT_SIP_SERVER_D:
604 case DH6OPT_DOMAIN_LIST:
605 tp = (u_char *)(dh6o + 1);
606 while (tp < cp + sizeof(*dh6o) + optlen) {
607 putchar(' ');
608 if ((tp = ns_nprint(tp, cp + sizeof(*dh6o) + optlen)) == NULL)
609 goto trunc;
610 }
611 printf(")");
612 break;
613 case DH6OPT_STATUS_CODE:
614 if (optlen < 2) {
615 printf(" ?)");
616 break;
617 }
618 tp = (u_char *)(dh6o + 1);
619 printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0])));
620 break;
621 case DH6OPT_IA_NA:
622 case DH6OPT_IA_PD:
623 if (optlen < 12) {
624 printf(" ?)");
625 break;
626 }
627 tp = (u_char *)(dh6o + 1);
628 printf(" IAID:%u T1:%u T2:%u",
629 EXTRACT_32BITS(&tp[0]),
630 EXTRACT_32BITS(&tp[4]),
631 EXTRACT_32BITS(&tp[8]));
632 if (optlen > 12) {
633 /* there are sub-options */
634 dhcp6opt_print(tp + 12, tp + optlen);
635 }
636 printf(")");
637 break;
638 case DH6OPT_IA_TA:
639 if (optlen < 4) {
640 printf(" ?)");
641 break;
642 }
643 tp = (u_char *)(dh6o + 1);
644 printf(" IAID:%u", EXTRACT_32BITS(tp));
645 if (optlen > 4) {
646 /* there are sub-options */
647 dhcp6opt_print(tp + 4, tp + optlen);
648 }
649 printf(")");
650 break;
651 case DH6OPT_IA_PD_PREFIX:
652 if (optlen < 25) {
653 printf(" ?)");
654 break;
655 }
656 tp = (u_char *)(dh6o + 1);
657 printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]);
658 printf(" pltime:%u vltime:%u",
659 EXTRACT_32BITS(&tp[0]),
660 EXTRACT_32BITS(&tp[4]));
661 if (optlen > 25) {
662 /* there are sub-options */
663 dhcp6opt_print(tp + 25, tp + optlen);
664 }
665 printf(")");
666 break;
667 case DH6OPT_LIFETIME:
668 case DH6OPT_CLT_TIME:
669 if (optlen != 4) {
670 printf(" ?)");
671 break;
672 }
673 tp = (u_char *)(dh6o + 1);
674 printf(" %d)", EXTRACT_32BITS(tp));
675 break;
676 case DH6OPT_REMOTE_ID:
677 if (optlen < 4) {
678 printf(" ?)");
679 break;
680 }
681 tp = (u_char *)(dh6o + 1);
682 printf(" %d ", EXTRACT_32BITS(tp));
683 /*
684 * Print hex dump first 10 characters.
685 */
686 for (i = 4; i < optlen && i < 14; i++)
687 printf("%02x", tp[i]);
688 printf("...)");
689 break;
690 case DH6OPT_LQ_QUERY:
691 if (optlen < 17) {
692 printf(" ?)");
693 break;
694 }
695 tp = (u_char *)(dh6o + 1);
696 switch (*tp) {
697 case 1:
698 printf(" by-address");
699 break;
700 case 2:
701 printf(" by-clientID");
702 break;
703 default:
704 printf(" type_%d", (int)*tp);
705 break;
706 }
707 printf(" %s", ip6addr_string(&tp[1]));
708 if (optlen > 17) {
709 /* there are query-options */
710 dhcp6opt_print(tp + 17, tp + optlen);
711 }
712 printf(")");
713 break;
714 case DH6OPT_CLIENT_DATA:
715 tp = (u_char *)(dh6o + 1);
716 if (optlen > 0) {
717 /* there are encapsulated options */
718 dhcp6opt_print(tp, tp + optlen);
719 }
720 printf(")");
721 break;
722 case DH6OPT_LQ_RELAY_DATA:
723 if (optlen < 16) {
724 printf(" ?)");
725 break;
726 }
727 tp = (u_char *)(dh6o + 1);
728 printf(" %s ", ip6addr_string(&tp[0]));
729 /*
730 * Print hex dump first 10 characters.
731 */
732 for (i = 16; i < optlen && i < 26; i++)
733 printf("%02x", tp[i]);
734 printf("...)");
735 break;
736 case DH6OPT_NTP_SERVER:
737 if (optlen < 4) {
738 printf(" ?)");
739 break;
740 }
741 tp = (u_char *)(dh6o + 1);
742 while (tp < cp + sizeof(*dh6o) + optlen - 4) {
743 subopt_code = EXTRACT_16BITS(tp);
744 tp += 2;
745 subopt_len = EXTRACT_16BITS(tp);
746 tp += 2;
747 if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
748 goto trunc;
749 printf(" subopt:%d", subopt_code);
750 switch (subopt_code) {
751 case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
752 case DH6OPT_NTP_SUBOPTION_MC_ADDR:
753 if (subopt_len != 16) {
754 printf(" ?");
755 break;
756 }
757 printf(" %s", ip6addr_string(&tp[0]));
758 break;
759 case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
760 putchar(' ');
761 if (ns_nprint(tp, tp + subopt_len) == NULL)
762 goto trunc;
763 break;
764 default:
765 printf(" ?");
766 break;
767 }
768 tp += subopt_len;
769 }
770 printf(")");
771 break;
772 case DH6OPT_AFTR_NAME:
773 if (optlen < 3) {
774 printf(" ?)");
775 break;
776 }
777 tp = (u_char *)(dh6o + 1);
778 remain_len = optlen;
779 printf(" ");
780 /* Encoding is described in section 3.1 of RFC 1035 */
781 while (remain_len && *tp) {
782 label_len = *tp++;
783 if (label_len < remain_len - 1) {
784 printf("%.*s", label_len, tp);
785 tp += label_len;
786 remain_len -= (label_len + 1);
787 if(*tp) printf(".");
788 } else {
789 printf(" ?");
790 break;
791 }
792 }
793 printf(")");
794 break;
795 default:
796 printf(")");
797 break;
798 }
799
800 cp += sizeof(*dh6o) + optlen;
801 }
802 return;
803
804 trunc:
805 printf("[|dhcp6ext]");
806 }
807
808 /*
809 * Print dhcp6 packets
810 */
811 void
812 dhcp6_print(const u_char *cp, u_int length)
813 {
814 struct dhcp6 *dh6;
815 struct dhcp6_relay *dh6relay;
816 const u_char *ep;
817 u_char *extp;
818 const char *name;
819
820 printf("dhcp6");
821
822 ep = (u_char *)snapend;
823 if (cp + length < ep)
824 ep = cp + length;
825
826 dh6 = (struct dhcp6 *)cp;
827 dh6relay = (struct dhcp6_relay *)cp;
828 TCHECK(dh6->dh6_xid);
829 switch (dh6->dh6_msgtype) {
830 case DH6_SOLICIT:
831 name = "solicit";
832 break;
833 case DH6_ADVERTISE:
834 name = "advertise";
835 break;
836 case DH6_REQUEST:
837 name = "request";
838 break;
839 case DH6_CONFIRM:
840 name = "confirm";
841 break;
842 case DH6_RENEW:
843 name = "renew";
844 break;
845 case DH6_REBIND:
846 name = "rebind";
847 break;
848 case DH6_REPLY:
849 name = "reply";
850 break;
851 case DH6_RELEASE:
852 name = "release";
853 break;
854 case DH6_DECLINE:
855 name = "decline";
856 break;
857 case DH6_RECONFIGURE:
858 name = "reconfigure";
859 break;
860 case DH6_INFORM_REQ:
861 name= "inf-req";
862 break;
863 case DH6_RELAY_FORW:
864 name= "relay-fwd";
865 break;
866 case DH6_RELAY_REPLY:
867 name= "relay-reply";
868 break;
869 case DH6_LEASEQUERY:
870 name= "leasequery";
871 break;
872 case DH6_LQ_REPLY:
873 name= "leasequery-reply";
874 break;
875 default:
876 name = NULL;
877 break;
878 }
879
880 if (!vflag) {
881 if (name)
882 printf(" %s", name);
883 else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
884 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
885 printf(" msgtype-%u", dh6->dh6_msgtype);
886 }
887 return;
888 }
889
890 /* XXX relay agent messages have to be handled differently */
891
892 if (name)
893 printf(" %s (", name); /*)*/
894 else
895 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/
896 if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
897 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
898 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
899 extp = (u_char *)(dh6 + 1);
900 dhcp6opt_print(extp, ep);
901 } else { /* relay messages */
902 struct in6_addr addr6;
903
904 TCHECK(dh6relay->dh6relay_peeraddr);
905
906 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
907 printf("linkaddr=%s", ip6addr_string(&addr6));
908
909 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
910 printf(" peeraddr=%s", ip6addr_string(&addr6));
911
912 dhcp6opt_print((u_char *)(dh6relay + 1), ep);
913 }
914 /*(*/
915 printf(")");
916 return;
917
918 trunc:
919 printf("[|dhcp6]");
920 }