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