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