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 * RFC6334: Dual-Stack Lite option, 40 */ 41 42 #ifndef lint 43 static const char rcsid[] _U_ = 44 "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp $"; 45 #endif 46 47 #ifdef HAVE_CONFIG_H 48 #include "config.h" 49 #endif 50 51 #include <tcpdump-stdinc.h> 52 53 #include <stdio.h> 54 #include <string.h> 55 56 #include "interface.h" 57 #include "addrtoname.h" 58 #include "extract.h" 59 60 /* lease duration */ 61 #define DHCP6_DURATITION_INFINITE 0xffffffff 62 63 /* Error Values */ 64 #define DH6ERR_FAILURE 16 65 #define DH6ERR_AUTHFAIL 17 66 #define DH6ERR_POORLYFORMED 18 67 #define DH6ERR_UNAVAIL 19 68 #define DH6ERR_OPTUNAVAIL 20 69 70 /* Message type */ 71 #define DH6_SOLICIT 1 72 #define DH6_ADVERTISE 2 73 #define DH6_REQUEST 3 74 #define DH6_CONFIRM 4 75 #define DH6_RENEW 5 76 #define DH6_REBIND 6 77 #define DH6_REPLY 7 78 #define DH6_RELEASE 8 79 #define DH6_DECLINE 9 80 #define DH6_RECONFIGURE 10 81 #define DH6_INFORM_REQ 11 82 #define DH6_RELAY_FORW 12 83 #define DH6_RELAY_REPLY 13 84 #define DH6_LEASEQUERY 14 85 #define DH6_LQ_REPLY 15 86 87 /* DHCP6 base packet format */ 88 struct dhcp6 { 89 union { 90 u_int8_t m; 91 u_int32_t x; 92 } dh6_msgtypexid; 93 /* options follow */ 94 }; 95 #define dh6_msgtype dh6_msgtypexid.m 96 #define dh6_xid dh6_msgtypexid.x 97 #define DH6_XIDMASK 0x00ffffff 98 99 /* DHCPv6 relay messages */ 100 struct dhcp6_relay { 101 u_int8_t dh6relay_msgtype; 102 u_int8_t dh6relay_hcnt; 103 u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */ 104 u_int8_t dh6relay_peeraddr[16]; 105 /* options follow */ 106 }; 107 108 /* options */ 109 #define DH6OPT_CLIENTID 1 110 #define DH6OPT_SERVERID 2 111 #define DH6OPT_IA_NA 3 112 #define DH6OPT_IA_TA 4 113 #define DH6OPT_IA_ADDR 5 114 #define DH6OPT_ORO 6 115 #define DH6OPT_PREFERENCE 7 116 # define DH6OPT_PREF_MAX 255 117 #define DH6OPT_ELAPSED_TIME 8 118 #define DH6OPT_RELAY_MSG 9 119 /*#define DH6OPT_SERVER_MSG 10 deprecated */ 120 #define DH6OPT_AUTH 11 121 # define DH6OPT_AUTHPROTO_DELAYED 2 122 # define DH6OPT_AUTHPROTO_RECONFIG 3 123 # define DH6OPT_AUTHALG_HMACMD5 1 124 # define DH6OPT_AUTHRDM_MONOCOUNTER 0 125 # define DH6OPT_AUTHRECONFIG_KEY 1 126 # define DH6OPT_AUTHRECONFIG_HMACMD5 2 127 #define DH6OPT_UNICAST 12 128 #define DH6OPT_STATUS_CODE 13 129 # define DH6OPT_STCODE_SUCCESS 0 130 # define DH6OPT_STCODE_UNSPECFAIL 1 131 # define DH6OPT_STCODE_NOADDRAVAIL 2 132 # define DH6OPT_STCODE_NOBINDING 3 133 # define DH6OPT_STCODE_NOTONLINK 4 134 # define DH6OPT_STCODE_USEMULTICAST 5 135 # define DH6OPT_STCODE_NOPREFIXAVAIL 6 136 # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7 137 # define DH6OPT_STCODE_MALFORMEDQUERY 8 138 # define DH6OPT_STCODE_NOTCONFIGURED 9 139 # define DH6OPT_STCODE_NOTALLOWED 10 140 #define DH6OPT_RAPID_COMMIT 14 141 #define DH6OPT_USER_CLASS 15 142 #define DH6OPT_VENDOR_CLASS 16 143 #define DH6OPT_VENDOR_OPTS 17 144 #define DH6OPT_INTERFACE_ID 18 145 #define DH6OPT_RECONF_MSG 19 146 #define DH6OPT_RECONF_ACCEPT 20 147 #define DH6OPT_SIP_SERVER_D 21 148 #define DH6OPT_SIP_SERVER_A 22 149 #define DH6OPT_DNS 23 150 #define DH6OPT_DNSNAME 24 151 #define DH6OPT_IA_PD 25 152 #define DH6OPT_IA_PD_PREFIX 26 153 #define DH6OPT_NIS_SERVERS 27 154 #define DH6OPT_NISP_SERVERS 28 155 #define DH6OPT_NIS_NAME 29 156 #define DH6OPT_NISP_NAME 30 157 #define DH6OPT_NTP_SERVERS 31 158 #define DH6OPT_LIFETIME 32 159 #define DH6OPT_BCMCS_SERVER_D 33 160 #define DH6OPT_BCMCS_SERVER_A 34 161 #define DH6OPT_GEOCONF_CIVIC 36 162 #define DH6OPT_REMOTE_ID 37 163 #define DH6OPT_SUBSCRIBER_ID 38 164 #define DH6OPT_CLIENT_FQDN 39 165 #define DH6OPT_PANA_AGENT 40 166 #define DH6OPT_NEW_POSIX_TIMEZONE 41 167 #define DH6OPT_NEW_TZDB_TIMEZONE 42 168 #define DH6OPT_ERO 43 169 #define DH6OPT_LQ_QUERY 44 170 #define DH6OPT_CLIENT_DATA 45 171 #define DH6OPT_CLT_TIME 46 172 #define DH6OPT_LQ_RELAY_DATA 47 173 #define DH6OPT_LQ_CLIENT_LINK 48 174 #define DH6OPT_AFTR_NAME 64 175 176 struct dhcp6opt { 177 u_int16_t dh6opt_type; 178 u_int16_t dh6opt_len; 179 /* type-dependent data follows */ 180 }; 181 182 static const char * 183 dhcp6opt_name(int type) 184 { 185 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ 186 187 if (type > 65535) 188 return "INVALID-option"; 189 190 switch(type) { 191 case DH6OPT_CLIENTID: 192 return "client-ID"; 193 case DH6OPT_SERVERID: 194 return "server-ID"; 195 case DH6OPT_IA_NA: 196 return "IA_NA"; 197 case DH6OPT_IA_TA: 198 return "IA_TA"; 199 case DH6OPT_IA_ADDR: 200 return "IA_ADDR"; 201 case DH6OPT_ORO: 202 return "option-request"; 203 case DH6OPT_PREFERENCE: 204 return "preference"; 205 case DH6OPT_ELAPSED_TIME: 206 return "elapsed-time"; 207 case DH6OPT_RELAY_MSG: 208 return "relay-message"; 209 case DH6OPT_AUTH: 210 return "authentication"; 211 case DH6OPT_UNICAST: 212 return "server-unicast"; 213 case DH6OPT_STATUS_CODE: 214 return "status-code"; 215 case DH6OPT_RAPID_COMMIT: 216 return "rapid-commit"; 217 case DH6OPT_USER_CLASS: 218 return "user-class"; 219 case DH6OPT_VENDOR_CLASS: 220 return "vendor-class"; 221 case DH6OPT_VENDOR_OPTS: 222 return "vendor-specific-info"; 223 case DH6OPT_INTERFACE_ID: 224 return "interface-ID"; 225 case DH6OPT_RECONF_MSG: 226 return "reconfigure-message"; 227 case DH6OPT_RECONF_ACCEPT: 228 return "reconfigure-accept"; 229 case DH6OPT_SIP_SERVER_D: 230 return "SIP-servers-domain"; 231 case DH6OPT_SIP_SERVER_A: 232 return "SIP-servers-address"; 233 case DH6OPT_DNS: 234 return "DNS-server"; 235 case DH6OPT_DNSNAME: 236 return "DNS-search-list"; 237 case DH6OPT_IA_PD: 238 return "IA_PD"; 239 case DH6OPT_IA_PD_PREFIX: 240 return "IA_PD-prefix"; 241 case DH6OPT_NTP_SERVERS: 242 return "NTP-server"; 243 case DH6OPT_LIFETIME: 244 return "lifetime"; 245 case DH6OPT_NIS_SERVERS: 246 return "NIS-server"; 247 case DH6OPT_NISP_SERVERS: 248 return "NIS+-server"; 249 case DH6OPT_NIS_NAME: 250 return "NIS-domain-name"; 251 case DH6OPT_NISP_NAME: 252 return "NIS+-domain-name"; 253 case DH6OPT_BCMCS_SERVER_D: 254 return "BCMCS-domain-name"; 255 case DH6OPT_BCMCS_SERVER_A: 256 return "BCMCS-server"; 257 case DH6OPT_GEOCONF_CIVIC: 258 return "Geoconf-Civic"; 259 case DH6OPT_REMOTE_ID: 260 return "Remote-ID"; 261 case DH6OPT_SUBSCRIBER_ID: 262 return "Subscriber-ID"; 263 case DH6OPT_CLIENT_FQDN: 264 return "Client-FQDN"; 265 case DH6OPT_PANA_AGENT: 266 return "PANA-agent"; 267 case DH6OPT_NEW_POSIX_TIMEZONE: 268 return "POSIX-timezone"; 269 case DH6OPT_NEW_TZDB_TIMEZONE: 270 return "POSIX-tz-database"; 271 case DH6OPT_ERO: 272 return "Echo-request-option"; 273 case DH6OPT_LQ_QUERY: 274 return "Lease-query"; 275 case DH6OPT_CLIENT_DATA: 276 return "LQ-client-data"; 277 case DH6OPT_CLT_TIME: 278 return "Clt-time"; 279 case DH6OPT_LQ_RELAY_DATA: 280 return "LQ-relay-data"; 281 case DH6OPT_LQ_CLIENT_LINK: 282 return "LQ-client-link"; 283 case DH6OPT_AFTR_NAME: 284 return "AFTR-Name"; 285 default: 286 snprintf(genstr, sizeof(genstr), "opt_%d", type); 287 return(genstr); 288 } 289 } 290 291 static const char * 292 dhcp6stcode(int code) 293 { 294 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ 295 296 if (code > 255) 297 return "INVALID code"; 298 299 switch(code) { 300 case DH6OPT_STCODE_SUCCESS: 301 return "success"; 302 case DH6OPT_STCODE_UNSPECFAIL: 303 return "unspec failure"; 304 case DH6OPT_STCODE_NOADDRAVAIL: 305 return "no addresses"; 306 case DH6OPT_STCODE_NOBINDING: 307 return "no binding"; 308 case DH6OPT_STCODE_NOTONLINK: 309 return "not on-link"; 310 case DH6OPT_STCODE_USEMULTICAST: 311 return "use multicast"; 312 case DH6OPT_STCODE_NOPREFIXAVAIL: 313 return "no prefixes"; 314 case DH6OPT_STCODE_UNKNOWNQUERYTYPE: 315 return "unknown query type"; 316 case DH6OPT_STCODE_MALFORMEDQUERY: 317 return "malformed query"; 318 case DH6OPT_STCODE_NOTCONFIGURED: 319 return "not configured"; 320 case DH6OPT_STCODE_NOTALLOWED: 321 return "not allowed"; 322 default: 323 snprintf(genstr, sizeof(genstr), "code%d", code); 324 return(genstr); 325 } 326 } 327 328 static void 329 dhcp6opt_print(const u_char *cp, const u_char *ep) 330 { 331 struct dhcp6opt *dh6o; 332 u_char *tp; 333 size_t i; 334 u_int16_t opttype; 335 size_t optlen; 336 u_int8_t auth_proto; 337 u_int authinfolen, authrealmlen; 338 339 if (cp == ep) 340 return; 341 while (cp < ep) { 342 if (ep < cp + sizeof(*dh6o)) 343 goto trunc; 344 dh6o = (struct dhcp6opt *)cp; 345 TCHECK(*dh6o); 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 + 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 + 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 + 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 + 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 case DH6OPT_AFTR_NAME: 721 if (optlen < 3) { 722 printf(" ?)"); 723 break; 724 } 725 tp = (u_char *)(dh6o + 1); 726 int remain_len = optlen; 727 printf(" "); 728 /* Encoding is described in section 3.1 of RFC 1035 */ 729 int label_len; /* Label length */ 730 while (remain_len && *tp) { 731 label_len = *tp++; 732 if (label_len < remain_len - 1) { 733 printf("%.*s", label_len, tp); 734 tp += label_len; 735 remain_len -= (label_len + 1); 736 if(*tp) printf("."); 737 } else { 738 printf(" ?"); 739 break; 740 } 741 } 742 printf(")"); 743 break; 744 default: 745 printf(")"); 746 break; 747 } 748 749 cp += sizeof(*dh6o) + optlen; 750 } 751 return; 752 753 trunc: 754 printf("[|dhcp6ext]"); 755 } 756 757 /* 758 * Print dhcp6 packets 759 */ 760 void 761 dhcp6_print(const u_char *cp, u_int length) 762 { 763 struct dhcp6 *dh6; 764 struct dhcp6_relay *dh6relay; 765 const u_char *ep; 766 u_char *extp; 767 const char *name; 768 769 printf("dhcp6"); 770 771 ep = (u_char *)snapend; 772 if (cp + length < ep) 773 ep = cp + length; 774 775 dh6 = (struct dhcp6 *)cp; 776 dh6relay = (struct dhcp6_relay *)cp; 777 TCHECK(dh6->dh6_xid); 778 switch (dh6->dh6_msgtype) { 779 case DH6_SOLICIT: 780 name = "solicit"; 781 break; 782 case DH6_ADVERTISE: 783 name = "advertise"; 784 break; 785 case DH6_REQUEST: 786 name = "request"; 787 break; 788 case DH6_CONFIRM: 789 name = "confirm"; 790 break; 791 case DH6_RENEW: 792 name = "renew"; 793 break; 794 case DH6_REBIND: 795 name = "rebind"; 796 break; 797 case DH6_REPLY: 798 name = "reply"; 799 break; 800 case DH6_RELEASE: 801 name = "release"; 802 break; 803 case DH6_DECLINE: 804 name = "decline"; 805 break; 806 case DH6_RECONFIGURE: 807 name = "reconfigure"; 808 break; 809 case DH6_INFORM_REQ: 810 name= "inf-req"; 811 break; 812 case DH6_RELAY_FORW: 813 name= "relay-fwd"; 814 break; 815 case DH6_RELAY_REPLY: 816 name= "relay-reply"; 817 break; 818 case DH6_LEASEQUERY: 819 name= "leasequery"; 820 break; 821 case DH6_LQ_REPLY: 822 name= "leasequery-reply"; 823 break; 824 default: 825 name = NULL; 826 break; 827 } 828 829 if (!vflag) { 830 if (name) 831 printf(" %s", name); 832 else if (dh6->dh6_msgtype != DH6_RELAY_FORW && 833 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 834 printf(" msgtype-%u", dh6->dh6_msgtype); 835 } 836 return; 837 } 838 839 /* XXX relay agent messages have to be handled differently */ 840 841 if (name) 842 printf(" %s (", name); /*)*/ 843 else 844 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ 845 if (dh6->dh6_msgtype != DH6_RELAY_FORW && 846 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 847 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); 848 extp = (u_char *)(dh6 + 1); 849 dhcp6opt_print(extp, ep); 850 } else { /* relay messages */ 851 struct in6_addr addr6; 852 853 TCHECK(dh6relay->dh6relay_peeraddr); 854 855 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 856 printf("linkaddr=%s", ip6addr_string(&addr6)); 857 858 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 859 printf(" peeraddr=%s", ip6addr_string(&addr6)); 860 861 dhcp6opt_print((u_char *)(dh6relay + 1), ep); 862 } 863 /*(*/ 864 printf(")"); 865 return; 866 867 trunc: 868 printf("[|dhcp6]"); 869 } 870