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#include <sys/cdefs.h> 42#ifndef lint 43#if 0 44static const char rcsid[] _U_ = 45 "@(#) Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp"; 46#else 47__RCSID("$NetBSD$"); 48#endif 49#endif 50 51#ifdef HAVE_CONFIG_H 52#include "config.h" 53#endif 54 55#include <tcpdump-stdinc.h> 56 57#include <stdio.h> 58#include <string.h> 59 60#include "interface.h" 61#include "addrtoname.h" 62#include "extract.h" 63 64/* lease duration */ 65#define DHCP6_DURATITION_INFINITE 0xffffffff 66 67/* Error Values */ 68#define DH6ERR_FAILURE 16 69#define DH6ERR_AUTHFAIL 17 70#define DH6ERR_POORLYFORMED 18 71#define DH6ERR_UNAVAIL 19 72#define DH6ERR_OPTUNAVAIL 20 73 74/* Message type */ 75#define DH6_SOLICIT 1 76#define DH6_ADVERTISE 2 77#define DH6_REQUEST 3 78#define DH6_CONFIRM 4 79#define DH6_RENEW 5 80#define DH6_REBIND 6 81#define DH6_REPLY 7 82#define DH6_RELEASE 8 83#define DH6_DECLINE 9 84#define DH6_RECONFIGURE 10 85#define DH6_INFORM_REQ 11 86#define DH6_RELAY_FORW 12 87#define DH6_RELAY_REPLY 13 88#define DH6_LEASEQUERY 14 89#define DH6_LQ_REPLY 15 90 91/* DHCP6 base packet format */ 92struct dhcp6 { 93 union { 94 u_int8_t m; 95 u_int32_t x; 96 } dh6_msgtypexid; 97 /* options follow */ 98}; 99#define dh6_msgtype dh6_msgtypexid.m 100#define dh6_xid dh6_msgtypexid.x 101#define DH6_XIDMASK 0x00ffffff 102 103/* DHCPv6 relay messages */ 104struct dhcp6_relay { 105 u_int8_t dh6relay_msgtype; 106 u_int8_t dh6relay_hcnt; 107 u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */ 108 u_int8_t dh6relay_peeraddr[16]; 109 /* options follow */ 110}; 111 112/* options */ 113#define DH6OPT_CLIENTID 1 114#define DH6OPT_SERVERID 2 115#define DH6OPT_IA_NA 3 116#define DH6OPT_IA_TA 4 117#define DH6OPT_IA_ADDR 5 118#define DH6OPT_ORO 6 119#define DH6OPT_PREFERENCE 7 120# define DH6OPT_PREF_MAX 255 121#define DH6OPT_ELAPSED_TIME 8 122#define DH6OPT_RELAY_MSG 9 123/*#define DH6OPT_SERVER_MSG 10 deprecated */ 124#define DH6OPT_AUTH 11 125# define DH6OPT_AUTHPROTO_DELAYED 2 126# define DH6OPT_AUTHPROTO_RECONFIG 3 127# define DH6OPT_AUTHALG_HMACMD5 1 128# define DH6OPT_AUTHRDM_MONOCOUNTER 0 129# define DH6OPT_AUTHRECONFIG_KEY 1 130# define DH6OPT_AUTHRECONFIG_HMACMD5 2 131#define DH6OPT_UNICAST 12 132#define DH6OPT_STATUS_CODE 13 133# define DH6OPT_STCODE_SUCCESS 0 134# define DH6OPT_STCODE_UNSPECFAIL 1 135# define DH6OPT_STCODE_NOADDRAVAIL 2 136# define DH6OPT_STCODE_NOBINDING 3 137# define DH6OPT_STCODE_NOTONLINK 4 138# define DH6OPT_STCODE_USEMULTICAST 5 139# define DH6OPT_STCODE_NOPREFIXAVAIL 6 140# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7 141# define DH6OPT_STCODE_MALFORMEDQUERY 8 142# define DH6OPT_STCODE_NOTCONFIGURED 9 143# define DH6OPT_STCODE_NOTALLOWED 10 144#define DH6OPT_RAPID_COMMIT 14 145#define DH6OPT_USER_CLASS 15 146#define DH6OPT_VENDOR_CLASS 16 147#define DH6OPT_VENDOR_OPTS 17 148#define DH6OPT_INTERFACE_ID 18 149#define DH6OPT_RECONF_MSG 19 150#define DH6OPT_RECONF_ACCEPT 20 151#define DH6OPT_SIP_SERVER_D 21 152#define DH6OPT_SIP_SERVER_A 22 153#define DH6OPT_DNS 23 154#define DH6OPT_DNSNAME 24 155#define DH6OPT_IA_PD 25 156#define DH6OPT_IA_PD_PREFIX 26 157#define DH6OPT_NIS_SERVERS 27 158#define DH6OPT_NISP_SERVERS 28 159#define DH6OPT_NIS_NAME 29 160#define DH6OPT_NISP_NAME 30 161#define DH6OPT_NTP_SERVERS 31 162#define DH6OPT_LIFETIME 32 163#define DH6OPT_BCMCS_SERVER_D 33 164#define DH6OPT_BCMCS_SERVER_A 34 165#define DH6OPT_GEOCONF_CIVIC 36 166#define DH6OPT_REMOTE_ID 37 167#define DH6OPT_SUBSCRIBER_ID 38 168#define DH6OPT_CLIENT_FQDN 39 169#define DH6OPT_PANA_AGENT 40 170#define DH6OPT_NEW_POSIX_TIMEZONE 41 171#define DH6OPT_NEW_TZDB_TIMEZONE 42 172#define DH6OPT_ERO 43 173#define DH6OPT_LQ_QUERY 44 174#define DH6OPT_CLIENT_DATA 45 175#define DH6OPT_CLT_TIME 46 176#define DH6OPT_LQ_RELAY_DATA 47 177#define DH6OPT_LQ_CLIENT_LINK 48 178 179struct dhcp6opt { 180 u_int16_t dh6opt_type; 181 u_int16_t dh6opt_len; 182 /* type-dependent data follows */ 183}; 184 185static const char * 186dhcp6opt_name(int type) 187{ 188 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ 189 190 if (type > 65535) 191 return "INVALID-option"; 192 193 switch(type) { 194 case DH6OPT_CLIENTID: 195 return "client-ID"; 196 case DH6OPT_SERVERID: 197 return "server-ID"; 198 case DH6OPT_IA_NA: 199 return "IA_NA"; 200 case DH6OPT_IA_TA: 201 return "IA_TA"; 202 case DH6OPT_IA_ADDR: 203 return "IA_ADDR"; 204 case DH6OPT_ORO: 205 return "option-request"; 206 case DH6OPT_PREFERENCE: 207 return "preference"; 208 case DH6OPT_ELAPSED_TIME: 209 return "elapsed-time"; 210 case DH6OPT_RELAY_MSG: 211 return "relay-message"; 212 case DH6OPT_AUTH: 213 return "authentication"; 214 case DH6OPT_UNICAST: 215 return "server-unicast"; 216 case DH6OPT_STATUS_CODE: 217 return "status-code"; 218 case DH6OPT_RAPID_COMMIT: 219 return "rapid-commit"; 220 case DH6OPT_USER_CLASS: 221 return "user-class"; 222 case DH6OPT_VENDOR_CLASS: 223 return "vendor-class"; 224 case DH6OPT_VENDOR_OPTS: 225 return "vendor-specific-info"; 226 case DH6OPT_INTERFACE_ID: 227 return "interface-ID"; 228 case DH6OPT_RECONF_MSG: 229 return "reconfigure-message"; 230 case DH6OPT_RECONF_ACCEPT: 231 return "reconfigure-accept"; 232 case DH6OPT_SIP_SERVER_D: 233 return "SIP-servers-domain"; 234 case DH6OPT_SIP_SERVER_A: 235 return "SIP-servers-address"; 236 case DH6OPT_DNS: 237 return "DNS"; 238 case DH6OPT_DNSNAME: 239 return "DNS-name"; 240 case DH6OPT_IA_PD: 241 return "IA_PD"; 242 case DH6OPT_IA_PD_PREFIX: 243 return "IA_PD-prefix"; 244 case DH6OPT_NTP_SERVERS: 245 return "NTP-Server"; 246 case DH6OPT_LIFETIME: 247 return "lifetime"; 248 case DH6OPT_NIS_SERVERS: 249 return "NIS-server"; 250 case DH6OPT_NISP_SERVERS: 251 return "NIS+-server"; 252 case DH6OPT_NIS_NAME: 253 return "NIS-domain-name"; 254 case DH6OPT_NISP_NAME: 255 return "NIS+-domain-name"; 256 case DH6OPT_BCMCS_SERVER_D: 257 return "BCMCS-domain-name"; 258 case DH6OPT_BCMCS_SERVER_A: 259 return "BCMCS-server"; 260 case DH6OPT_GEOCONF_CIVIC: 261 return "Geoconf-Civic"; 262 case DH6OPT_REMOTE_ID: 263 return "Remote-ID"; 264 case DH6OPT_SUBSCRIBER_ID: 265 return "Subscriber-ID"; 266 case DH6OPT_CLIENT_FQDN: 267 return "Client-FQDN"; 268 case DH6OPT_PANA_AGENT: 269 return "PANA-agent"; 270 case DH6OPT_NEW_POSIX_TIMEZONE: 271 return "POSIX-timezone"; 272 case DH6OPT_NEW_TZDB_TIMEZONE: 273 return "POSIX-tz-database"; 274 case DH6OPT_ERO: 275 return "Echo-request-option"; 276 case DH6OPT_LQ_QUERY: 277 return "Lease-query"; 278 case DH6OPT_CLIENT_DATA: 279 return "LQ-client-data"; 280 case DH6OPT_CLT_TIME: 281 return "Clt-time"; 282 case DH6OPT_LQ_RELAY_DATA: 283 return "LQ-relay-data"; 284 case DH6OPT_LQ_CLIENT_LINK: 285 return "LQ-client-link"; 286 default: 287 snprintf(genstr, sizeof(genstr), "opt_%d", type); 288 return(genstr); 289 } 290} 291 292static const char * 293dhcp6stcode(int code) 294{ 295 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ 296 297 if (code > 255) 298 return "INVALID code"; 299 300 switch(code) { 301 case DH6OPT_STCODE_SUCCESS: 302 return "success"; 303 case DH6OPT_STCODE_UNSPECFAIL: 304 return "unspec failure"; 305 case DH6OPT_STCODE_NOADDRAVAIL: 306 return "no addresses"; 307 case DH6OPT_STCODE_NOBINDING: 308 return "no binding"; 309 case DH6OPT_STCODE_NOTONLINK: 310 return "not on-link"; 311 case DH6OPT_STCODE_USEMULTICAST: 312 return "use multicast"; 313 case DH6OPT_STCODE_NOPREFIXAVAIL: 314 return "no prefixes"; 315 case DH6OPT_STCODE_UNKNOWNQUERYTYPE: 316 return "unknown query type"; 317 case DH6OPT_STCODE_MALFORMEDQUERY: 318 return "malformed query"; 319 case DH6OPT_STCODE_NOTCONFIGURED: 320 return "not configured"; 321 case DH6OPT_STCODE_NOTALLOWED: 322 return "not allowed"; 323 default: 324 snprintf(genstr, sizeof(genstr), "code%d", code); 325 return(genstr); 326 } 327} 328 329static void 330dhcp6opt_print(const u_char *cp, const u_char *ep) 331{ 332 struct dhcp6opt *dh6o; 333 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 340 if (cp == ep) 341 return; 342 while (cp < ep) { 343 if (ep < cp + sizeof(*dh6o)) 344 goto trunc; 345 dh6o = (struct dhcp6opt *)cp; 346 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); 347 if (ep < cp + sizeof(*dh6o) + optlen) 348 goto trunc; 349 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); 350 printf(" (%s", dhcp6opt_name(opttype)); 351 switch (opttype) { 352 case DH6OPT_CLIENTID: 353 case DH6OPT_SERVERID: 354 if (optlen < 2) { 355 /*(*/ 356 printf(" ?)"); 357 break; 358 } 359 tp = (u_char *)(dh6o + 1); 360 switch (EXTRACT_16BITS(tp)) { 361 case 1: 362 if (optlen >= 2 + 6) { 363 printf(" hwaddr/time type %u time %u ", 364 EXTRACT_16BITS(&tp[2]), 365 EXTRACT_32BITS(&tp[4])); 366 for (i = 8; i < optlen; i++) 367 printf("%02x", tp[i]); 368 /*(*/ 369 printf(")"); 370 } else { 371 /*(*/ 372 printf(" ?)"); 373 } 374 break; 375 case 2: 376 if (optlen >= 2 + 8) { 377 printf(" vid "); 378 for (i = 2; i < 2 + 8; i++) 379 printf("%02x", tp[i]); 380 /*(*/ 381 printf(")"); 382 } else { 383 /*(*/ 384 printf(" ?)"); 385 } 386 break; 387 case 3: 388 if (optlen >= 2 + 2) { 389 printf(" hwaddr type %u ", 390 EXTRACT_16BITS(&tp[2])); 391 for (i = 4; i < optlen; i++) 392 printf("%02x", tp[i]); 393 /*(*/ 394 printf(")"); 395 } else { 396 /*(*/ 397 printf(" ?)"); 398 } 399 break; 400 default: 401 printf(" type %d)", EXTRACT_16BITS(tp)); 402 break; 403 } 404 break; 405 case DH6OPT_IA_ADDR: 406 if (optlen < 24) { 407 /*(*/ 408 printf(" ?)"); 409 break; 410 } 411 tp = (u_char *)(dh6o + 1); 412 printf(" %s", ip6addr_string(&tp[0])); 413 printf(" pltime:%u vltime:%u", 414 EXTRACT_32BITS(&tp[16]), 415 EXTRACT_32BITS(&tp[20])); 416 if (optlen > 24) { 417 /* there are sub-options */ 418 dhcp6opt_print(tp + 24, tp + 24 + optlen); 419 } 420 printf(")"); 421 break; 422 case DH6OPT_ORO: 423 case DH6OPT_ERO: 424 if (optlen % 2) { 425 printf(" ?)"); 426 break; 427 } 428 tp = (u_char *)(dh6o + 1); 429 for (i = 0; i < optlen; i += 2) { 430 printf(" %s", 431 dhcp6opt_name(EXTRACT_16BITS(&tp[i]))); 432 } 433 printf(")"); 434 break; 435 case DH6OPT_PREFERENCE: 436 if (optlen != 1) { 437 printf(" ?)"); 438 break; 439 } 440 tp = (u_char *)(dh6o + 1); 441 printf(" %d)", *tp); 442 break; 443 case DH6OPT_ELAPSED_TIME: 444 if (optlen != 2) { 445 printf(" ?)"); 446 break; 447 } 448 tp = (u_char *)(dh6o + 1); 449 printf(" %d)", EXTRACT_16BITS(tp)); 450 break; 451 case DH6OPT_RELAY_MSG: 452 printf(" ("); 453 tp = (u_char *)(dh6o + 1); 454 dhcp6_print(tp, optlen); 455 printf(")"); 456 break; 457 case DH6OPT_AUTH: 458 if (optlen < 11) { 459 printf(" ?)"); 460 break; 461 } 462 tp = (u_char *)(dh6o + 1); 463 auth_proto = *tp; 464 switch (auth_proto) { 465 case DH6OPT_AUTHPROTO_DELAYED: 466 printf(" proto: delayed"); 467 break; 468 case DH6OPT_AUTHPROTO_RECONFIG: 469 printf(" proto: reconfigure"); 470 break; 471 default: 472 printf(" proto: %d", auth_proto); 473 break; 474 } 475 tp++; 476 switch (*tp) { 477 case DH6OPT_AUTHALG_HMACMD5: 478 /* XXX: may depend on the protocol */ 479 printf(", alg: HMAC-MD5"); 480 break; 481 default: 482 printf(", alg: %d", *tp); 483 break; 484 } 485 tp++; 486 switch (*tp) { 487 case DH6OPT_AUTHRDM_MONOCOUNTER: 488 printf(", RDM: mono"); 489 break; 490 default: 491 printf(", RDM: %d", *tp); 492 break; 493 } 494 tp++; 495 printf(", RD:"); 496 for (i = 0; i < 4; i++, tp += 2) 497 printf(" %04x", EXTRACT_16BITS(tp)); 498 499 /* protocol dependent part */ 500 authinfolen = optlen - 11; 501 switch (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 case DH6OPT_SUBSCRIBER_ID: 553 /* 554 * Since we cannot predict the encoding, print hex dump 555 * at most 10 characters. 556 */ 557 tp = (u_char *)(dh6o + 1); 558 printf(" "); 559 for (i = 0; i < optlen && i < 10; i++) 560 printf("%02x", tp[i]); 561 printf("...)"); 562 break; 563 case DH6OPT_RECONF_MSG: 564 tp = (u_char *)(dh6o + 1); 565 switch (*tp) { 566 case DH6_RENEW: 567 printf(" for renew)"); 568 break; 569 case DH6_INFORM_REQ: 570 printf(" for inf-req)"); 571 break; 572 default: 573 printf(" for ?\?\?(%02x))", *tp); 574 break; 575 } 576 break; 577 case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 578 printf(")"); 579 break; 580 case DH6OPT_SIP_SERVER_A: 581 case DH6OPT_DNS: 582 case DH6OPT_NTP_SERVERS: 583 case DH6OPT_NIS_SERVERS: 584 case DH6OPT_NISP_SERVERS: 585 case DH6OPT_BCMCS_SERVER_A: 586 case DH6OPT_PANA_AGENT: 587 case DH6OPT_LQ_CLIENT_LINK: 588 if (optlen % 16) { 589 printf(" ?)"); 590 break; 591 } 592 tp = (u_char *)(dh6o + 1); 593 for (i = 0; i < optlen; i += 16) 594 printf(" %s", ip6addr_string(&tp[i])); 595 printf(")"); 596 break; 597 case DH6OPT_STATUS_CODE: 598 if (optlen < 2) { 599 printf(" ?)"); 600 break; 601 } 602 tp = (u_char *)(dh6o + 1); 603 printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))); 604 break; 605 case DH6OPT_IA_NA: 606 case DH6OPT_IA_PD: 607 if (optlen < 12) { 608 printf(" ?)"); 609 break; 610 } 611 tp = (u_char *)(dh6o + 1); 612 printf(" IAID:%u T1:%u T2:%u", 613 EXTRACT_32BITS(&tp[0]), 614 EXTRACT_32BITS(&tp[4]), 615 EXTRACT_32BITS(&tp[8])); 616 if (optlen > 12) { 617 /* there are sub-options */ 618 dhcp6opt_print(tp + 12, tp + 12 + optlen); 619 } 620 printf(")"); 621 break; 622 case DH6OPT_IA_TA: 623 if (optlen < 4) { 624 printf(" ?)"); 625 break; 626 } 627 tp = (u_char *)(dh6o + 1); 628 printf(" IAID:%u", EXTRACT_32BITS(tp)); 629 if (optlen > 4) { 630 /* there are sub-options */ 631 dhcp6opt_print(tp + 4, tp + 4 + optlen); 632 } 633 printf(")"); 634 break; 635 case DH6OPT_IA_PD_PREFIX: 636 if (optlen < 25) { 637 printf(" ?)"); 638 break; 639 } 640 tp = (u_char *)(dh6o + 1); 641 printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]); 642 printf(" pltime:%u vltime:%u", 643 EXTRACT_32BITS(&tp[0]), 644 EXTRACT_32BITS(&tp[4])); 645 if (optlen > 25) { 646 /* there are sub-options */ 647 dhcp6opt_print(tp + 25, tp + 25 + optlen); 648 } 649 printf(")"); 650 break; 651 case DH6OPT_LIFETIME: 652 case DH6OPT_CLT_TIME: 653 if (optlen != 4) { 654 printf(" ?)"); 655 break; 656 } 657 tp = (u_char *)(dh6o + 1); 658 printf(" %d)", EXTRACT_32BITS(tp)); 659 break; 660 case DH6OPT_REMOTE_ID: 661 if (optlen < 4) { 662 printf(" ?)"); 663 break; 664 } 665 tp = (u_char *)(dh6o + 1); 666 printf(" %d ", EXTRACT_32BITS(tp)); 667 /* 668 * Print hex dump first 10 characters. 669 */ 670 for (i = 4; i < optlen && i < 14; i++) 671 printf("%02x", tp[i]); 672 printf("...)"); 673 break; 674 case DH6OPT_LQ_QUERY: 675 if (optlen < 17) { 676 printf(" ?)"); 677 break; 678 } 679 tp = (u_char *)(dh6o + 1); 680 switch (*tp) { 681 case 1: 682 printf(" by-address"); 683 break; 684 case 2: 685 printf(" by-clientID"); 686 break; 687 default: 688 printf(" type_%d", (int)*tp); 689 break; 690 } 691 printf(" %s", ip6addr_string(&tp[1])); 692 if (optlen > 17) { 693 /* there are query-options */ 694 dhcp6opt_print(tp + 17, tp + optlen); 695 } 696 printf(")"); 697 break; 698 case DH6OPT_CLIENT_DATA: 699 tp = (u_char *)(dh6o + 1); 700 if (optlen > 0) { 701 /* there are encapsulated options */ 702 dhcp6opt_print(tp, tp + optlen); 703 } 704 printf(")"); 705 break; 706 case DH6OPT_LQ_RELAY_DATA: 707 if (optlen < 16) { 708 printf(" ?)"); 709 break; 710 } 711 tp = (u_char *)(dh6o + 1); 712 printf(" %s ", ip6addr_string(&tp[0])); 713 /* 714 * Print hex dump first 10 characters. 715 */ 716 for (i = 16; i < optlen && i < 26; i++) 717 printf("%02x", tp[i]); 718 printf("...)"); 719 break; 720 default: 721 printf(")"); 722 break; 723 } 724 725 cp += sizeof(*dh6o) + optlen; 726 } 727 return; 728 729trunc: 730 printf("[|dhcp6ext]"); 731} 732 733/* 734 * Print dhcp6 packets 735 */ 736void 737dhcp6_print(const u_char *cp, u_int length) 738{ 739 struct dhcp6 *dh6; 740 struct dhcp6_relay *dh6relay; 741 const u_char *ep; 742 u_char *extp; 743 const char *name; 744 745 printf("dhcp6"); 746 747 ep = (u_char *)snapend; 748 if (cp + length < ep) 749 ep = cp + length; 750 751 dh6 = (struct dhcp6 *)cp; 752 dh6relay = (struct dhcp6_relay *)cp; 753 TCHECK(dh6->dh6_xid); 754 switch (dh6->dh6_msgtype) { 755 case DH6_SOLICIT: 756 name = "solicit"; 757 break; 758 case DH6_ADVERTISE: 759 name = "advertise"; 760 break; 761 case DH6_REQUEST: 762 name = "request"; 763 break; 764 case DH6_CONFIRM: 765 name = "confirm"; 766 break; 767 case DH6_RENEW: 768 name = "renew"; 769 break; 770 case DH6_REBIND: 771 name = "rebind"; 772 break; 773 case DH6_REPLY: 774 name = "reply"; 775 break; 776 case DH6_RELEASE: 777 name = "release"; 778 break; 779 case DH6_DECLINE: 780 name = "decline"; 781 break; 782 case DH6_RECONFIGURE: 783 name = "reconfigure"; 784 break; 785 case DH6_INFORM_REQ: 786 name= "inf-req"; 787 break; 788 case DH6_RELAY_FORW: 789 name= "relay-fwd"; 790 break; 791 case DH6_RELAY_REPLY: 792 name= "relay-reply"; 793 break; 794 case DH6_LEASEQUERY: 795 name= "leasequery"; 796 break; 797 case DH6_LQ_REPLY: 798 name= "leasequery-reply"; 799 break; 800 default: 801 name = NULL; 802 break; 803 } 804 805 if (!vflag) { 806 if (name) 807 printf(" %s", name); 808 else if (dh6->dh6_msgtype != DH6_RELAY_FORW && 809 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 810 printf(" msgtype-%u", dh6->dh6_msgtype); 811 } 812 return; 813 } 814 815 /* XXX relay agent messages have to be handled differently */ 816 817 if (name) 818 printf(" %s (", name); /*)*/ 819 else 820 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ 821 if (dh6->dh6_msgtype != DH6_RELAY_FORW && 822 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 823 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); 824 extp = (u_char *)(dh6 + 1); 825 dhcp6opt_print(extp, ep); 826 } else { /* relay messages */ 827 struct in6_addr addr6; 828 829 TCHECK(dh6relay->dh6relay_peeraddr); 830 831 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 832 printf("linkaddr=%s", ip6addr_string(&addr6)); 833 834 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 835 printf(" peeraddr=%s", ip6addr_string(&addr6)); 836 837 dhcp6opt_print((u_char *)(dh6relay + 1), ep); 838 } 839 /*(*/ 840 printf(")"); 841 return; 842 843trunc: 844 printf("[|dhcp6]"); 845} 846