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