]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
use macros for VAT and WB port numbers
[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 * RFC6334: Dual-Stack Lite option,
40 */
41
42 #ifndef lint
43 static const char rcsid[] _U_ =
44 "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp $";
45 #endif
46
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 #include <tcpdump-stdinc.h>
52
53 #include <stdio.h>
54 #include <string.h>
55
56 #include "interface.h"
57 #include "addrtoname.h"
58 #include "extract.h"
59
60 /* lease duration */
61 #define DHCP6_DURATITION_INFINITE 0xffffffff
62
63 /* Error Values */
64 #define DH6ERR_FAILURE 16
65 #define DH6ERR_AUTHFAIL 17
66 #define DH6ERR_POORLYFORMED 18
67 #define DH6ERR_UNAVAIL 19
68 #define DH6ERR_OPTUNAVAIL 20
69
70 /* Message type */
71 #define DH6_SOLICIT 1
72 #define DH6_ADVERTISE 2
73 #define DH6_REQUEST 3
74 #define DH6_CONFIRM 4
75 #define DH6_RENEW 5
76 #define DH6_REBIND 6
77 #define DH6_REPLY 7
78 #define DH6_RELEASE 8
79 #define DH6_DECLINE 9
80 #define DH6_RECONFIGURE 10
81 #define DH6_INFORM_REQ 11
82 #define DH6_RELAY_FORW 12
83 #define DH6_RELAY_REPLY 13
84 #define DH6_LEASEQUERY 14
85 #define DH6_LQ_REPLY 15
86
87 /* DHCP6 base packet format */
88 struct dhcp6 {
89 union {
90 u_int8_t m;
91 u_int32_t x;
92 } dh6_msgtypexid;
93 /* options follow */
94 };
95 #define dh6_msgtype dh6_msgtypexid.m
96 #define dh6_xid dh6_msgtypexid.x
97 #define DH6_XIDMASK 0x00ffffff
98
99 /* DHCPv6 relay messages */
100 struct dhcp6_relay {
101 u_int8_t dh6relay_msgtype;
102 u_int8_t dh6relay_hcnt;
103 u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */
104 u_int8_t dh6relay_peeraddr[16];
105 /* options follow */
106 };
107
108 /* options */
109 #define DH6OPT_CLIENTID 1
110 #define DH6OPT_SERVERID 2
111 #define DH6OPT_IA_NA 3
112 #define DH6OPT_IA_TA 4
113 #define DH6OPT_IA_ADDR 5
114 #define DH6OPT_ORO 6
115 #define DH6OPT_PREFERENCE 7
116 # define DH6OPT_PREF_MAX 255
117 #define DH6OPT_ELAPSED_TIME 8
118 #define DH6OPT_RELAY_MSG 9
119 /*#define DH6OPT_SERVER_MSG 10 deprecated */
120 #define DH6OPT_AUTH 11
121 # define DH6OPT_AUTHPROTO_DELAYED 2
122 # define DH6OPT_AUTHPROTO_RECONFIG 3
123 # define DH6OPT_AUTHALG_HMACMD5 1
124 # define DH6OPT_AUTHRDM_MONOCOUNTER 0
125 # define DH6OPT_AUTHRECONFIG_KEY 1
126 # define DH6OPT_AUTHRECONFIG_HMACMD5 2
127 #define DH6OPT_UNICAST 12
128 #define DH6OPT_STATUS_CODE 13
129 # define DH6OPT_STCODE_SUCCESS 0
130 # define DH6OPT_STCODE_UNSPECFAIL 1
131 # define DH6OPT_STCODE_NOADDRAVAIL 2
132 # define DH6OPT_STCODE_NOBINDING 3
133 # define DH6OPT_STCODE_NOTONLINK 4
134 # define DH6OPT_STCODE_USEMULTICAST 5
135 # define DH6OPT_STCODE_NOPREFIXAVAIL 6
136 # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
137 # define DH6OPT_STCODE_MALFORMEDQUERY 8
138 # define DH6OPT_STCODE_NOTCONFIGURED 9
139 # define DH6OPT_STCODE_NOTALLOWED 10
140 #define DH6OPT_RAPID_COMMIT 14
141 #define DH6OPT_USER_CLASS 15
142 #define DH6OPT_VENDOR_CLASS 16
143 #define DH6OPT_VENDOR_OPTS 17
144 #define DH6OPT_INTERFACE_ID 18
145 #define DH6OPT_RECONF_MSG 19
146 #define DH6OPT_RECONF_ACCEPT 20
147 #define DH6OPT_SIP_SERVER_D 21
148 #define DH6OPT_SIP_SERVER_A 22
149 #define DH6OPT_DNS 23
150 #define DH6OPT_DNSNAME 24
151 #define DH6OPT_IA_PD 25
152 #define DH6OPT_IA_PD_PREFIX 26
153 #define DH6OPT_NIS_SERVERS 27
154 #define DH6OPT_NISP_SERVERS 28
155 #define DH6OPT_NIS_NAME 29
156 #define DH6OPT_NISP_NAME 30
157 #define DH6OPT_NTP_SERVERS 31
158 #define DH6OPT_LIFETIME 32
159 #define DH6OPT_BCMCS_SERVER_D 33
160 #define DH6OPT_BCMCS_SERVER_A 34
161 #define DH6OPT_GEOCONF_CIVIC 36
162 #define DH6OPT_REMOTE_ID 37
163 #define DH6OPT_SUBSCRIBER_ID 38
164 #define DH6OPT_CLIENT_FQDN 39
165 #define DH6OPT_PANA_AGENT 40
166 #define DH6OPT_NEW_POSIX_TIMEZONE 41
167 #define DH6OPT_NEW_TZDB_TIMEZONE 42
168 #define DH6OPT_ERO 43
169 #define DH6OPT_LQ_QUERY 44
170 #define DH6OPT_CLIENT_DATA 45
171 #define DH6OPT_CLT_TIME 46
172 #define DH6OPT_LQ_RELAY_DATA 47
173 #define DH6OPT_LQ_CLIENT_LINK 48
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:
234 return "DNS-server";
235 case DH6OPT_DNSNAME:
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_NTP_SERVERS:
242 return "NTP-server";
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_AFTR_NAME:
284 return "AFTR-Name";
285 default:
286 snprintf(genstr, sizeof(genstr), "opt_%d", type);
287 return(genstr);
288 }
289 }
290
291 static const char *
292 dhcp6stcode(int code)
293 {
294 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
295
296 if (code > 255)
297 return "INVALID code";
298
299 switch(code) {
300 case DH6OPT_STCODE_SUCCESS:
301 return "success";
302 case DH6OPT_STCODE_UNSPECFAIL:
303 return "unspec failure";
304 case DH6OPT_STCODE_NOADDRAVAIL:
305 return "no addresses";
306 case DH6OPT_STCODE_NOBINDING:
307 return "no binding";
308 case DH6OPT_STCODE_NOTONLINK:
309 return "not on-link";
310 case DH6OPT_STCODE_USEMULTICAST:
311 return "use multicast";
312 case DH6OPT_STCODE_NOPREFIXAVAIL:
313 return "no prefixes";
314 case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
315 return "unknown query type";
316 case DH6OPT_STCODE_MALFORMEDQUERY:
317 return "malformed query";
318 case DH6OPT_STCODE_NOTCONFIGURED:
319 return "not configured";
320 case DH6OPT_STCODE_NOTALLOWED:
321 return "not allowed";
322 default:
323 snprintf(genstr, sizeof(genstr), "code%d", code);
324 return(genstr);
325 }
326 }
327
328 static void
329 dhcp6opt_print(const u_char *cp, const u_char *ep)
330 {
331 struct dhcp6opt *dh6o;
332 u_char *tp;
333 size_t i;
334 u_int16_t opttype;
335 size_t optlen;
336 u_int8_t auth_proto;
337 u_int authinfolen, authrealmlen;
338 int remain_len; /* Length of remaining options */
339 int label_len; /* Label length */
340
341 if (cp == ep)
342 return;
343 while (cp < ep) {
344 if (ep < cp + sizeof(*dh6o))
345 goto trunc;
346 dh6o = (struct dhcp6opt *)cp;
347 TCHECK(*dh6o);
348 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
349 if (ep < cp + sizeof(*dh6o) + optlen)
350 goto trunc;
351 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
352 printf(" (%s", dhcp6opt_name(opttype));
353 switch (opttype) {
354 case DH6OPT_CLIENTID:
355 case DH6OPT_SERVERID:
356 if (optlen < 2) {
357 /*(*/
358 printf(" ?)");
359 break;
360 }
361 tp = (u_char *)(dh6o + 1);
362 switch (EXTRACT_16BITS(tp)) {
363 case 1:
364 if (optlen >= 2 + 6) {
365 printf(" hwaddr/time type %u time %u ",
366 EXTRACT_16BITS(&tp[2]),
367 EXTRACT_32BITS(&tp[4]));
368 for (i = 8; i < optlen; i++)
369 printf("%02x", tp[i]);
370 /*(*/
371 printf(")");
372 } else {
373 /*(*/
374 printf(" ?)");
375 }
376 break;
377 case 2:
378 if (optlen >= 2 + 8) {
379 printf(" vid ");
380 for (i = 2; i < 2 + 8; i++)
381 printf("%02x", tp[i]);
382 /*(*/
383 printf(")");
384 } else {
385 /*(*/
386 printf(" ?)");
387 }
388 break;
389 case 3:
390 if (optlen >= 2 + 2) {
391 printf(" hwaddr type %u ",
392 EXTRACT_16BITS(&tp[2]));
393 for (i = 4; i < optlen; i++)
394 printf("%02x", tp[i]);
395 /*(*/
396 printf(")");
397 } else {
398 /*(*/
399 printf(" ?)");
400 }
401 break;
402 default:
403 printf(" type %d)", EXTRACT_16BITS(tp));
404 break;
405 }
406 break;
407 case DH6OPT_IA_ADDR:
408 if (optlen < 24) {
409 /*(*/
410 printf(" ?)");
411 break;
412 }
413 tp = (u_char *)(dh6o + 1);
414 printf(" %s", ip6addr_string(&tp[0]));
415 printf(" pltime:%u vltime:%u",
416 EXTRACT_32BITS(&tp[16]),
417 EXTRACT_32BITS(&tp[20]));
418 if (optlen > 24) {
419 /* there are sub-options */
420 dhcp6opt_print(tp + 24, tp + optlen);
421 }
422 printf(")");
423 break;
424 case DH6OPT_ORO:
425 case DH6OPT_ERO:
426 if (optlen % 2) {
427 printf(" ?)");
428 break;
429 }
430 tp = (u_char *)(dh6o + 1);
431 for (i = 0; i < optlen; i += 2) {
432 printf(" %s",
433 dhcp6opt_name(EXTRACT_16BITS(&tp[i])));
434 }
435 printf(")");
436 break;
437 case DH6OPT_PREFERENCE:
438 if (optlen != 1) {
439 printf(" ?)");
440 break;
441 }
442 tp = (u_char *)(dh6o + 1);
443 printf(" %d)", *tp);
444 break;
445 case DH6OPT_ELAPSED_TIME:
446 if (optlen != 2) {
447 printf(" ?)");
448 break;
449 }
450 tp = (u_char *)(dh6o + 1);
451 printf(" %d)", EXTRACT_16BITS(tp));
452 break;
453 case DH6OPT_RELAY_MSG:
454 printf(" (");
455 tp = (u_char *)(dh6o + 1);
456 dhcp6_print(tp, optlen);
457 printf(")");
458 break;
459 case DH6OPT_AUTH:
460 if (optlen < 11) {
461 printf(" ?)");
462 break;
463 }
464 tp = (u_char *)(dh6o + 1);
465 auth_proto = *tp;
466 switch (auth_proto) {
467 case DH6OPT_AUTHPROTO_DELAYED:
468 printf(" proto: delayed");
469 break;
470 case DH6OPT_AUTHPROTO_RECONFIG:
471 printf(" proto: reconfigure");
472 break;
473 default:
474 printf(" proto: %d", auth_proto);
475 break;
476 }
477 tp++;
478 switch (*tp) {
479 case DH6OPT_AUTHALG_HMACMD5:
480 /* XXX: may depend on the protocol */
481 printf(", alg: HMAC-MD5");
482 break;
483 default:
484 printf(", alg: %d", *tp);
485 break;
486 }
487 tp++;
488 switch (*tp) {
489 case DH6OPT_AUTHRDM_MONOCOUNTER:
490 printf(", RDM: mono");
491 break;
492 default:
493 printf(", RDM: %d", *tp);
494 break;
495 }
496 tp++;
497 printf(", RD:");
498 for (i = 0; i < 4; i++, tp += 2)
499 printf(" %04x", EXTRACT_16BITS(tp));
500
501 /* protocol dependent part */
502 authinfolen = optlen - 11;
503 switch (auth_proto) {
504 case DH6OPT_AUTHPROTO_DELAYED:
505 if (authinfolen == 0)
506 break;
507 if (authinfolen < 20) {
508 printf(" ??");
509 break;
510 }
511 authrealmlen = authinfolen - 20;
512 if (authrealmlen > 0) {
513 printf(", realm: ");
514 }
515 for (i = 0; i < authrealmlen; i++, tp++)
516 printf("%02x", *tp);
517 printf(", key ID: %08x", EXTRACT_32BITS(tp));
518 tp += 4;
519 printf(", HMAC-MD5:");
520 for (i = 0; i < 4; i++, tp+= 4)
521 printf(" %08x", EXTRACT_32BITS(tp));
522 break;
523 case DH6OPT_AUTHPROTO_RECONFIG:
524 if (authinfolen != 17) {
525 printf(" ??");
526 break;
527 }
528 switch (*tp++) {
529 case DH6OPT_AUTHRECONFIG_KEY:
530 printf(" reconfig-key");
531 break;
532 case DH6OPT_AUTHRECONFIG_HMACMD5:
533 printf(" type: HMAC-MD5");
534 break;
535 default:
536 printf(" type: ??");
537 break;
538 }
539 printf(" value:");
540 for (i = 0; i < 4; i++, tp+= 4)
541 printf(" %08x", EXTRACT_32BITS(tp));
542 break;
543 default:
544 printf(" ??");
545 break;
546 }
547
548 printf(")");
549 break;
550 case DH6OPT_RAPID_COMMIT: /* nothing todo */
551 printf(")");
552 break;
553 case DH6OPT_INTERFACE_ID:
554 case DH6OPT_SUBSCRIBER_ID:
555 /*
556 * Since we cannot predict the encoding, print hex dump
557 * at most 10 characters.
558 */
559 tp = (u_char *)(dh6o + 1);
560 printf(" ");
561 for (i = 0; i < optlen && i < 10; i++)
562 printf("%02x", tp[i]);
563 printf("...)");
564 break;
565 case DH6OPT_RECONF_MSG:
566 tp = (u_char *)(dh6o + 1);
567 switch (*tp) {
568 case DH6_RENEW:
569 printf(" for renew)");
570 break;
571 case DH6_INFORM_REQ:
572 printf(" for inf-req)");
573 break;
574 default:
575 printf(" for ?\?\?(%02x))", *tp);
576 break;
577 }
578 break;
579 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
580 printf(")");
581 break;
582 case DH6OPT_SIP_SERVER_A:
583 case DH6OPT_DNS:
584 case DH6OPT_NTP_SERVERS:
585 case DH6OPT_NIS_SERVERS:
586 case DH6OPT_NISP_SERVERS:
587 case DH6OPT_BCMCS_SERVER_A:
588 case DH6OPT_PANA_AGENT:
589 case DH6OPT_LQ_CLIENT_LINK:
590 if (optlen % 16) {
591 printf(" ?)");
592 break;
593 }
594 tp = (u_char *)(dh6o + 1);
595 for (i = 0; i < optlen; i += 16)
596 printf(" %s", ip6addr_string(&tp[i]));
597 printf(")");
598 break;
599 case DH6OPT_STATUS_CODE:
600 if (optlen < 2) {
601 printf(" ?)");
602 break;
603 }
604 tp = (u_char *)(dh6o + 1);
605 printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0])));
606 break;
607 case DH6OPT_IA_NA:
608 case DH6OPT_IA_PD:
609 if (optlen < 12) {
610 printf(" ?)");
611 break;
612 }
613 tp = (u_char *)(dh6o + 1);
614 printf(" IAID:%u T1:%u T2:%u",
615 EXTRACT_32BITS(&tp[0]),
616 EXTRACT_32BITS(&tp[4]),
617 EXTRACT_32BITS(&tp[8]));
618 if (optlen > 12) {
619 /* there are sub-options */
620 dhcp6opt_print(tp + 12, tp + optlen);
621 }
622 printf(")");
623 break;
624 case DH6OPT_IA_TA:
625 if (optlen < 4) {
626 printf(" ?)");
627 break;
628 }
629 tp = (u_char *)(dh6o + 1);
630 printf(" IAID:%u", EXTRACT_32BITS(tp));
631 if (optlen > 4) {
632 /* there are sub-options */
633 dhcp6opt_print(tp + 4, tp + optlen);
634 }
635 printf(")");
636 break;
637 case DH6OPT_IA_PD_PREFIX:
638 if (optlen < 25) {
639 printf(" ?)");
640 break;
641 }
642 tp = (u_char *)(dh6o + 1);
643 printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]);
644 printf(" pltime:%u vltime:%u",
645 EXTRACT_32BITS(&tp[0]),
646 EXTRACT_32BITS(&tp[4]));
647 if (optlen > 25) {
648 /* there are sub-options */
649 dhcp6opt_print(tp + 25, tp + optlen);
650 }
651 printf(")");
652 break;
653 case DH6OPT_LIFETIME:
654 case DH6OPT_CLT_TIME:
655 if (optlen != 4) {
656 printf(" ?)");
657 break;
658 }
659 tp = (u_char *)(dh6o + 1);
660 printf(" %d)", EXTRACT_32BITS(tp));
661 break;
662 case DH6OPT_REMOTE_ID:
663 if (optlen < 4) {
664 printf(" ?)");
665 break;
666 }
667 tp = (u_char *)(dh6o + 1);
668 printf(" %d ", EXTRACT_32BITS(tp));
669 /*
670 * Print hex dump first 10 characters.
671 */
672 for (i = 4; i < optlen && i < 14; i++)
673 printf("%02x", tp[i]);
674 printf("...)");
675 break;
676 case DH6OPT_LQ_QUERY:
677 if (optlen < 17) {
678 printf(" ?)");
679 break;
680 }
681 tp = (u_char *)(dh6o + 1);
682 switch (*tp) {
683 case 1:
684 printf(" by-address");
685 break;
686 case 2:
687 printf(" by-clientID");
688 break;
689 default:
690 printf(" type_%d", (int)*tp);
691 break;
692 }
693 printf(" %s", ip6addr_string(&tp[1]));
694 if (optlen > 17) {
695 /* there are query-options */
696 dhcp6opt_print(tp + 17, tp + optlen);
697 }
698 printf(")");
699 break;
700 case DH6OPT_CLIENT_DATA:
701 tp = (u_char *)(dh6o + 1);
702 if (optlen > 0) {
703 /* there are encapsulated options */
704 dhcp6opt_print(tp, tp + optlen);
705 }
706 printf(")");
707 break;
708 case DH6OPT_LQ_RELAY_DATA:
709 if (optlen < 16) {
710 printf(" ?)");
711 break;
712 }
713 tp = (u_char *)(dh6o + 1);
714 printf(" %s ", ip6addr_string(&tp[0]));
715 /*
716 * Print hex dump first 10 characters.
717 */
718 for (i = 16; i < optlen && i < 26; i++)
719 printf("%02x", tp[i]);
720 printf("...)");
721 break;
722 case DH6OPT_AFTR_NAME:
723 if (optlen < 3) {
724 printf(" ?)");
725 break;
726 }
727 tp = (u_char *)(dh6o + 1);
728 remain_len = optlen;
729 printf(" ");
730 /* Encoding is described in section 3.1 of RFC 1035 */
731 while (remain_len && *tp) {
732 label_len = *tp++;
733 if (label_len < remain_len - 1) {
734 printf("%.*s", label_len, tp);
735 tp += label_len;
736 remain_len -= (label_len + 1);
737 if(*tp) printf(".");
738 } else {
739 printf(" ?");
740 break;
741 }
742 }
743 printf(")");
744 break;
745 default:
746 printf(")");
747 break;
748 }
749
750 cp += sizeof(*dh6o) + optlen;
751 }
752 return;
753
754 trunc:
755 printf("[|dhcp6ext]");
756 }
757
758 /*
759 * Print dhcp6 packets
760 */
761 void
762 dhcp6_print(const u_char *cp, u_int length)
763 {
764 struct dhcp6 *dh6;
765 struct dhcp6_relay *dh6relay;
766 const u_char *ep;
767 u_char *extp;
768 const char *name;
769
770 printf("dhcp6");
771
772 ep = (u_char *)snapend;
773 if (cp + length < ep)
774 ep = cp + length;
775
776 dh6 = (struct dhcp6 *)cp;
777 dh6relay = (struct dhcp6_relay *)cp;
778 TCHECK(dh6->dh6_xid);
779 switch (dh6->dh6_msgtype) {
780 case DH6_SOLICIT:
781 name = "solicit";
782 break;
783 case DH6_ADVERTISE:
784 name = "advertise";
785 break;
786 case DH6_REQUEST:
787 name = "request";
788 break;
789 case DH6_CONFIRM:
790 name = "confirm";
791 break;
792 case DH6_RENEW:
793 name = "renew";
794 break;
795 case DH6_REBIND:
796 name = "rebind";
797 break;
798 case DH6_REPLY:
799 name = "reply";
800 break;
801 case DH6_RELEASE:
802 name = "release";
803 break;
804 case DH6_DECLINE:
805 name = "decline";
806 break;
807 case DH6_RECONFIGURE:
808 name = "reconfigure";
809 break;
810 case DH6_INFORM_REQ:
811 name= "inf-req";
812 break;
813 case DH6_RELAY_FORW:
814 name= "relay-fwd";
815 break;
816 case DH6_RELAY_REPLY:
817 name= "relay-reply";
818 break;
819 case DH6_LEASEQUERY:
820 name= "leasequery";
821 break;
822 case DH6_LQ_REPLY:
823 name= "leasequery-reply";
824 break;
825 default:
826 name = NULL;
827 break;
828 }
829
830 if (!vflag) {
831 if (name)
832 printf(" %s", name);
833 else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
834 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
835 printf(" msgtype-%u", dh6->dh6_msgtype);
836 }
837 return;
838 }
839
840 /* XXX relay agent messages have to be handled differently */
841
842 if (name)
843 printf(" %s (", name); /*)*/
844 else
845 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/
846 if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
847 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
848 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
849 extp = (u_char *)(dh6 + 1);
850 dhcp6opt_print(extp, ep);
851 } else { /* relay messages */
852 struct in6_addr addr6;
853
854 TCHECK(dh6relay->dh6relay_peeraddr);
855
856 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
857 printf("linkaddr=%s", ip6addr_string(&addr6));
858
859 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
860 printf(" peeraddr=%s", ip6addr_string(&addr6));
861
862 dhcp6opt_print((u_char *)(dh6relay + 1), ep);
863 }
864 /*(*/
865 printf(")");
866 return;
867
868 trunc:
869 printf("[|dhcp6]");
870 }