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,
33 * RFC3633,
34 * RFC3646,
35 * RFC3898,
36 * RFC4075,
37 * RFC4242,
38 * RFC4280,
39 */
40
41 #ifndef lint
42 static const char rcsid[] _U_ =
43 "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.35.2.1 2006/10/25 22:04:36 guy Exp $";
44 #endif
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include <tcpdump-stdinc.h>
51
52 #include <stdio.h>
53 #include <string.h>
54
55 #include "interface.h"
56 #include "addrtoname.h"
57 #include "extract.h"
58
59 /* lease duration */
60 #define DHCP6_DURATITION_INFINITE 0xffffffff
61
62 /* Error Values */
63 #define DH6ERR_FAILURE 16
64 #define DH6ERR_AUTHFAIL 17
65 #define DH6ERR_POORLYFORMED 18
66 #define DH6ERR_UNAVAIL 19
67 #define DH6ERR_OPTUNAVAIL 20
68
69 /* Message type */
70 #define DH6_SOLICIT 1
71 #define DH6_ADVERTISE 2
72 #define DH6_REQUEST 3
73 #define DH6_CONFIRM 4
74 #define DH6_RENEW 5
75 #define DH6_REBIND 6
76 #define DH6_REPLY 7
77 #define DH6_RELEASE 8
78 #define DH6_DECLINE 9
79 #define DH6_RECONFIGURE 10
80 #define DH6_INFORM_REQ 11
81 #define DH6_RELAY_FORW 12
82 #define DH6_RELAY_REPLY 13
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_RAPID_COMMIT 14
134 #define DH6OPT_USER_CLASS 15
135 #define DH6OPT_VENDOR_CLASS 16
136 #define DH6OPT_VENDOR_OPTS 17
137 #define DH6OPT_INTERFACE_ID 18
138 #define DH6OPT_RECONF_MSG 19
139 #define DH6OPT_RECONF_ACCEPT 20
140 #define DH6OPT_SIP_SERVER_D 21
141 #define DH6OPT_SIP_SERVER_A 22
142 #define DH6OPT_DNS 23
143 #define DH6OPT_DNSNAME 24
144 #define DH6OPT_IA_PD 25
145 #define DH6OPT_IA_PD_PREFIX 26
146 #define DH6OPT_NIS_SERVERS 27
147 #define DH6OPT_NISP_SERVERS 28
148 #define DH6OPT_NIS_NAME 29
149 #define DH6OPT_NISP_NAME 30
150 #define DH6OPT_NTP_SERVERS 31
151 #define DH6OPT_LIFETIME 32
152 #define DH6OPT_BCMCS_SERVER_D 33
153 #define DH6OPT_BCMCS_SERVER_A 34
154 #define DH6OPT_GEOCONF_CIVIC 36
155 #define DH6OPT_REMOTE_ID 37
156 #define DH6OPT_SUBSCRIBER_ID 38
157 #define DH6OPT_CLIENT_FQDN 39
158
159 struct dhcp6opt {
160 u_int16_t dh6opt_type;
161 u_int16_t dh6opt_len;
162 /* type-dependent data follows */
163 };
164
165 struct dhcp6_ia {
166 u_int16_t dh6opt_ia_type;
167 u_int16_t dh6opt_ia_len;
168 u_int32_t dh6opt_ia_iaid;
169 u_int32_t dh6opt_ia_t1;
170 u_int32_t dh6opt_ia_t2;
171 };
172
173 struct dhcp6_ia_addr {
174 u_int16_t dh6opt_ia_addr_type;
175 u_int16_t dh6opt_ia_addr_len;
176 struct in6_addr dh6opt_ia_addr_addr;
177 u_int32_t dh6opt_ia_addr_pltime;
178 u_int32_t dh6opt_ia_addr_vltime;
179 } __attribute__ ((__packed__));
180
181 struct dhcp6_ia_prefix {
182 u_int16_t dh6opt_ia_prefix_type;
183 u_int16_t dh6opt_ia_prefix_len;
184 u_int32_t dh6opt_ia_prefix_pltime;
185 u_int32_t dh6opt_ia_prefix_vltime;
186 u_int8_t dh6opt_ia_prefix_plen;
187 struct in6_addr dh6opt_ia_prefix_addr;
188 } __attribute__ ((__packed__));
189
190 struct dhcp6_auth {
191 u_int16_t dh6opt_auth_type;
192 u_int16_t dh6opt_auth_len;
193 u_int8_t dh6opt_auth_proto;
194 u_int8_t dh6opt_auth_alg;
195 u_int8_t dh6opt_auth_rdm;
196 u_int8_t dh6opt_auth_rdinfo[8];
197 /* authentication information follows */
198 } __attribute__ ((__packed__));
199
200 static const char *
dhcp6opt_name(int type)201 dhcp6opt_name(int type)
202 {
203 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
204
205 if (type > 65535)
206 return "INVALID option";
207
208 switch(type) {
209 case DH6OPT_CLIENTID:
210 return "client ID";
211 case DH6OPT_SERVERID:
212 return "server ID";
213 case DH6OPT_IA_NA:
214 return "IA_NA";
215 case DH6OPT_IA_TA:
216 return "IA_TA";
217 case DH6OPT_IA_ADDR:
218 return "IA_ADDR";
219 case DH6OPT_ORO:
220 return "option request";
221 case DH6OPT_PREFERENCE:
222 return "preference";
223 case DH6OPT_ELAPSED_TIME:
224 return "elapsed time";
225 case DH6OPT_RELAY_MSG:
226 return "relay message";
227 case DH6OPT_AUTH:
228 return "authentication";
229 case DH6OPT_UNICAST:
230 return "server unicast";
231 case DH6OPT_STATUS_CODE:
232 return "status code";
233 case DH6OPT_RAPID_COMMIT:
234 return "rapid commit";
235 case DH6OPT_USER_CLASS:
236 return "user class";
237 case DH6OPT_VENDOR_CLASS:
238 return "vendor class";
239 case DH6OPT_VENDOR_OPTS:
240 return "vendor-specific info";
241 case DH6OPT_INTERFACE_ID:
242 return "interface ID";
243 case DH6OPT_RECONF_MSG:
244 return "reconfigure message";
245 case DH6OPT_RECONF_ACCEPT:
246 return "reconfigure accept";
247 case DH6OPT_SIP_SERVER_D:
248 return "SIP servers domain";
249 case DH6OPT_SIP_SERVER_A:
250 return "SIP servers address";
251 case DH6OPT_DNS:
252 return "DNS";
253 case DH6OPT_DNSNAME:
254 return "DNS name";
255 case DH6OPT_IA_PD:
256 return "IA_PD";
257 case DH6OPT_IA_PD_PREFIX:
258 return "IA_PD prefix";
259 case DH6OPT_NTP_SERVERS:
260 return "NTP Server";
261 case DH6OPT_LIFETIME:
262 return "lifetime";
263 case DH6OPT_NIS_SERVERS:
264 return "NIS server";
265 case DH6OPT_NISP_SERVERS:
266 return "NIS+ server";
267 case DH6OPT_NIS_NAME:
268 return "NIS domain name";
269 case DH6OPT_NISP_NAME:
270 return "NIS+ domain name";
271 case DH6OPT_BCMCS_SERVER_D:
272 return "BCMCS domain name";
273 case DH6OPT_BCMCS_SERVER_A:
274 return "BCMCS server";
275 case DH6OPT_GEOCONF_CIVIC:
276 return "Geoconf Civic";
277 case DH6OPT_REMOTE_ID:
278 return "Remote ID";
279 case DH6OPT_SUBSCRIBER_ID:
280 return "Subscriber ID";
281 case DH6OPT_CLIENT_FQDN:
282 return "Client FQDN";
283 default:
284 snprintf(genstr, sizeof(genstr), "opt_%d", type);
285 return(genstr);
286 }
287 }
288
289 static const char *
dhcp6stcode(int code)290 dhcp6stcode(int code)
291 {
292 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
293
294 if (code > 255)
295 return "INVALID code";
296
297 switch(code) {
298 case DH6OPT_STCODE_SUCCESS:
299 return "success";
300 case DH6OPT_STCODE_UNSPECFAIL:
301 return "unspec failure";
302 case DH6OPT_STCODE_NOADDRAVAIL:
303 return "no addresses";
304 case DH6OPT_STCODE_NOBINDING:
305 return "no binding";
306 case DH6OPT_STCODE_NOTONLINK:
307 return "not on-link";
308 case DH6OPT_STCODE_USEMULTICAST:
309 return "use multicast";
310 case DH6OPT_STCODE_NOPREFIXAVAIL:
311 return "no prefixes";
312 default:
313 snprintf(genstr, sizeof(genstr), "code%d", code);
314 return(genstr);
315 }
316 }
317
318 static void
dhcp6opt_print(const u_char * cp,const u_char * ep)319 dhcp6opt_print(const u_char *cp, const u_char *ep)
320 {
321 struct dhcp6opt *dh6o;
322 u_char *tp;
323 size_t i;
324 u_int16_t opttype;
325 size_t optlen;
326 u_int16_t val16;
327 u_int32_t val32;
328 struct dhcp6_ia ia;
329 struct dhcp6_ia_prefix ia_prefix;
330 struct dhcp6_ia_addr ia_addr;
331 struct dhcp6_auth authopt;
332 u_int authinfolen, authrealmlen;
333
334 if (cp == ep)
335 return;
336 while (cp < ep) {
337 if (ep < cp + sizeof(*dh6o))
338 goto trunc;
339 dh6o = (struct dhcp6opt *)cp;
340 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
341 if (ep < cp + sizeof(*dh6o) + optlen)
342 goto trunc;
343 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
344 printf(" (%s", dhcp6opt_name(opttype));
345 switch (opttype) {
346 case DH6OPT_CLIENTID:
347 case DH6OPT_SERVERID:
348 if (optlen < 2) {
349 /*(*/
350 printf(" ?)");
351 break;
352 }
353 tp = (u_char *)(dh6o + 1);
354 switch (EXTRACT_16BITS(tp)) {
355 case 1:
356 if (optlen >= 2 + 6) {
357 printf(" hwaddr/time type %u time %u ",
358 EXTRACT_16BITS(&tp[2]),
359 EXTRACT_32BITS(&tp[4]));
360 for (i = 8; i < optlen; i++)
361 printf("%02x", tp[i]);
362 /*(*/
363 printf(")");
364 } else {
365 /*(*/
366 printf(" ?)");
367 }
368 break;
369 case 2:
370 if (optlen >= 2 + 8) {
371 printf(" vid ");
372 for (i = 2; i < 2 + 8; i++)
373 printf("%02x", tp[i]);
374 /*(*/
375 printf(")");
376 } else {
377 /*(*/
378 printf(" ?)");
379 }
380 break;
381 case 3:
382 if (optlen >= 2 + 2) {
383 printf(" hwaddr type %u ",
384 EXTRACT_16BITS(&tp[2]));
385 for (i = 4; i < optlen; i++)
386 printf("%02x", tp[i]);
387 /*(*/
388 printf(")");
389 } else {
390 /*(*/
391 printf(" ?)");
392 }
393 break;
394 default:
395 printf(" type %d)", EXTRACT_16BITS(tp));
396 break;
397 }
398 break;
399 case DH6OPT_IA_ADDR:
400 if (optlen < sizeof(ia_addr) - 4) {
401 printf(" ?)");
402 break;
403 }
404 memcpy(&ia_addr, (u_char *)dh6o, sizeof(ia_addr));
405 printf(" %s",
406 ip6addr_string(&ia_addr.dh6opt_ia_addr_addr));
407 ia_addr.dh6opt_ia_addr_pltime =
408 ntohl(ia_addr.dh6opt_ia_addr_pltime);
409 ia_addr.dh6opt_ia_addr_vltime =
410 ntohl(ia_addr.dh6opt_ia_addr_vltime);
411 printf(" pltime:%lu vltime:%lu",
412 (unsigned long)ia_addr.dh6opt_ia_addr_pltime,
413 (unsigned long)ia_addr.dh6opt_ia_addr_vltime);
414 if (optlen > sizeof(ia_addr) - 4) {
415 /* there are sub-options */
416 dhcp6opt_print((u_char *)dh6o +
417 sizeof(ia_addr),
418 (u_char *)(dh6o + 1) + optlen);
419 }
420 printf(")");
421 break;
422 case DH6OPT_ORO:
423 if (optlen % 2) {
424 printf(" ?)");
425 break;
426 }
427 tp = (u_char *)(dh6o + 1);
428 for (i = 0; i < optlen; i += 2) {
429 u_int16_t opt;
430
431 memcpy(&opt, &tp[i], sizeof(opt));
432 printf(" %s", dhcp6opt_name(ntohs(opt)));
433 }
434 printf(")");
435 break;
436 case DH6OPT_PREFERENCE:
437 if (optlen != 1) {
438 printf(" ?)");
439 break;
440 }
441 printf(" %d)", *((u_char *)(dh6o + 1) + 1));
442 break;
443 case DH6OPT_ELAPSED_TIME:
444 if (optlen != 2) {
445 printf(" ?)");
446 break;
447 }
448 memcpy(&val16, dh6o + 1, sizeof(val16));
449 val16 = ntohs(val16);
450 printf(" %d)", (int)val16);
451 break;
452 case DH6OPT_RELAY_MSG:
453 printf(" (");
454 dhcp6_print((const u_char *)(dh6o + 1), optlen);
455 printf(")");
456 break;
457 case DH6OPT_AUTH:
458 if (optlen < sizeof(authopt) - sizeof(*dh6o)) {
459 printf(" ?)");
460 break;
461 }
462 memcpy(&authopt, dh6o, sizeof(authopt));
463 switch (authopt.dh6opt_auth_proto) {
464 case DH6OPT_AUTHPROTO_DELAYED:
465 printf(" proto: delayed");
466 break;
467 case DH6OPT_AUTHPROTO_RECONFIG:
468 printf(" proto: reconfigure");
469 break;
470 default:
471 printf(" proto: %d",
472 authopt.dh6opt_auth_proto);
473 break;
474 }
475 switch (authopt.dh6opt_auth_alg) {
476 case DH6OPT_AUTHALG_HMACMD5:
477 /* XXX: may depend on the protocol */
478 printf(", alg: HMAC-MD5");
479 break;
480 default:
481 printf(", alg: %d", authopt.dh6opt_auth_alg);
482 break;
483 }
484 switch (authopt.dh6opt_auth_rdm) {
485 case DH6OPT_AUTHRDM_MONOCOUNTER:
486 printf(", RDM: mono");
487 break;
488 default:
489 printf(", RDM: %d", authopt.dh6opt_auth_rdm);
490 break;
491 }
492 tp = (u_char *)&authopt.dh6opt_auth_rdinfo;
493 printf(", RD:");
494 for (i = 0; i < 4; i++, tp += sizeof(val16))
495 printf(" %04x", EXTRACT_16BITS(tp));
496
497 /* protocol dependent part */
498 tp = (u_char *)dh6o + sizeof(authopt);
499 authinfolen =
500 optlen + sizeof(*dh6o) - sizeof(authopt);
501 switch (authopt.dh6opt_auth_proto) {
502 case DH6OPT_AUTHPROTO_DELAYED:
503 if (authinfolen == 0)
504 break;
505 if (authinfolen < 20) {
506 printf(" ??");
507 break;
508 }
509 authrealmlen = authinfolen - 20;
510 if (authrealmlen > 0) {
511 printf(", realm: ");
512 }
513 for (i = 0; i < authrealmlen; i++, tp++)
514 printf("%02x", *tp);
515 printf(", key ID: %08x", EXTRACT_32BITS(tp));
516 tp += 4;
517 printf(", HMAC-MD5:");
518 for (i = 0; i < 4; i++, tp+= 4)
519 printf(" %08x", EXTRACT_32BITS(tp));
520 break;
521 case DH6OPT_AUTHPROTO_RECONFIG:
522 if (authinfolen != 17) {
523 printf(" ??");
524 break;
525 }
526 switch (*tp++) {
527 case DH6OPT_AUTHRECONFIG_KEY:
528 printf(" reconfig-key");
529 break;
530 case DH6OPT_AUTHRECONFIG_HMACMD5:
531 printf(" type: HMAC-MD5");
532 break;
533 default:
534 printf(" type: ??");
535 break;
536 }
537 printf(" value:");
538 for (i = 0; i < 4; i++, tp+= 4)
539 printf(" %08x", EXTRACT_32BITS(tp));
540 break;
541 default:
542 printf(" ??");
543 break;
544 }
545
546 printf(")");
547 break;
548 case DH6OPT_RAPID_COMMIT: /* nothing todo */
549 printf(")");
550 break;
551 case DH6OPT_INTERFACE_ID:
552 /*
553 * Since we cannot predict the encoding, print hex dump
554 * at most 10 characters.
555 */
556 for (i = 0; i < optlen && i < 10; i++)
557 printf("%02x", ((u_char *)(dh6o + 1))[i]);
558 break;
559 case DH6OPT_RECONF_MSG:
560 tp = (u_char *)(dh6o + 1);
561 switch (*tp) {
562 case DH6_RENEW:
563 printf(" for renew)");
564 break;
565 case DH6_INFORM_REQ:
566 printf(" for inf-req)");
567 break;
568 default:
569 printf(" for ?\?\?(%02x))", *tp);
570 break;
571 }
572 break;
573 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
574 printf(")");
575 break;
576 case DH6OPT_SIP_SERVER_A:
577 case DH6OPT_DNS:
578 case DH6OPT_NTP_SERVERS:
579 case DH6OPT_NIS_SERVERS:
580 case DH6OPT_NISP_SERVERS:
581 case DH6OPT_BCMCS_SERVER_A:
582 if (optlen % 16) {
583 printf(" ?)");
584 break;
585 }
586 tp = (u_char *)(dh6o + 1);
587 for (i = 0; i < optlen; i += 16)
588 printf(" %s", ip6addr_string(&tp[i]));
589 printf(")");
590 break;
591 case DH6OPT_STATUS_CODE:
592 if (optlen < 2) {
593 printf(" ?)");
594 break;
595 }
596 memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
597 val16 = ntohs(val16);
598 printf(" %s)", dhcp6stcode(val16));
599 break;
600 case DH6OPT_IA_NA:
601 case DH6OPT_IA_PD:
602 if (optlen < sizeof(ia) - 4) {
603 printf(" ?)");
604 break;
605 }
606 memcpy(&ia, (u_char *)dh6o, sizeof(ia));
607 ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid);
608 ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1);
609 ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2);
610 printf(" IAID:%lu T1:%lu T2:%lu",
611 (unsigned long)ia.dh6opt_ia_iaid,
612 (unsigned long)ia.dh6opt_ia_t1,
613 (unsigned long)ia.dh6opt_ia_t2);
614 if (optlen > sizeof(ia) - 4) {
615 /* there are sub-options */
616 dhcp6opt_print((u_char *)dh6o + sizeof(ia),
617 (u_char *)(dh6o + 1) + optlen);
618 }
619 printf(")");
620 break;
621 case DH6OPT_IA_PD_PREFIX:
622 if (optlen < sizeof(ia_prefix) - 4) {
623 printf(" ?)");
624 break;
625 }
626 memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix));
627 printf(" %s/%d",
628 ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr),
629 ia_prefix.dh6opt_ia_prefix_plen);
630 ia_prefix.dh6opt_ia_prefix_pltime =
631 ntohl(ia_prefix.dh6opt_ia_prefix_pltime);
632 ia_prefix.dh6opt_ia_prefix_vltime =
633 ntohl(ia_prefix.dh6opt_ia_prefix_vltime);
634 printf(" pltime:%lu vltime:%lu",
635 (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime,
636 (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime);
637 if (optlen > sizeof(ia_prefix) - 4) {
638 /* there are sub-options */
639 dhcp6opt_print((u_char *)dh6o +
640 sizeof(ia_prefix),
641 (u_char *)(dh6o + 1) + optlen);
642 }
643 printf(")");
644 break;
645 case DH6OPT_LIFETIME:
646 if (optlen != 4) {
647 printf(" ?)");
648 break;
649 }
650 memcpy(&val32, dh6o + 1, sizeof(val32));
651 val32 = ntohl(val32);
652 printf(" %d)", (int)val32);
653 break;
654 default:
655 printf(")");
656 break;
657 }
658
659 cp += sizeof(*dh6o) + optlen;
660 }
661 return;
662
663 trunc:
664 printf("[|dhcp6ext]");
665 }
666
667 /*
668 * Print dhcp6 packets
669 */
670 void
dhcp6_print(const u_char * cp,u_int length)671 dhcp6_print(const u_char *cp, u_int length)
672 {
673 struct dhcp6 *dh6;
674 struct dhcp6_relay *dh6relay;
675 const u_char *ep;
676 u_char *extp;
677 const char *name;
678
679 printf("dhcp6");
680
681 ep = (u_char *)snapend;
682 if (cp + length < ep)
683 ep = cp + length;
684
685 dh6 = (struct dhcp6 *)cp;
686 dh6relay = (struct dhcp6_relay *)cp;
687 TCHECK(dh6->dh6_xid);
688 switch (dh6->dh6_msgtype) {
689 case DH6_SOLICIT:
690 name = "solicit";
691 break;
692 case DH6_ADVERTISE:
693 name = "advertise";
694 break;
695 case DH6_REQUEST:
696 name = "request";
697 break;
698 case DH6_CONFIRM:
699 name = "confirm";
700 break;
701 case DH6_RENEW:
702 name = "renew";
703 break;
704 case DH6_REBIND:
705 name = "rebind";
706 break;
707 case DH6_REPLY:
708 name = "reply";
709 break;
710 case DH6_RELEASE:
711 name = "release";
712 break;
713 case DH6_DECLINE:
714 name = "decline";
715 break;
716 case DH6_RECONFIGURE:
717 name = "reconfigure";
718 break;
719 case DH6_INFORM_REQ:
720 name= "inf-req";
721 break;
722 case DH6_RELAY_FORW:
723 name= "relay-fwd";
724 break;
725 case DH6_RELAY_REPLY:
726 name= "relay-reply";
727 break;
728 default:
729 name = NULL;
730 break;
731 }
732
733 if (!vflag) {
734 if (name)
735 printf(" %s", name);
736 else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
737 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
738 printf(" msgtype-%u", dh6->dh6_msgtype);
739 }
740 return;
741 }
742
743 /* XXX relay agent messages have to be handled differently */
744
745 if (name)
746 printf(" %s (", name); /*)*/
747 else
748 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/
749 if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
750 dh6->dh6_msgtype != DH6_RELAY_REPLY) {
751 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
752 extp = (u_char *)(dh6 + 1);
753 dhcp6opt_print(extp, ep);
754 } else { /* relay messages */
755 struct in6_addr addr6;
756
757 TCHECK(dh6relay->dh6relay_peeraddr);
758
759 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
760 printf("linkaddr=%s", ip6addr_string(&addr6));
761
762 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
763 printf(" peeraddr=%s", ip6addr_string(&addr6));
764
765 dhcp6opt_print((u_char *)(dh6relay + 1), ep);
766 }
767 /*(*/
768 printf(")");
769 return;
770
771 trunc:
772 printf("[|dhcp6]");
773 }
774