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.36.2.1 2008-02-06 10:26:27 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 struct dhcp6_ia { 181 u_int16_t dh6opt_ia_type; 182 u_int16_t dh6opt_ia_len; 183 u_int32_t dh6opt_ia_iaid; 184 u_int32_t dh6opt_ia_t1; 185 u_int32_t dh6opt_ia_t2; 186 }; 187 188 struct dhcp6_ia_addr { 189 u_int16_t dh6opt_ia_addr_type; 190 u_int16_t dh6opt_ia_addr_len; 191 struct in6_addr dh6opt_ia_addr_addr; 192 u_int32_t dh6opt_ia_addr_pltime; 193 u_int32_t dh6opt_ia_addr_vltime; 194 } __attribute__ ((__packed__)); 195 196 struct dhcp6_ia_prefix { 197 u_int16_t dh6opt_ia_prefix_type; 198 u_int16_t dh6opt_ia_prefix_len; 199 u_int32_t dh6opt_ia_prefix_pltime; 200 u_int32_t dh6opt_ia_prefix_vltime; 201 u_int8_t dh6opt_ia_prefix_plen; 202 struct in6_addr dh6opt_ia_prefix_addr; 203 } __attribute__ ((__packed__)); 204 205 struct dhcp6_auth { 206 u_int16_t dh6opt_auth_type; 207 u_int16_t dh6opt_auth_len; 208 u_int8_t dh6opt_auth_proto; 209 u_int8_t dh6opt_auth_alg; 210 u_int8_t dh6opt_auth_rdm; 211 u_int8_t dh6opt_auth_rdinfo[8]; 212 /* authentication information follows */ 213 } __attribute__ ((__packed__)); 214 215 static const char * 216 dhcp6opt_name(int type) 217 { 218 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ 219 220 if (type > 65535) 221 return "INVALID option"; 222 223 switch(type) { 224 case DH6OPT_CLIENTID: 225 return "client ID"; 226 case DH6OPT_SERVERID: 227 return "server ID"; 228 case DH6OPT_IA_NA: 229 return "IA_NA"; 230 case DH6OPT_IA_TA: 231 return "IA_TA"; 232 case DH6OPT_IA_ADDR: 233 return "IA_ADDR"; 234 case DH6OPT_ORO: 235 return "option request"; 236 case DH6OPT_PREFERENCE: 237 return "preference"; 238 case DH6OPT_ELAPSED_TIME: 239 return "elapsed time"; 240 case DH6OPT_RELAY_MSG: 241 return "relay message"; 242 case DH6OPT_AUTH: 243 return "authentication"; 244 case DH6OPT_UNICAST: 245 return "server unicast"; 246 case DH6OPT_STATUS_CODE: 247 return "status code"; 248 case DH6OPT_RAPID_COMMIT: 249 return "rapid commit"; 250 case DH6OPT_USER_CLASS: 251 return "user class"; 252 case DH6OPT_VENDOR_CLASS: 253 return "vendor class"; 254 case DH6OPT_VENDOR_OPTS: 255 return "vendor-specific info"; 256 case DH6OPT_INTERFACE_ID: 257 return "interface ID"; 258 case DH6OPT_RECONF_MSG: 259 return "reconfigure message"; 260 case DH6OPT_RECONF_ACCEPT: 261 return "reconfigure accept"; 262 case DH6OPT_SIP_SERVER_D: 263 return "SIP servers domain"; 264 case DH6OPT_SIP_SERVER_A: 265 return "SIP servers address"; 266 case DH6OPT_DNS: 267 return "DNS"; 268 case DH6OPT_DNSNAME: 269 return "DNS name"; 270 case DH6OPT_IA_PD: 271 return "IA_PD"; 272 case DH6OPT_IA_PD_PREFIX: 273 return "IA_PD prefix"; 274 case DH6OPT_NTP_SERVERS: 275 return "NTP Server"; 276 case DH6OPT_LIFETIME: 277 return "lifetime"; 278 case DH6OPT_NIS_SERVERS: 279 return "NIS server"; 280 case DH6OPT_NISP_SERVERS: 281 return "NIS+ server"; 282 case DH6OPT_NIS_NAME: 283 return "NIS domain name"; 284 case DH6OPT_NISP_NAME: 285 return "NIS+ domain name"; 286 case DH6OPT_BCMCS_SERVER_D: 287 return "BCMCS domain name"; 288 case DH6OPT_BCMCS_SERVER_A: 289 return "BCMCS server"; 290 case DH6OPT_GEOCONF_CIVIC: 291 return "Geoconf Civic"; 292 case DH6OPT_REMOTE_ID: 293 return "Remote ID"; 294 case DH6OPT_SUBSCRIBER_ID: 295 return "Subscriber ID"; 296 case DH6OPT_CLIENT_FQDN: 297 return "Client FQDN"; 298 case DH6OPT_PANA_AGENT: 299 return "PANA agent"; 300 case DH6OPT_NEW_POSIX_TIMEZONE: 301 return "POSIX timezone"; 302 case DH6OPT_NEW_TZDB_TIMEZONE: 303 return "POSIX tz database"; 304 case DH6OPT_ERO: 305 return "Echo request option"; 306 case DH6OPT_LQ_QUERY: 307 return "Lease query"; 308 case DH6OPT_CLIENT_DATA: 309 return "LQ client data"; 310 case DH6OPT_CLT_TIME: 311 return "Clt time"; 312 case DH6OPT_LQ_RELAY_DATA: 313 return "LQ relay data"; 314 case DH6OPT_LQ_CLIENT_LINK: 315 return "LQ client link"; 316 default: 317 snprintf(genstr, sizeof(genstr), "opt_%d", type); 318 return(genstr); 319 } 320 } 321 322 static const char * 323 dhcp6stcode(int code) 324 { 325 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ 326 327 if (code > 255) 328 return "INVALID code"; 329 330 switch(code) { 331 case DH6OPT_STCODE_SUCCESS: 332 return "success"; 333 case DH6OPT_STCODE_UNSPECFAIL: 334 return "unspec failure"; 335 case DH6OPT_STCODE_NOADDRAVAIL: 336 return "no addresses"; 337 case DH6OPT_STCODE_NOBINDING: 338 return "no binding"; 339 case DH6OPT_STCODE_NOTONLINK: 340 return "not on-link"; 341 case DH6OPT_STCODE_USEMULTICAST: 342 return "use multicast"; 343 case DH6OPT_STCODE_NOPREFIXAVAIL: 344 return "no prefixes"; 345 case DH6OPT_STCODE_UNKNOWNQUERYTYPE: 346 return "unknown query type"; 347 case DH6OPT_STCODE_MALFORMEDQUERY: 348 return "malformed query"; 349 case DH6OPT_STCODE_NOTCONFIGURED: 350 return "not configured"; 351 case DH6OPT_STCODE_NOTALLOWED: 352 return "not allowed"; 353 default: 354 snprintf(genstr, sizeof(genstr), "code%d", code); 355 return(genstr); 356 } 357 } 358 359 static void 360 dhcp6opt_print(const u_char *cp, const u_char *ep) 361 { 362 struct dhcp6opt *dh6o; 363 u_char *tp; 364 size_t i; 365 u_int16_t opttype; 366 size_t optlen; 367 u_int16_t val16; 368 u_int32_t val32; 369 struct dhcp6_ia ia; 370 struct dhcp6_ia_prefix ia_prefix; 371 struct dhcp6_ia_addr ia_addr; 372 struct dhcp6_auth authopt; 373 u_int authinfolen, authrealmlen; 374 375 if (cp == ep) 376 return; 377 while (cp < ep) { 378 if (ep < cp + sizeof(*dh6o)) 379 goto trunc; 380 dh6o = (struct dhcp6opt *)cp; 381 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); 382 if (ep < cp + sizeof(*dh6o) + optlen) 383 goto trunc; 384 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); 385 printf(" (%s", dhcp6opt_name(opttype)); 386 switch (opttype) { 387 case DH6OPT_CLIENTID: 388 case DH6OPT_SERVERID: 389 if (optlen < 2) { 390 /*(*/ 391 printf(" ?)"); 392 break; 393 } 394 tp = (u_char *)(dh6o + 1); 395 switch (EXTRACT_16BITS(tp)) { 396 case 1: 397 if (optlen >= 2 + 6) { 398 printf(" hwaddr/time type %u time %u ", 399 EXTRACT_16BITS(&tp[2]), 400 EXTRACT_32BITS(&tp[4])); 401 for (i = 8; i < optlen; i++) 402 printf("%02x", tp[i]); 403 /*(*/ 404 printf(")"); 405 } else { 406 /*(*/ 407 printf(" ?)"); 408 } 409 break; 410 case 2: 411 if (optlen >= 2 + 8) { 412 printf(" vid "); 413 for (i = 2; i < 2 + 8; i++) 414 printf("%02x", tp[i]); 415 /*(*/ 416 printf(")"); 417 } else { 418 /*(*/ 419 printf(" ?)"); 420 } 421 break; 422 case 3: 423 if (optlen >= 2 + 2) { 424 printf(" hwaddr type %u ", 425 EXTRACT_16BITS(&tp[2])); 426 for (i = 4; i < optlen; i++) 427 printf("%02x", tp[i]); 428 /*(*/ 429 printf(")"); 430 } else { 431 /*(*/ 432 printf(" ?)"); 433 } 434 break; 435 default: 436 printf(" type %d)", EXTRACT_16BITS(tp)); 437 break; 438 } 439 break; 440 case DH6OPT_IA_ADDR: 441 if (optlen < sizeof(ia_addr) - 4) { 442 printf(" ?)"); 443 break; 444 } 445 memcpy(&ia_addr, (u_char *)dh6o, sizeof(ia_addr)); 446 printf(" %s", 447 ip6addr_string(&ia_addr.dh6opt_ia_addr_addr)); 448 ia_addr.dh6opt_ia_addr_pltime = 449 ntohl(ia_addr.dh6opt_ia_addr_pltime); 450 ia_addr.dh6opt_ia_addr_vltime = 451 ntohl(ia_addr.dh6opt_ia_addr_vltime); 452 printf(" pltime:%lu vltime:%lu", 453 (unsigned long)ia_addr.dh6opt_ia_addr_pltime, 454 (unsigned long)ia_addr.dh6opt_ia_addr_vltime); 455 if (optlen > sizeof(ia_addr) - 4) { 456 /* there are sub-options */ 457 dhcp6opt_print((u_char *)dh6o + 458 sizeof(ia_addr), 459 (u_char *)(dh6o + 1) + optlen); 460 } 461 printf(")"); 462 break; 463 case DH6OPT_ORO: 464 case DH6OPT_ERO: 465 if (optlen % 2) { 466 printf(" ?)"); 467 break; 468 } 469 tp = (u_char *)(dh6o + 1); 470 for (i = 0; i < optlen; i += 2) { 471 u_int16_t opt; 472 473 memcpy(&opt, &tp[i], sizeof(opt)); 474 printf(" %s", dhcp6opt_name(ntohs(opt))); 475 } 476 printf(")"); 477 break; 478 case DH6OPT_PREFERENCE: 479 if (optlen != 1) { 480 printf(" ?)"); 481 break; 482 } 483 printf(" %d)", *((u_char *)(dh6o + 1) + 1)); 484 break; 485 case DH6OPT_ELAPSED_TIME: 486 if (optlen != 2) { 487 printf(" ?)"); 488 break; 489 } 490 memcpy(&val16, dh6o + 1, sizeof(val16)); 491 val16 = ntohs(val16); 492 printf(" %d)", (int)val16); 493 break; 494 case DH6OPT_RELAY_MSG: 495 printf(" ("); 496 dhcp6_print((const u_char *)(dh6o + 1), optlen); 497 printf(")"); 498 break; 499 case DH6OPT_AUTH: 500 if (optlen < sizeof(authopt) - sizeof(*dh6o)) { 501 printf(" ?)"); 502 break; 503 } 504 memcpy(&authopt, dh6o, sizeof(authopt)); 505 switch (authopt.dh6opt_auth_proto) { 506 case DH6OPT_AUTHPROTO_DELAYED: 507 printf(" proto: delayed"); 508 break; 509 case DH6OPT_AUTHPROTO_RECONFIG: 510 printf(" proto: reconfigure"); 511 break; 512 default: 513 printf(" proto: %d", 514 authopt.dh6opt_auth_proto); 515 break; 516 } 517 switch (authopt.dh6opt_auth_alg) { 518 case DH6OPT_AUTHALG_HMACMD5: 519 /* XXX: may depend on the protocol */ 520 printf(", alg: HMAC-MD5"); 521 break; 522 default: 523 printf(", alg: %d", authopt.dh6opt_auth_alg); 524 break; 525 } 526 switch (authopt.dh6opt_auth_rdm) { 527 case DH6OPT_AUTHRDM_MONOCOUNTER: 528 printf(", RDM: mono"); 529 break; 530 default: 531 printf(", RDM: %d", authopt.dh6opt_auth_rdm); 532 break; 533 } 534 tp = (u_char *)&authopt.dh6opt_auth_rdinfo; 535 printf(", RD:"); 536 for (i = 0; i < 4; i++, tp += sizeof(val16)) 537 printf(" %04x", EXTRACT_16BITS(tp)); 538 539 /* protocol dependent part */ 540 tp = (u_char *)dh6o + sizeof(authopt); 541 authinfolen = 542 optlen + sizeof(*dh6o) - sizeof(authopt); 543 switch (authopt.dh6opt_auth_proto) { 544 case DH6OPT_AUTHPROTO_DELAYED: 545 if (authinfolen == 0) 546 break; 547 if (authinfolen < 20) { 548 printf(" ??"); 549 break; 550 } 551 authrealmlen = authinfolen - 20; 552 if (authrealmlen > 0) { 553 printf(", realm: "); 554 } 555 for (i = 0; i < authrealmlen; i++, tp++) 556 printf("%02x", *tp); 557 printf(", key ID: %08x", EXTRACT_32BITS(tp)); 558 tp += 4; 559 printf(", HMAC-MD5:"); 560 for (i = 0; i < 4; i++, tp+= 4) 561 printf(" %08x", EXTRACT_32BITS(tp)); 562 break; 563 case DH6OPT_AUTHPROTO_RECONFIG: 564 if (authinfolen != 17) { 565 printf(" ??"); 566 break; 567 } 568 switch (*tp++) { 569 case DH6OPT_AUTHRECONFIG_KEY: 570 printf(" reconfig-key"); 571 break; 572 case DH6OPT_AUTHRECONFIG_HMACMD5: 573 printf(" type: HMAC-MD5"); 574 break; 575 default: 576 printf(" type: ??"); 577 break; 578 } 579 printf(" value:"); 580 for (i = 0; i < 4; i++, tp+= 4) 581 printf(" %08x", EXTRACT_32BITS(tp)); 582 break; 583 default: 584 printf(" ??"); 585 break; 586 } 587 588 printf(")"); 589 break; 590 case DH6OPT_RAPID_COMMIT: /* nothing todo */ 591 printf(")"); 592 break; 593 case DH6OPT_INTERFACE_ID: 594 case DH6OPT_SUBSCRIBER_ID: 595 /* 596 * Since we cannot predict the encoding, print hex dump 597 * at most 10 characters. 598 */ 599 printf(" "); 600 for (i = 0; i < optlen && i < 10; i++) 601 printf("%02x", ((u_char *)(dh6o + 1))[i]); 602 printf("...)"); 603 break; 604 case DH6OPT_RECONF_MSG: 605 tp = (u_char *)(dh6o + 1); 606 switch (*tp) { 607 case DH6_RENEW: 608 printf(" for renew)"); 609 break; 610 case DH6_INFORM_REQ: 611 printf(" for inf-req)"); 612 break; 613 default: 614 printf(" for ?\?\?(%02x))", *tp); 615 break; 616 } 617 break; 618 case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 619 printf(")"); 620 break; 621 case DH6OPT_SIP_SERVER_A: 622 case DH6OPT_DNS: 623 case DH6OPT_NTP_SERVERS: 624 case DH6OPT_NIS_SERVERS: 625 case DH6OPT_NISP_SERVERS: 626 case DH6OPT_BCMCS_SERVER_A: 627 case DH6OPT_PANA_AGENT: 628 case DH6OPT_LQ_CLIENT_LINK: 629 if (optlen % 16) { 630 printf(" ?)"); 631 break; 632 } 633 tp = (u_char *)(dh6o + 1); 634 for (i = 0; i < optlen; i += 16) 635 printf(" %s", ip6addr_string(&tp[i])); 636 printf(")"); 637 break; 638 case DH6OPT_STATUS_CODE: 639 if (optlen < 2) { 640 printf(" ?)"); 641 break; 642 } 643 memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16)); 644 val16 = ntohs(val16); 645 printf(" %s)", dhcp6stcode(val16)); 646 break; 647 case DH6OPT_IA_NA: 648 case DH6OPT_IA_PD: 649 if (optlen < sizeof(ia) - 4) { 650 printf(" ?)"); 651 break; 652 } 653 memcpy(&ia, (u_char *)dh6o, sizeof(ia)); 654 ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid); 655 ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1); 656 ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2); 657 printf(" IAID:%lu T1:%lu T2:%lu", 658 (unsigned long)ia.dh6opt_ia_iaid, 659 (unsigned long)ia.dh6opt_ia_t1, 660 (unsigned long)ia.dh6opt_ia_t2); 661 if (optlen > sizeof(ia) - 4) { 662 /* there are sub-options */ 663 dhcp6opt_print((u_char *)dh6o + sizeof(ia), 664 (u_char *)(dh6o + 1) + optlen); 665 } 666 printf(")"); 667 break; 668 case DH6OPT_IA_TA: 669 if (optlen < 4) { 670 printf(" ?)"); 671 break; 672 } 673 memcpy(&val32, dh6o + 1, sizeof(val32)); 674 val32 = ntohl(val32); 675 printf(" IAID:%lu", (unsigned long)val32); 676 if (optlen > 4) { 677 /* there are sub-options */ 678 dhcp6opt_print((u_char *)(dh6o + 1) + 4, 679 (u_char *)(dh6o + 1) + optlen); 680 } 681 printf(")"); 682 break; 683 case DH6OPT_IA_PD_PREFIX: 684 if (optlen < sizeof(ia_prefix) - 4) { 685 printf(" ?)"); 686 break; 687 } 688 memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix)); 689 printf(" %s/%d", 690 ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr), 691 ia_prefix.dh6opt_ia_prefix_plen); 692 ia_prefix.dh6opt_ia_prefix_pltime = 693 ntohl(ia_prefix.dh6opt_ia_prefix_pltime); 694 ia_prefix.dh6opt_ia_prefix_vltime = 695 ntohl(ia_prefix.dh6opt_ia_prefix_vltime); 696 printf(" pltime:%lu vltime:%lu", 697 (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime, 698 (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime); 699 if (optlen > sizeof(ia_prefix) - 4) { 700 /* there are sub-options */ 701 dhcp6opt_print((u_char *)dh6o + 702 sizeof(ia_prefix), 703 (u_char *)(dh6o + 1) + optlen); 704 } 705 printf(")"); 706 break; 707 case DH6OPT_LIFETIME: 708 case DH6OPT_CLT_TIME: 709 if (optlen != 4) { 710 printf(" ?)"); 711 break; 712 } 713 memcpy(&val32, dh6o + 1, sizeof(val32)); 714 val32 = ntohl(val32); 715 printf(" %d)", (int)val32); 716 break; 717 case DH6OPT_REMOTE_ID: 718 if (optlen < 4) { 719 printf(" ?)"); 720 break; 721 } 722 tp = (u_char *)(dh6o + 1); 723 memcpy(&val32, &tp[0], sizeof(val32)); 724 val32 = ntohl(val32); 725 printf(" %d ", (int)val32); 726 /* 727 * Print hex dump first 10 characters. 728 */ 729 for (i = 4; i < optlen && i < 14; i++) 730 printf("%02x", tp[i]); 731 printf("...)"); 732 break; 733 case DH6OPT_LQ_QUERY: 734 if (optlen < 17) { 735 printf(" ?)"); 736 break; 737 } 738 tp = (u_char *)(dh6o + 1); 739 switch (*tp) { 740 case 1: 741 printf(" by-address"); 742 break; 743 case 2: 744 printf(" by-clientID"); 745 break; 746 default: 747 printf(" type_%d", (int)*tp); 748 break; 749 } 750 printf(" %s", ip6addr_string(&tp[1])); 751 if (optlen > 17) { 752 /* there are query-options */ 753 dhcp6opt_print(tp + 17, tp + optlen); 754 } 755 printf(")"); 756 break; 757 case DH6OPT_CLIENT_DATA: 758 if (optlen > 0) { 759 /* there are encapsulated options */ 760 dhcp6opt_print((u_char *)(dh6o + 1), 761 (u_char *)(dh6o + 1) + optlen); 762 } 763 printf(")"); 764 break; 765 case DH6OPT_LQ_RELAY_DATA: 766 if (optlen < 16) { 767 printf(" ?)"); 768 break; 769 } 770 tp = (u_char *)(dh6o + 1); 771 printf(" %s ", ip6addr_string(&tp[0])); 772 /* 773 * Print hex dump first 10 characters. 774 */ 775 for (i = 16; i < optlen && i < 26; i++) 776 printf("%02x", tp[i]); 777 printf("...)"); 778 break; 779 default: 780 printf(")"); 781 break; 782 } 783 784 cp += sizeof(*dh6o) + optlen; 785 } 786 return; 787 788 trunc: 789 printf("[|dhcp6ext]"); 790 } 791 792 /* 793 * Print dhcp6 packets 794 */ 795 void 796 dhcp6_print(const u_char *cp, u_int length) 797 { 798 struct dhcp6 *dh6; 799 struct dhcp6_relay *dh6relay; 800 const u_char *ep; 801 u_char *extp; 802 const char *name; 803 804 printf("dhcp6"); 805 806 ep = (u_char *)snapend; 807 if (cp + length < ep) 808 ep = cp + length; 809 810 dh6 = (struct dhcp6 *)cp; 811 dh6relay = (struct dhcp6_relay *)cp; 812 TCHECK(dh6->dh6_xid); 813 switch (dh6->dh6_msgtype) { 814 case DH6_SOLICIT: 815 name = "solicit"; 816 break; 817 case DH6_ADVERTISE: 818 name = "advertise"; 819 break; 820 case DH6_REQUEST: 821 name = "request"; 822 break; 823 case DH6_CONFIRM: 824 name = "confirm"; 825 break; 826 case DH6_RENEW: 827 name = "renew"; 828 break; 829 case DH6_REBIND: 830 name = "rebind"; 831 break; 832 case DH6_REPLY: 833 name = "reply"; 834 break; 835 case DH6_RELEASE: 836 name = "release"; 837 break; 838 case DH6_DECLINE: 839 name = "decline"; 840 break; 841 case DH6_RECONFIGURE: 842 name = "reconfigure"; 843 break; 844 case DH6_INFORM_REQ: 845 name= "inf-req"; 846 break; 847 case DH6_RELAY_FORW: 848 name= "relay-fwd"; 849 break; 850 case DH6_RELAY_REPLY: 851 name= "relay-reply"; 852 break; 853 case DH6_LEASEQUERY: 854 name= "leasequery"; 855 break; 856 case DH6_LQ_REPLY: 857 name= "leasequery-reply"; 858 break; 859 default: 860 name = NULL; 861 break; 862 } 863 864 if (!vflag) { 865 if (name) 866 printf(" %s", name); 867 else if (dh6->dh6_msgtype != DH6_RELAY_FORW && 868 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 869 printf(" msgtype-%u", dh6->dh6_msgtype); 870 } 871 return; 872 } 873 874 /* XXX relay agent messages have to be handled differently */ 875 876 if (name) 877 printf(" %s (", name); /*)*/ 878 else 879 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ 880 if (dh6->dh6_msgtype != DH6_RELAY_FORW && 881 dh6->dh6_msgtype != DH6_RELAY_REPLY) { 882 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); 883 extp = (u_char *)(dh6 + 1); 884 dhcp6opt_print(extp, ep); 885 } else { /* relay messages */ 886 struct in6_addr addr6; 887 888 TCHECK(dh6relay->dh6relay_peeraddr); 889 890 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 891 printf("linkaddr=%s", ip6addr_string(&addr6)); 892 893 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 894 printf(" peeraddr=%s", ip6addr_string(&addr6)); 895 896 dhcp6opt_print((u_char *)(dh6relay + 1), ep); 897 } 898 /*(*/ 899 printf(")"); 900 return; 901 902 trunc: 903 printf("[|dhcp6]"); 904 } 905