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 * 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 * 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 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 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