]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
cd7a588ed0103be931ea7abb6c700cfc38f0b168
[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 #define NETDISSECT_REWORKED
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include <tcpdump-stdinc.h>
49
50 #include <stdio.h>
51 #include <string.h>
52
53 #include "interface.h"
54 #include "addrtoname.h"
55 #include "extract.h"
56
57 /* lease duration */
58 #define DHCP6_DURATION_INFINITE 0xffffffff
59
60 /* Error Values */
61 #define DH6ERR_FAILURE 16
62 #define DH6ERR_AUTHFAIL 17
63 #define DH6ERR_POORLYFORMED 18
64 #define DH6ERR_UNAVAIL 19
65 #define DH6ERR_OPTUNAVAIL 20
66
67 /* Message type */
68 #define DH6_SOLICIT 1
69 #define DH6_ADVERTISE 2
70 #define DH6_REQUEST 3
71 #define DH6_CONFIRM 4
72 #define DH6_RENEW 5
73 #define DH6_REBIND 6
74 #define DH6_REPLY 7
75 #define DH6_RELEASE 8
76 #define DH6_DECLINE 9
77 #define DH6_RECONFIGURE 10
78 #define DH6_INFORM_REQ 11
79 #define DH6_RELAY_FORW 12
80 #define DH6_RELAY_REPLY 13
81 #define DH6_LEASEQUERY 14
82 #define DH6_LQ_REPLY 15
83
84 /* DHCP6 base packet format */
85 struct dhcp6 {
86 union {
87 u_int8_t m;
88 u_int32_t x;
89 } dh6_msgtypexid;
90 /* options follow */
91 };
92 #define dh6_msgtype dh6_msgtypexid.m
93 #define dh6_xid dh6_msgtypexid.x
94 #define DH6_XIDMASK 0x00ffffff
95
96 /* DHCPv6 relay messages */
97 struct dhcp6_relay {
98 u_int8_t dh6relay_msgtype;
99 u_int8_t dh6relay_hcnt;
100 u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */
101 u_int8_t dh6relay_peeraddr[16];
102 /* options follow */
103 };
104
105 /* options */
106 #define DH6OPT_CLIENTID 1
107 #define DH6OPT_SERVERID 2
108 #define DH6OPT_IA_NA 3
109 #define DH6OPT_IA_TA 4
110 #define DH6OPT_IA_ADDR 5
111 #define DH6OPT_ORO 6
112 #define DH6OPT_PREFERENCE 7
113 # define DH6OPT_PREF_MAX 255
114 #define DH6OPT_ELAPSED_TIME 8
115 #define DH6OPT_RELAY_MSG 9
116 /*#define DH6OPT_SERVER_MSG 10 deprecated */
117 #define DH6OPT_AUTH 11
118 # define DH6OPT_AUTHPROTO_DELAYED 2
119 # define DH6OPT_AUTHPROTO_RECONFIG 3
120 # define DH6OPT_AUTHALG_HMACMD5 1
121 # define DH6OPT_AUTHRDM_MONOCOUNTER 0
122 # define DH6OPT_AUTHRECONFIG_KEY 1
123 # define DH6OPT_AUTHRECONFIG_HMACMD5 2
124 #define DH6OPT_UNICAST 12
125 #define DH6OPT_STATUS_CODE 13
126 # define DH6OPT_STCODE_SUCCESS 0
127 # define DH6OPT_STCODE_UNSPECFAIL 1
128 # define DH6OPT_STCODE_NOADDRAVAIL 2
129 # define DH6OPT_STCODE_NOBINDING 3
130 # define DH6OPT_STCODE_NOTONLINK 4
131 # define DH6OPT_STCODE_USEMULTICAST 5
132 # define DH6OPT_STCODE_NOPREFIXAVAIL 6
133 # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
134 # define DH6OPT_STCODE_MALFORMEDQUERY 8
135 # define DH6OPT_STCODE_NOTCONFIGURED 9
136 # define DH6OPT_STCODE_NOTALLOWED 10
137 #define DH6OPT_RAPID_COMMIT 14
138 #define DH6OPT_USER_CLASS 15
139 #define DH6OPT_VENDOR_CLASS 16
140 #define DH6OPT_VENDOR_OPTS 17
141 #define DH6OPT_INTERFACE_ID 18
142 #define DH6OPT_RECONF_MSG 19
143 #define DH6OPT_RECONF_ACCEPT 20
144 #define DH6OPT_SIP_SERVER_D 21
145 #define DH6OPT_SIP_SERVER_A 22
146 #define DH6OPT_DNS_SERVERS 23
147 #define DH6OPT_DOMAIN_LIST 24
148 #define DH6OPT_IA_PD 25
149 #define DH6OPT_IA_PD_PREFIX 26
150 #define DH6OPT_NIS_SERVERS 27
151 #define DH6OPT_NISP_SERVERS 28
152 #define DH6OPT_NIS_NAME 29
153 #define DH6OPT_NISP_NAME 30
154 #define DH6OPT_SNTP_SERVERS 31
155 #define DH6OPT_LIFETIME 32
156 #define DH6OPT_BCMCS_SERVER_D 33
157 #define DH6OPT_BCMCS_SERVER_A 34
158 #define DH6OPT_GEOCONF_CIVIC 36
159 #define DH6OPT_REMOTE_ID 37
160 #define DH6OPT_SUBSCRIBER_ID 38
161 #define DH6OPT_CLIENT_FQDN 39
162 #define DH6OPT_PANA_AGENT 40
163 #define DH6OPT_NEW_POSIX_TIMEZONE 41
164 #define DH6OPT_NEW_TZDB_TIMEZONE 42
165 #define DH6OPT_ERO 43
166 #define DH6OPT_LQ_QUERY 44
167 #define DH6OPT_CLIENT_DATA 45
168 #define DH6OPT_CLT_TIME 46
169 #define DH6OPT_LQ_RELAY_DATA 47
170 #define DH6OPT_LQ_CLIENT_LINK 48
171 #define DH6OPT_NTP_SERVER 56
172 # define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
173 # define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
174 # define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
175 #define DH6OPT_AFTR_NAME 64
176
177 struct dhcp6opt {
178 u_int16_t dh6opt_type;
179 u_int16_t dh6opt_len;
180 /* type-dependent data follows */
181 };
182
183 static const char *
184 dhcp6opt_name(int type)
185 {
186 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
187
188 switch(type) {
189 case DH6OPT_CLIENTID:
190 return "client-ID";
191 case DH6OPT_SERVERID:
192 return "server-ID";
193 case DH6OPT_IA_NA:
194 return "IA_NA";
195 case DH6OPT_IA_TA:
196 return "IA_TA";
197 case DH6OPT_IA_ADDR:
198 return "IA_ADDR";
199 case DH6OPT_ORO:
200 return "option-request";
201 case DH6OPT_PREFERENCE:
202 return "preference";
203 case DH6OPT_ELAPSED_TIME:
204 return "elapsed-time";
205 case DH6OPT_RELAY_MSG:
206 return "relay-message";
207 case DH6OPT_AUTH:
208 return "authentication";
209 case DH6OPT_UNICAST:
210 return "server-unicast";
211 case DH6OPT_STATUS_CODE:
212 return "status-code";
213 case DH6OPT_RAPID_COMMIT:
214 return "rapid-commit";
215 case DH6OPT_USER_CLASS:
216 return "user-class";
217 case DH6OPT_VENDOR_CLASS:
218 return "vendor-class";
219 case DH6OPT_VENDOR_OPTS:
220 return "vendor-specific-info";
221 case DH6OPT_INTERFACE_ID:
222 return "interface-ID";
223 case DH6OPT_RECONF_MSG:
224 return "reconfigure-message";
225 case DH6OPT_RECONF_ACCEPT:
226 return "reconfigure-accept";
227 case DH6OPT_SIP_SERVER_D:
228 return "SIP-servers-domain";
229 case DH6OPT_SIP_SERVER_A:
230 return "SIP-servers-address";
231 case DH6OPT_DNS_SERVERS:
232 return "DNS-server";
233 case DH6OPT_DOMAIN_LIST:
234 return "DNS-search-list";
235 case DH6OPT_IA_PD:
236 return "IA_PD";
237 case DH6OPT_IA_PD_PREFIX:
238 return "IA_PD-prefix";
239 case DH6OPT_SNTP_SERVERS:
240 return "SNTP-servers";
241 case DH6OPT_LIFETIME:
242 return "lifetime";
243 case DH6OPT_NIS_SERVERS:
244 return "NIS-server";
245 case DH6OPT_NISP_SERVERS:
246 return "NIS+-server";
247 case DH6OPT_NIS_NAME:
248 return "NIS-domain-name";
249 case DH6OPT_NISP_NAME:
250 return "NIS+-domain-name";
251 case DH6OPT_BCMCS_SERVER_D:
252 return "BCMCS-domain-name";
253 case DH6OPT_BCMCS_SERVER_A:
254 return "BCMCS-server";
255 case DH6OPT_GEOCONF_CIVIC:
256 return "Geoconf-Civic";
257 case DH6OPT_REMOTE_ID:
258 return "Remote-ID";
259 case DH6OPT_SUBSCRIBER_ID:
260 return "Subscriber-ID";
261 case DH6OPT_CLIENT_FQDN:
262 return "Client-FQDN";
263 case DH6OPT_PANA_AGENT:
264 return "PANA-agent";
265 case DH6OPT_NEW_POSIX_TIMEZONE:
266 return "POSIX-timezone";
267 case DH6OPT_NEW_TZDB_TIMEZONE:
268 return "POSIX-tz-database";
269 case DH6OPT_ERO:
270 return "Echo-request-option";
271 case DH6OPT_LQ_QUERY:
272 return "Lease-query";
273 case DH6OPT_CLIENT_DATA:
274 return "LQ-client-data";
275 case DH6OPT_CLT_TIME:
276 return "Clt-time";
277 case DH6OPT_LQ_RELAY_DATA:
278 return "LQ-relay-data";
279 case DH6OPT_LQ_CLIENT_LINK:
280 return "LQ-client-link";
281 case DH6OPT_NTP_SERVER:
282 return "NTP-server";
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(netdissect_options *ndo,
330 const u_char *cp, const u_char *ep)
331 {
332 const struct dhcp6opt *dh6o;
333 const u_char *tp;
334 size_t i;
335 u_int16_t opttype;
336 size_t optlen;
337 u_int8_t auth_proto;
338 u_int authinfolen, authrealmlen;
339 int remain_len; /* Length of remaining options */
340 int label_len; /* Label length */
341 u_int16_t subopt_code;
342 u_int16_t subopt_len;
343
344 if (cp == ep)
345 return;
346 while (cp < ep) {
347 if (ep < cp + sizeof(*dh6o))
348 goto trunc;
349 dh6o = (struct dhcp6opt *)cp;
350 ND_TCHECK(*dh6o);
351 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
352 if (ep < cp + sizeof(*dh6o) + optlen)
353 goto trunc;
354 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
355 ND_PRINT((ndo, " (%s", dhcp6opt_name(opttype)));
356 switch (opttype) {
357 case DH6OPT_CLIENTID:
358 case DH6OPT_SERVERID:
359 if (optlen < 2) {
360 /*(*/
361 ND_PRINT((ndo, " ?)"));
362 break;
363 }
364 tp = (u_char *)(dh6o + 1);
365 switch (EXTRACT_16BITS(tp)) {
366 case 1:
367 if (optlen >= 2 + 6) {
368 ND_PRINT((ndo, " hwaddr/time type %u time %u ",
369 EXTRACT_16BITS(&tp[2]),
370 EXTRACT_32BITS(&tp[4])));
371 for (i = 8; i < optlen; i++)
372 ND_PRINT((ndo, "%02x", tp[i]));
373 /*(*/
374 ND_PRINT((ndo, ")"));
375 } else {
376 /*(*/
377 ND_PRINT((ndo, " ?)"));
378 }
379 break;
380 case 2:
381 if (optlen >= 2 + 8) {
382 ND_PRINT((ndo, " vid "));
383 for (i = 2; i < 2 + 8; i++)
384 ND_PRINT((ndo, "%02x", tp[i]));
385 /*(*/
386 ND_PRINT((ndo, ")"));
387 } else {
388 /*(*/
389 ND_PRINT((ndo, " ?)"));
390 }
391 break;
392 case 3:
393 if (optlen >= 2 + 2) {
394 ND_PRINT((ndo, " hwaddr type %u ",
395 EXTRACT_16BITS(&tp[2])));
396 for (i = 4; i < optlen; i++)
397 ND_PRINT((ndo, "%02x", tp[i]));
398 /*(*/
399 ND_PRINT((ndo, ")"));
400 } else {
401 /*(*/
402 ND_PRINT((ndo, " ?)"));
403 }
404 break;
405 default:
406 ND_PRINT((ndo, " type %d)", EXTRACT_16BITS(tp)));
407 break;
408 }
409 break;
410 case DH6OPT_IA_ADDR:
411 if (optlen < 24) {
412 /*(*/
413 ND_PRINT((ndo, " ?)"));
414 break;
415 }
416 tp = (u_char *)(dh6o + 1);
417 ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0])));
418 ND_PRINT((ndo, " pltime:%u vltime:%u",
419 EXTRACT_32BITS(&tp[16]),
420 EXTRACT_32BITS(&tp[20])));
421 if (optlen > 24) {
422 /* there are sub-options */
423 dhcp6opt_print(ndo, tp + 24, tp + optlen);
424 }
425 ND_PRINT((ndo, ")"));
426 break;
427 case DH6OPT_ORO:
428 case DH6OPT_ERO:
429 if (optlen % 2) {
430 ND_PRINT((ndo, " ?)"));
431 break;
432 }
433 tp = (u_char *)(dh6o + 1);
434 for (i = 0; i < optlen; i += 2) {
435 ND_PRINT((ndo, " %s",
436 dhcp6opt_name(EXTRACT_16BITS(&tp[i]))));
437 }
438 ND_PRINT((ndo, ")"));
439 break;
440 case DH6OPT_PREFERENCE:
441 if (optlen != 1) {
442 ND_PRINT((ndo, " ?)"));
443 break;
444 }
445 tp = (u_char *)(dh6o + 1);
446 ND_PRINT((ndo, " %d)", *tp));
447 break;
448 case DH6OPT_ELAPSED_TIME:
449 if (optlen != 2) {
450 ND_PRINT((ndo, " ?)"));
451 break;
452 }
453 tp = (u_char *)(dh6o + 1);
454 ND_PRINT((ndo, " %d)", EXTRACT_16BITS(tp)));
455 break;
456 case DH6OPT_RELAY_MSG:
457 ND_PRINT((ndo, " ("));
458 tp = (u_char *)(dh6o + 1);
459 dhcp6_print(ndo, tp, optlen);
460 ND_PRINT((ndo, ")"));
461 break;
462 case DH6OPT_AUTH:
463 if (optlen < 11) {
464 ND_PRINT((ndo, " ?)"));
465 break;
466 }
467 tp = (u_char *)(dh6o + 1);
468 auth_proto = *tp;
469 switch (auth_proto) {
470 case DH6OPT_AUTHPROTO_DELAYED:
471 ND_PRINT((ndo, " proto: delayed"));
472 break;
473 case DH6OPT_AUTHPROTO_RECONFIG:
474 ND_PRINT((ndo, " proto: reconfigure"));
475 break;
476 default:
477 ND_PRINT((ndo, " proto: %d", auth_proto));
478 break;
479 }
480 tp++;
481 switch (*tp) {
482 case DH6OPT_AUTHALG_HMACMD5:
483 /* XXX: may depend on the protocol */
484 ND_PRINT((ndo, ", alg: HMAC-MD5"));
485 break;
486 default:
487 ND_PRINT((ndo, ", alg: %d", *tp));
488 break;
489 }
490 tp++;
491 switch (*tp) {
492 case DH6OPT_AUTHRDM_MONOCOUNTER:
493 ND_PRINT((ndo, ", RDM: mono"));
494 break;
495 default:
496 ND_PRINT((ndo, ", RDM: %d", *tp));
497 break;
498 }
499 tp++;
500 ND_PRINT((ndo, ", RD:"));
501 for (i = 0; i < 4; i++, tp += 2)
502 ND_PRINT((ndo, " %04x", EXTRACT_16BITS(tp)));
503
504 /* protocol dependent part */
505 authinfolen = optlen - 11;
506 switch (auth_proto) {
507 case DH6OPT_AUTHPROTO_DELAYED:
508 if (authinfolen == 0)
509 break;
510 if (authinfolen < 20) {
511 ND_PRINT((ndo, " ??"));
512 break;
513 }
514 authrealmlen = authinfolen - 20;
515 if (authrealmlen > 0) {
516 ND_PRINT((ndo, ", realm: "));
517 }
518 for (i = 0; i < authrealmlen; i++, tp++)
519 ND_PRINT((ndo, "%02x", *tp));
520 ND_PRINT((ndo, ", key ID: %08x", EXTRACT_32BITS(tp)));
521 tp += 4;
522 ND_PRINT((ndo, ", HMAC-MD5:"));
523 for (i = 0; i < 4; i++, tp+= 4)
524 ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
525 break;
526 case DH6OPT_AUTHPROTO_RECONFIG:
527 if (authinfolen != 17) {
528 ND_PRINT((ndo, " ??"));
529 break;
530 }
531 switch (*tp++) {
532 case DH6OPT_AUTHRECONFIG_KEY:
533 ND_PRINT((ndo, " reconfig-key"));
534 break;
535 case DH6OPT_AUTHRECONFIG_HMACMD5:
536 ND_PRINT((ndo, " type: HMAC-MD5"));
537 break;
538 default:
539 ND_PRINT((ndo, " type: ??"));
540 break;
541 }
542 ND_PRINT((ndo, " value:"));
543 for (i = 0; i < 4; i++, tp+= 4)
544 ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
545 break;
546 default:
547 ND_PRINT((ndo, " ??"));
548 break;
549 }
550
551 ND_PRINT((ndo, ")"));
552 break;
553 case DH6OPT_RAPID_COMMIT: /* nothing todo */
554 ND_PRINT((ndo, ")"));
555 break;
556 case DH6OPT_INTERFACE_ID:
557 case DH6OPT_SUBSCRIBER_ID:
558 /*
559 * Since we cannot predict the encoding, print hex dump
560 * at most 10 characters.
561 */
562 tp = (u_char *)(dh6o + 1);
563 ND_PRINT((ndo, " "));
564 for (i = 0; i < optlen && i < 10; i++)
565 ND_PRINT((ndo, "%02x", tp[i]));
566 ND_PRINT((ndo, "...)"));
567 break;
568 case DH6OPT_RECONF_MSG:
569 tp = (u_char *)(dh6o + 1);
570 switch (*tp) {
571 case DH6_RENEW:
572 ND_PRINT((ndo, " for renew)"));
573 break;
574 case DH6_INFORM_REQ:
575 ND_PRINT((ndo, " for inf-req)"));
576 break;
577 default:
578 ND_PRINT((ndo, " for ?\?\?(%02x))", *tp));
579 break;
580 }
581 break;
582 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
583 ND_PRINT((ndo, ")"));
584 break;
585 case DH6OPT_SIP_SERVER_A:
586 case DH6OPT_DNS_SERVERS:
587 case DH6OPT_SNTP_SERVERS:
588 case DH6OPT_NIS_SERVERS:
589 case DH6OPT_NISP_SERVERS:
590 case DH6OPT_BCMCS_SERVER_A:
591 case DH6OPT_PANA_AGENT:
592 case DH6OPT_LQ_CLIENT_LINK:
593 if (optlen % 16) {
594 ND_PRINT((ndo, " ?)"));
595 break;
596 }
597 tp = (u_char *)(dh6o + 1);
598 for (i = 0; i < optlen; i += 16)
599 ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[i])));
600 ND_PRINT((ndo, ")"));
601 break;
602 case DH6OPT_SIP_SERVER_D:
603 case DH6OPT_DOMAIN_LIST:
604 tp = (u_char *)(dh6o + 1);
605 while (tp < cp + sizeof(*dh6o) + optlen) {
606 ND_PRINT((ndo, " "));
607 if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL)
608 goto trunc;
609 }
610 ND_PRINT((ndo, ")"));
611 break;
612 case DH6OPT_STATUS_CODE:
613 if (optlen < 2) {
614 ND_PRINT((ndo, " ?)"));
615 break;
616 }
617 tp = (u_char *)(dh6o + 1);
618 ND_PRINT((ndo, " %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))));
619 break;
620 case DH6OPT_IA_NA:
621 case DH6OPT_IA_PD:
622 if (optlen < 12) {
623 ND_PRINT((ndo, " ?)"));
624 break;
625 }
626 tp = (u_char *)(dh6o + 1);
627 ND_PRINT((ndo, " IAID:%u T1:%u T2:%u",
628 EXTRACT_32BITS(&tp[0]),
629 EXTRACT_32BITS(&tp[4]),
630 EXTRACT_32BITS(&tp[8])));
631 if (optlen > 12) {
632 /* there are sub-options */
633 dhcp6opt_print(ndo, tp + 12, tp + optlen);
634 }
635 ND_PRINT((ndo, ")"));
636 break;
637 case DH6OPT_IA_TA:
638 if (optlen < 4) {
639 ND_PRINT((ndo, " ?)"));
640 break;
641 }
642 tp = (u_char *)(dh6o + 1);
643 ND_PRINT((ndo, " IAID:%u", EXTRACT_32BITS(tp)));
644 if (optlen > 4) {
645 /* there are sub-options */
646 dhcp6opt_print(ndo, tp + 4, tp + optlen);
647 }
648 ND_PRINT((ndo, ")"));
649 break;
650 case DH6OPT_IA_PD_PREFIX:
651 if (optlen < 25) {
652 ND_PRINT((ndo, " ?)"));
653 break;
654 }
655 tp = (u_char *)(dh6o + 1);
656 ND_PRINT((ndo, " %s/%d", ip6addr_string(ndo, &tp[9]), tp[8]));
657 ND_PRINT((ndo, " pltime:%u vltime:%u",
658 EXTRACT_32BITS(&tp[0]),
659 EXTRACT_32BITS(&tp[4])));
660 if (optlen > 25) {
661 /* there are sub-options */
662 dhcp6opt_print(ndo, tp + 25, tp + optlen);
663 }
664 ND_PRINT((ndo, ")"));
665 break;
666 case DH6OPT_LIFETIME:
667 case DH6OPT_CLT_TIME:
668 if (optlen != 4) {
669 ND_PRINT((ndo, " ?)"));
670 break;
671 }
672 tp = (u_char *)(dh6o + 1);
673 ND_PRINT((ndo, " %d)", EXTRACT_32BITS(tp)));
674 break;
675 case DH6OPT_REMOTE_ID:
676 if (optlen < 4) {
677 ND_PRINT((ndo, " ?)"));
678 break;
679 }
680 tp = (u_char *)(dh6o + 1);
681 ND_PRINT((ndo, " %d ", EXTRACT_32BITS(tp)));
682 /*
683 * Print hex dump first 10 characters.
684 */
685 for (i = 4; i < optlen && i < 14; i++)
686 ND_PRINT((ndo, "%02x", tp[i]));
687 ND_PRINT((ndo, "...)"));
688 break;
689 case DH6OPT_LQ_QUERY:
690 if (optlen < 17) {
691 ND_PRINT((ndo, " ?)"));
692 break;
693 }
694 tp = (u_char *)(dh6o + 1);
695 switch (*tp) {
696 case 1:
697 ND_PRINT((ndo, " by-address"));
698 break;
699 case 2:
700 ND_PRINT((ndo, " by-clientID"));
701 break;
702 default:
703 ND_PRINT((ndo, " type_%d", (int)*tp));
704 break;
705 }
706 ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[1])));
707 if (optlen > 17) {
708 /* there are query-options */
709 dhcp6opt_print(ndo, tp + 17, tp + optlen);
710 }
711 ND_PRINT((ndo, ")"));
712 break;
713 case DH6OPT_CLIENT_DATA:
714 tp = (u_char *)(dh6o + 1);
715 if (optlen > 0) {
716 /* there are encapsulated options */
717 dhcp6opt_print(ndo, tp, tp + optlen);
718 }
719 ND_PRINT((ndo, ")"));
720 break;
721 case DH6OPT_LQ_RELAY_DATA:
722 if (optlen < 16) {
723 ND_PRINT((ndo, " ?)"));
724 break;
725 }
726 tp = (u_char *)(dh6o + 1);
727 ND_PRINT((ndo, " %s ", ip6addr_string(ndo, &tp[0])));
728 /*
729 * Print hex dump first 10 characters.
730 */
731 for (i = 16; i < optlen && i < 26; i++)
732 ND_PRINT((ndo, "%02x", tp[i]));
733 ND_PRINT((ndo, "...)"));
734 break;
735 case DH6OPT_NTP_SERVER:
736 if (optlen < 4) {
737 ND_PRINT((ndo, " ?)"));
738 break;
739 }
740 tp = (u_char *)(dh6o + 1);
741 while (tp < cp + sizeof(*dh6o) + optlen - 4) {
742 subopt_code = EXTRACT_16BITS(tp);
743 tp += 2;
744 subopt_len = EXTRACT_16BITS(tp);
745 tp += 2;
746 if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
747 goto trunc;
748 ND_PRINT((ndo, " subopt:%d", subopt_code));
749 switch (subopt_code) {
750 case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
751 case DH6OPT_NTP_SUBOPTION_MC_ADDR:
752 if (subopt_len != 16) {
753 ND_PRINT((ndo, " ?"));
754 break;
755 }
756 ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0])));
757 break;
758 case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
759 ND_PRINT((ndo, " "));
760 if (ns_nprint(ndo, tp, tp + subopt_len) == NULL)
761 goto trunc;
762 break;
763 default:
764 ND_PRINT((ndo, " ?"));
765 break;
766 }
767 tp += subopt_len;
768 }
769 ND_PRINT((ndo, ")"));
770 break;
771 case DH6OPT_AFTR_NAME:
772 if (optlen < 3) {
773 ND_PRINT((ndo, " ?)"));
774 break;
775 }
776 tp = (u_char *)(dh6o + 1);
777 remain_len = optlen;
778 ND_PRINT((ndo, " "));
779 /* Encoding is described in section 3.1 of RFC 1035 */
780 while (remain_len && *tp) {
781 label_len = *tp++;
782 if (label_len < remain_len - 1) {
783 ND_PRINT((ndo, "%.*s", label_len, tp));
784 tp += label_len;
785 remain_len -= (label_len + 1);
786 if(*tp) ND_PRINT((ndo, "."));
787 } else {
788 ND_PRINT((ndo, " ?"));
789 break;
790 }
791 }
792 ND_PRINT((ndo, ")"));
793 break;
794 default:
795 ND_PRINT((ndo, ")"));
796 break;
797 }
798
799 cp += sizeof(*dh6o) + optlen;
800 }
801 return;
802
803 trunc:
804 ND_PRINT((ndo, "[|dhcp6ext]"));
805 }
806
807 /*
808 * Print dhcp6 packets
809 */
810 void
811 dhcp6_print(netdissect_options *ndo,
812 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 ND_PRINT((ndo, "dhcp6"));
821
822 ep = (u_char *)ndo->ndo_snapend;
823 if (cp + length < ep)
824 ep = cp + length;
825
826 dh6 = (struct dhcp6 *)cp;
827 dh6relay = (struct dhcp6_relay *)cp;
828 ND_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 (!ndo->ndo_vflag) {
881 if (name)
882 ND_PRINT((ndo, " %s", name));
883 else
884 ND_PRINT((ndo, " msgtype-%u", dh6->dh6_msgtype));
885 return;
886 }
887
888 /* XXX relay agent messages have to be handled differently */
889
890 if (name)
891 ND_PRINT((ndo, " %s (", name)); /*)*/
892 else
893 ND_PRINT((ndo, " msgtype-%u (", dh6->dh6_msgtype)); /*)*/
894 if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
895 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
896 ND_PRINT((ndo, "xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK));
897 extp = (u_char *)(dh6 + 1);
898 dhcp6opt_print(ndo, extp, ep);
899 } else { /* relay messages */
900 struct in6_addr addr6;
901
902 ND_TCHECK(dh6relay->dh6relay_peeraddr);
903
904 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
905 ND_PRINT((ndo, "linkaddr=%s", ip6addr_string(ndo, &addr6)));
906
907 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
908 ND_PRINT((ndo, " peeraddr=%s", ip6addr_string(ndo, &addr6)));
909
910 dhcp6opt_print(ndo, (u_char *)(dh6relay + 1), ep);
911 }
912 /*(*/
913 ND_PRINT((ndo, ")"));
914 return;
915
916 trunc:
917 ND_PRINT((ndo, "[|dhcp6]"));
918 }