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