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