]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
NDOize OSPFv3 decoder
[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 if (type > 65535)
189 return "INVALID-option";
190
191 switch(type) {
192 case DH6OPT_CLIENTID:
193 return "client-ID";
194 case DH6OPT_SERVERID:
195 return "server-ID";
196 case DH6OPT_IA_NA:
197 return "IA_NA";
198 case DH6OPT_IA_TA:
199 return "IA_TA";
200 case DH6OPT_IA_ADDR:
201 return "IA_ADDR";
202 case DH6OPT_ORO:
203 return "option-request";
204 case DH6OPT_PREFERENCE:
205 return "preference";
206 case DH6OPT_ELAPSED_TIME:
207 return "elapsed-time";
208 case DH6OPT_RELAY_MSG:
209 return "relay-message";
210 case DH6OPT_AUTH:
211 return "authentication";
212 case DH6OPT_UNICAST:
213 return "server-unicast";
214 case DH6OPT_STATUS_CODE:
215 return "status-code";
216 case DH6OPT_RAPID_COMMIT:
217 return "rapid-commit";
218 case DH6OPT_USER_CLASS:
219 return "user-class";
220 case DH6OPT_VENDOR_CLASS:
221 return "vendor-class";
222 case DH6OPT_VENDOR_OPTS:
223 return "vendor-specific-info";
224 case DH6OPT_INTERFACE_ID:
225 return "interface-ID";
226 case DH6OPT_RECONF_MSG:
227 return "reconfigure-message";
228 case DH6OPT_RECONF_ACCEPT:
229 return "reconfigure-accept";
230 case DH6OPT_SIP_SERVER_D:
231 return "SIP-servers-domain";
232 case DH6OPT_SIP_SERVER_A:
233 return "SIP-servers-address";
234 case DH6OPT_DNS_SERVERS:
235 return "DNS-server";
236 case DH6OPT_DOMAIN_LIST:
237 return "DNS-search-list";
238 case DH6OPT_IA_PD:
239 return "IA_PD";
240 case DH6OPT_IA_PD_PREFIX:
241 return "IA_PD-prefix";
242 case DH6OPT_SNTP_SERVERS:
243 return "SNTP-servers";
244 case DH6OPT_LIFETIME:
245 return "lifetime";
246 case DH6OPT_NIS_SERVERS:
247 return "NIS-server";
248 case DH6OPT_NISP_SERVERS:
249 return "NIS+-server";
250 case DH6OPT_NIS_NAME:
251 return "NIS-domain-name";
252 case DH6OPT_NISP_NAME:
253 return "NIS+-domain-name";
254 case DH6OPT_BCMCS_SERVER_D:
255 return "BCMCS-domain-name";
256 case DH6OPT_BCMCS_SERVER_A:
257 return "BCMCS-server";
258 case DH6OPT_GEOCONF_CIVIC:
259 return "Geoconf-Civic";
260 case DH6OPT_REMOTE_ID:
261 return "Remote-ID";
262 case DH6OPT_SUBSCRIBER_ID:
263 return "Subscriber-ID";
264 case DH6OPT_CLIENT_FQDN:
265 return "Client-FQDN";
266 case DH6OPT_PANA_AGENT:
267 return "PANA-agent";
268 case DH6OPT_NEW_POSIX_TIMEZONE:
269 return "POSIX-timezone";
270 case DH6OPT_NEW_TZDB_TIMEZONE:
271 return "POSIX-tz-database";
272 case DH6OPT_ERO:
273 return "Echo-request-option";
274 case DH6OPT_LQ_QUERY:
275 return "Lease-query";
276 case DH6OPT_CLIENT_DATA:
277 return "LQ-client-data";
278 case DH6OPT_CLT_TIME:
279 return "Clt-time";
280 case DH6OPT_LQ_RELAY_DATA:
281 return "LQ-relay-data";
282 case DH6OPT_LQ_CLIENT_LINK:
283 return "LQ-client-link";
284 case DH6OPT_NTP_SERVER:
285 return "NTP-server";
286 case DH6OPT_AFTR_NAME:
287 return "AFTR-Name";
288 default:
289 snprintf(genstr, sizeof(genstr), "opt_%d", type);
290 return(genstr);
291 }
292 }
293
294 static const char *
295 dhcp6stcode(int code)
296 {
297 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
298
299 if (code > 255)
300 return "INVALID code";
301
302 switch(code) {
303 case DH6OPT_STCODE_SUCCESS:
304 return "success";
305 case DH6OPT_STCODE_UNSPECFAIL:
306 return "unspec failure";
307 case DH6OPT_STCODE_NOADDRAVAIL:
308 return "no addresses";
309 case DH6OPT_STCODE_NOBINDING:
310 return "no binding";
311 case DH6OPT_STCODE_NOTONLINK:
312 return "not on-link";
313 case DH6OPT_STCODE_USEMULTICAST:
314 return "use multicast";
315 case DH6OPT_STCODE_NOPREFIXAVAIL:
316 return "no prefixes";
317 case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
318 return "unknown query type";
319 case DH6OPT_STCODE_MALFORMEDQUERY:
320 return "malformed query";
321 case DH6OPT_STCODE_NOTCONFIGURED:
322 return "not configured";
323 case DH6OPT_STCODE_NOTALLOWED:
324 return "not allowed";
325 default:
326 snprintf(genstr, sizeof(genstr), "code%d", code);
327 return(genstr);
328 }
329 }
330
331 static void
332 dhcp6opt_print(netdissect_options *ndo,
333 const u_char *cp, const u_char *ep)
334 {
335 const struct dhcp6opt *dh6o;
336 const u_char *tp;
337 size_t i;
338 u_int16_t opttype;
339 size_t optlen;
340 u_int8_t auth_proto;
341 u_int authinfolen, authrealmlen;
342 int remain_len; /* Length of remaining options */
343 int label_len; /* Label length */
344 u_int16_t subopt_code;
345 u_int16_t subopt_len;
346
347 if (cp == ep)
348 return;
349 while (cp < ep) {
350 if (ep < cp + sizeof(*dh6o))
351 goto trunc;
352 dh6o = (struct dhcp6opt *)cp;
353 ND_TCHECK(*dh6o);
354 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
355 if (ep < cp + sizeof(*dh6o) + optlen)
356 goto trunc;
357 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
358 ND_PRINT((ndo, " (%s", dhcp6opt_name(opttype)));
359 switch (opttype) {
360 case DH6OPT_CLIENTID:
361 case DH6OPT_SERVERID:
362 if (optlen < 2) {
363 /*(*/
364 ND_PRINT((ndo, " ?)"));
365 break;
366 }
367 tp = (u_char *)(dh6o + 1);
368 switch (EXTRACT_16BITS(tp)) {
369 case 1:
370 if (optlen >= 2 + 6) {
371 ND_PRINT((ndo, " hwaddr/time type %u time %u ",
372 EXTRACT_16BITS(&tp[2]),
373 EXTRACT_32BITS(&tp[4])));
374 for (i = 8; i < optlen; i++)
375 ND_PRINT((ndo, "%02x", tp[i]));
376 /*(*/
377 ND_PRINT((ndo, ")"));
378 } else {
379 /*(*/
380 ND_PRINT((ndo, " ?)"));
381 }
382 break;
383 case 2:
384 if (optlen >= 2 + 8) {
385 ND_PRINT((ndo, " vid "));
386 for (i = 2; i < 2 + 8; i++)
387 ND_PRINT((ndo, "%02x", tp[i]));
388 /*(*/
389 ND_PRINT((ndo, ")"));
390 } else {
391 /*(*/
392 ND_PRINT((ndo, " ?)"));
393 }
394 break;
395 case 3:
396 if (optlen >= 2 + 2) {
397 ND_PRINT((ndo, " hwaddr type %u ",
398 EXTRACT_16BITS(&tp[2])));
399 for (i = 4; i < optlen; i++)
400 ND_PRINT((ndo, "%02x", tp[i]));
401 /*(*/
402 ND_PRINT((ndo, ")"));
403 } else {
404 /*(*/
405 ND_PRINT((ndo, " ?)"));
406 }
407 break;
408 default:
409 ND_PRINT((ndo, " type %d)", EXTRACT_16BITS(tp)));
410 break;
411 }
412 break;
413 case DH6OPT_IA_ADDR:
414 if (optlen < 24) {
415 /*(*/
416 ND_PRINT((ndo, " ?)"));
417 break;
418 }
419 tp = (u_char *)(dh6o + 1);
420 ND_PRINT((ndo, " %s", ip6addr_string(&tp[0])));
421 ND_PRINT((ndo, " pltime:%u vltime:%u",
422 EXTRACT_32BITS(&tp[16]),
423 EXTRACT_32BITS(&tp[20])));
424 if (optlen > 24) {
425 /* there are sub-options */
426 dhcp6opt_print(ndo, tp + 24, tp + optlen);
427 }
428 ND_PRINT((ndo, ")"));
429 break;
430 case DH6OPT_ORO:
431 case DH6OPT_ERO:
432 if (optlen % 2) {
433 ND_PRINT((ndo, " ?)"));
434 break;
435 }
436 tp = (u_char *)(dh6o + 1);
437 for (i = 0; i < optlen; i += 2) {
438 ND_PRINT((ndo, " %s",
439 dhcp6opt_name(EXTRACT_16BITS(&tp[i]))));
440 }
441 ND_PRINT((ndo, ")"));
442 break;
443 case DH6OPT_PREFERENCE:
444 if (optlen != 1) {
445 ND_PRINT((ndo, " ?)"));
446 break;
447 }
448 tp = (u_char *)(dh6o + 1);
449 ND_PRINT((ndo, " %d)", *tp));
450 break;
451 case DH6OPT_ELAPSED_TIME:
452 if (optlen != 2) {
453 ND_PRINT((ndo, " ?)"));
454 break;
455 }
456 tp = (u_char *)(dh6o + 1);
457 ND_PRINT((ndo, " %d)", EXTRACT_16BITS(tp)));
458 break;
459 case DH6OPT_RELAY_MSG:
460 ND_PRINT((ndo, " ("));
461 tp = (u_char *)(dh6o + 1);
462 dhcp6_print(ndo, tp, optlen);
463 ND_PRINT((ndo, ")"));
464 break;
465 case DH6OPT_AUTH:
466 if (optlen < 11) {
467 ND_PRINT((ndo, " ?)"));
468 break;
469 }
470 tp = (u_char *)(dh6o + 1);
471 auth_proto = *tp;
472 switch (auth_proto) {
473 case DH6OPT_AUTHPROTO_DELAYED:
474 ND_PRINT((ndo, " proto: delayed"));
475 break;
476 case DH6OPT_AUTHPROTO_RECONFIG:
477 ND_PRINT((ndo, " proto: reconfigure"));
478 break;
479 default:
480 ND_PRINT((ndo, " proto: %d", auth_proto));
481 break;
482 }
483 tp++;
484 switch (*tp) {
485 case DH6OPT_AUTHALG_HMACMD5:
486 /* XXX: may depend on the protocol */
487 ND_PRINT((ndo, ", alg: HMAC-MD5"));
488 break;
489 default:
490 ND_PRINT((ndo, ", alg: %d", *tp));
491 break;
492 }
493 tp++;
494 switch (*tp) {
495 case DH6OPT_AUTHRDM_MONOCOUNTER:
496 ND_PRINT((ndo, ", RDM: mono"));
497 break;
498 default:
499 ND_PRINT((ndo, ", RDM: %d", *tp));
500 break;
501 }
502 tp++;
503 ND_PRINT((ndo, ", RD:"));
504 for (i = 0; i < 4; i++, tp += 2)
505 ND_PRINT((ndo, " %04x", EXTRACT_16BITS(tp)));
506
507 /* protocol dependent part */
508 authinfolen = optlen - 11;
509 switch (auth_proto) {
510 case DH6OPT_AUTHPROTO_DELAYED:
511 if (authinfolen == 0)
512 break;
513 if (authinfolen < 20) {
514 ND_PRINT((ndo, " ??"));
515 break;
516 }
517 authrealmlen = authinfolen - 20;
518 if (authrealmlen > 0) {
519 ND_PRINT((ndo, ", realm: "));
520 }
521 for (i = 0; i < authrealmlen; i++, tp++)
522 ND_PRINT((ndo, "%02x", *tp));
523 ND_PRINT((ndo, ", key ID: %08x", EXTRACT_32BITS(tp)));
524 tp += 4;
525 ND_PRINT((ndo, ", HMAC-MD5:"));
526 for (i = 0; i < 4; i++, tp+= 4)
527 ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
528 break;
529 case DH6OPT_AUTHPROTO_RECONFIG:
530 if (authinfolen != 17) {
531 ND_PRINT((ndo, " ??"));
532 break;
533 }
534 switch (*tp++) {
535 case DH6OPT_AUTHRECONFIG_KEY:
536 ND_PRINT((ndo, " reconfig-key"));
537 break;
538 case DH6OPT_AUTHRECONFIG_HMACMD5:
539 ND_PRINT((ndo, " type: HMAC-MD5"));
540 break;
541 default:
542 ND_PRINT((ndo, " type: ??"));
543 break;
544 }
545 ND_PRINT((ndo, " value:"));
546 for (i = 0; i < 4; i++, tp+= 4)
547 ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
548 break;
549 default:
550 ND_PRINT((ndo, " ??"));
551 break;
552 }
553
554 ND_PRINT((ndo, ")"));
555 break;
556 case DH6OPT_RAPID_COMMIT: /* nothing todo */
557 ND_PRINT((ndo, ")"));
558 break;
559 case DH6OPT_INTERFACE_ID:
560 case DH6OPT_SUBSCRIBER_ID:
561 /*
562 * Since we cannot predict the encoding, print hex dump
563 * at most 10 characters.
564 */
565 tp = (u_char *)(dh6o + 1);
566 ND_PRINT((ndo, " "));
567 for (i = 0; i < optlen && i < 10; i++)
568 ND_PRINT((ndo, "%02x", tp[i]));
569 ND_PRINT((ndo, "...)"));
570 break;
571 case DH6OPT_RECONF_MSG:
572 tp = (u_char *)(dh6o + 1);
573 switch (*tp) {
574 case DH6_RENEW:
575 ND_PRINT((ndo, " for renew)"));
576 break;
577 case DH6_INFORM_REQ:
578 ND_PRINT((ndo, " for inf-req)"));
579 break;
580 default:
581 ND_PRINT((ndo, " for ?\?\?(%02x))", *tp));
582 break;
583 }
584 break;
585 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
586 ND_PRINT((ndo, ")"));
587 break;
588 case DH6OPT_SIP_SERVER_A:
589 case DH6OPT_DNS_SERVERS:
590 case DH6OPT_SNTP_SERVERS:
591 case DH6OPT_NIS_SERVERS:
592 case DH6OPT_NISP_SERVERS:
593 case DH6OPT_BCMCS_SERVER_A:
594 case DH6OPT_PANA_AGENT:
595 case DH6OPT_LQ_CLIENT_LINK:
596 if (optlen % 16) {
597 ND_PRINT((ndo, " ?)"));
598 break;
599 }
600 tp = (u_char *)(dh6o + 1);
601 for (i = 0; i < optlen; i += 16)
602 ND_PRINT((ndo, " %s", ip6addr_string(&tp[i])));
603 ND_PRINT((ndo, ")"));
604 break;
605 case DH6OPT_SIP_SERVER_D:
606 case DH6OPT_DOMAIN_LIST:
607 tp = (u_char *)(dh6o + 1);
608 while (tp < cp + sizeof(*dh6o) + optlen) {
609 ND_PRINT((ndo, " "));
610 if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL)
611 goto trunc;
612 }
613 ND_PRINT((ndo, ")"));
614 break;
615 case DH6OPT_STATUS_CODE:
616 if (optlen < 2) {
617 ND_PRINT((ndo, " ?)"));
618 break;
619 }
620 tp = (u_char *)(dh6o + 1);
621 ND_PRINT((ndo, " %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))));
622 break;
623 case DH6OPT_IA_NA:
624 case DH6OPT_IA_PD:
625 if (optlen < 12) {
626 ND_PRINT((ndo, " ?)"));
627 break;
628 }
629 tp = (u_char *)(dh6o + 1);
630 ND_PRINT((ndo, " IAID:%u T1:%u T2:%u",
631 EXTRACT_32BITS(&tp[0]),
632 EXTRACT_32BITS(&tp[4]),
633 EXTRACT_32BITS(&tp[8])));
634 if (optlen > 12) {
635 /* there are sub-options */
636 dhcp6opt_print(ndo, tp + 12, tp + optlen);
637 }
638 ND_PRINT((ndo, ")"));
639 break;
640 case DH6OPT_IA_TA:
641 if (optlen < 4) {
642 ND_PRINT((ndo, " ?)"));
643 break;
644 }
645 tp = (u_char *)(dh6o + 1);
646 ND_PRINT((ndo, " IAID:%u", EXTRACT_32BITS(tp)));
647 if (optlen > 4) {
648 /* there are sub-options */
649 dhcp6opt_print(ndo, tp + 4, tp + optlen);
650 }
651 ND_PRINT((ndo, ")"));
652 break;
653 case DH6OPT_IA_PD_PREFIX:
654 if (optlen < 25) {
655 ND_PRINT((ndo, " ?)"));
656 break;
657 }
658 tp = (u_char *)(dh6o + 1);
659 ND_PRINT((ndo, " %s/%d", ip6addr_string(&tp[9]), tp[8]));
660 ND_PRINT((ndo, " pltime:%u vltime:%u",
661 EXTRACT_32BITS(&tp[0]),
662 EXTRACT_32BITS(&tp[4])));
663 if (optlen > 25) {
664 /* there are sub-options */
665 dhcp6opt_print(ndo, tp + 25, tp + optlen);
666 }
667 ND_PRINT((ndo, ")"));
668 break;
669 case DH6OPT_LIFETIME:
670 case DH6OPT_CLT_TIME:
671 if (optlen != 4) {
672 ND_PRINT((ndo, " ?)"));
673 break;
674 }
675 tp = (u_char *)(dh6o + 1);
676 ND_PRINT((ndo, " %d)", EXTRACT_32BITS(tp)));
677 break;
678 case DH6OPT_REMOTE_ID:
679 if (optlen < 4) {
680 ND_PRINT((ndo, " ?)"));
681 break;
682 }
683 tp = (u_char *)(dh6o + 1);
684 ND_PRINT((ndo, " %d ", EXTRACT_32BITS(tp)));
685 /*
686 * Print hex dump first 10 characters.
687 */
688 for (i = 4; i < optlen && i < 14; i++)
689 ND_PRINT((ndo, "%02x", tp[i]));
690 ND_PRINT((ndo, "...)"));
691 break;
692 case DH6OPT_LQ_QUERY:
693 if (optlen < 17) {
694 ND_PRINT((ndo, " ?)"));
695 break;
696 }
697 tp = (u_char *)(dh6o + 1);
698 switch (*tp) {
699 case 1:
700 ND_PRINT((ndo, " by-address"));
701 break;
702 case 2:
703 ND_PRINT((ndo, " by-clientID"));
704 break;
705 default:
706 ND_PRINT((ndo, " type_%d", (int)*tp));
707 break;
708 }
709 ND_PRINT((ndo, " %s", ip6addr_string(&tp[1])));
710 if (optlen > 17) {
711 /* there are query-options */
712 dhcp6opt_print(ndo, tp + 17, tp + optlen);
713 }
714 ND_PRINT((ndo, ")"));
715 break;
716 case DH6OPT_CLIENT_DATA:
717 tp = (u_char *)(dh6o + 1);
718 if (optlen > 0) {
719 /* there are encapsulated options */
720 dhcp6opt_print(ndo, tp, tp + optlen);
721 }
722 ND_PRINT((ndo, ")"));
723 break;
724 case DH6OPT_LQ_RELAY_DATA:
725 if (optlen < 16) {
726 ND_PRINT((ndo, " ?)"));
727 break;
728 }
729 tp = (u_char *)(dh6o + 1);
730 ND_PRINT((ndo, " %s ", ip6addr_string(&tp[0])));
731 /*
732 * Print hex dump first 10 characters.
733 */
734 for (i = 16; i < optlen && i < 26; i++)
735 ND_PRINT((ndo, "%02x", tp[i]));
736 ND_PRINT((ndo, "...)"));
737 break;
738 case DH6OPT_NTP_SERVER:
739 if (optlen < 4) {
740 ND_PRINT((ndo, " ?)"));
741 break;
742 }
743 tp = (u_char *)(dh6o + 1);
744 while (tp < cp + sizeof(*dh6o) + optlen - 4) {
745 subopt_code = EXTRACT_16BITS(tp);
746 tp += 2;
747 subopt_len = EXTRACT_16BITS(tp);
748 tp += 2;
749 if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
750 goto trunc;
751 ND_PRINT((ndo, " subopt:%d", subopt_code));
752 switch (subopt_code) {
753 case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
754 case DH6OPT_NTP_SUBOPTION_MC_ADDR:
755 if (subopt_len != 16) {
756 ND_PRINT((ndo, " ?"));
757 break;
758 }
759 ND_PRINT((ndo, " %s", ip6addr_string(&tp[0])));
760 break;
761 case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
762 ND_PRINT((ndo, " "));
763 if (ns_nprint(ndo, tp, tp + subopt_len) == NULL)
764 goto trunc;
765 break;
766 default:
767 ND_PRINT((ndo, " ?"));
768 break;
769 }
770 tp += subopt_len;
771 }
772 ND_PRINT((ndo, ")"));
773 break;
774 case DH6OPT_AFTR_NAME:
775 if (optlen < 3) {
776 ND_PRINT((ndo, " ?)"));
777 break;
778 }
779 tp = (u_char *)(dh6o + 1);
780 remain_len = optlen;
781 ND_PRINT((ndo, " "));
782 /* Encoding is described in section 3.1 of RFC 1035 */
783 while (remain_len && *tp) {
784 label_len = *tp++;
785 if (label_len < remain_len - 1) {
786 ND_PRINT((ndo, "%.*s", label_len, tp));
787 tp += label_len;
788 remain_len -= (label_len + 1);
789 if(*tp) ND_PRINT((ndo, "."));
790 } else {
791 ND_PRINT((ndo, " ?"));
792 break;
793 }
794 }
795 ND_PRINT((ndo, ")"));
796 break;
797 default:
798 ND_PRINT((ndo, ")"));
799 break;
800 }
801
802 cp += sizeof(*dh6o) + optlen;
803 }
804 return;
805
806 trunc:
807 ND_PRINT((ndo, "[|dhcp6ext]"));
808 }
809
810 /*
811 * Print dhcp6 packets
812 */
813 void
814 dhcp6_print(netdissect_options *ndo,
815 const u_char *cp, u_int length)
816 {
817 struct dhcp6 *dh6;
818 struct dhcp6_relay *dh6relay;
819 const u_char *ep;
820 u_char *extp;
821 const char *name;
822
823 ND_PRINT((ndo, "dhcp6"));
824
825 ep = (u_char *)ndo->ndo_snapend;
826 if (cp + length < ep)
827 ep = cp + length;
828
829 dh6 = (struct dhcp6 *)cp;
830 dh6relay = (struct dhcp6_relay *)cp;
831 ND_TCHECK(dh6->dh6_xid);
832 switch (dh6->dh6_msgtype) {
833 case DH6_SOLICIT:
834 name = "solicit";
835 break;
836 case DH6_ADVERTISE:
837 name = "advertise";
838 break;
839 case DH6_REQUEST:
840 name = "request";
841 break;
842 case DH6_CONFIRM:
843 name = "confirm";
844 break;
845 case DH6_RENEW:
846 name = "renew";
847 break;
848 case DH6_REBIND:
849 name = "rebind";
850 break;
851 case DH6_REPLY:
852 name = "reply";
853 break;
854 case DH6_RELEASE:
855 name = "release";
856 break;
857 case DH6_DECLINE:
858 name = "decline";
859 break;
860 case DH6_RECONFIGURE:
861 name = "reconfigure";
862 break;
863 case DH6_INFORM_REQ:
864 name= "inf-req";
865 break;
866 case DH6_RELAY_FORW:
867 name= "relay-fwd";
868 break;
869 case DH6_RELAY_REPLY:
870 name= "relay-reply";
871 break;
872 case DH6_LEASEQUERY:
873 name= "leasequery";
874 break;
875 case DH6_LQ_REPLY:
876 name= "leasequery-reply";
877 break;
878 default:
879 name = NULL;
880 break;
881 }
882
883 if (!ndo->ndo_vflag) {
884 if (name)
885 ND_PRINT((ndo, " %s", name));
886 else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
887 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
888 ND_PRINT((ndo, " msgtype-%u", dh6->dh6_msgtype));
889 }
890 return;
891 }
892
893 /* XXX relay agent messages have to be handled differently */
894
895 if (name)
896 ND_PRINT((ndo, " %s (", name)); /*)*/
897 else
898 ND_PRINT((ndo, " msgtype-%u (", dh6->dh6_msgtype)); /*)*/
899 if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
900 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
901 ND_PRINT((ndo, "xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK));
902 extp = (u_char *)(dh6 + 1);
903 dhcp6opt_print(ndo, extp, ep);
904 } else { /* relay messages */
905 struct in6_addr addr6;
906
907 ND_TCHECK(dh6relay->dh6relay_peeraddr);
908
909 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
910 ND_PRINT((ndo, "linkaddr=%s", ip6addr_string(&addr6)));
911
912 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
913 ND_PRINT((ndo, " peeraddr=%s", ip6addr_string(&addr6)));
914
915 dhcp6opt_print(ndo, (u_char *)(dh6relay + 1), ep);
916 }
917 /*(*/
918 ND_PRINT((ndo, ")"));
919 return;
920
921 trunc:
922 ND_PRINT((ndo, "[|dhcp6]"));
923 }