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