1 3431 carlsonj /* 2 3431 carlsonj * CDDL HEADER START 3 3431 carlsonj * 4 3431 carlsonj * The contents of this file are subject to the terms of the 5 3431 carlsonj * Common Development and Distribution License (the "License"). 6 3431 carlsonj * You may not use this file except in compliance with the License. 7 3431 carlsonj * 8 3431 carlsonj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 3431 carlsonj * or http://www.opensolaris.org/os/licensing. 10 3431 carlsonj * See the License for the specific language governing permissions 11 3431 carlsonj * and limitations under the License. 12 3431 carlsonj * 13 3431 carlsonj * When distributing Covered Code, include this CDDL HEADER in each 14 3431 carlsonj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 3431 carlsonj * If applicable, add the following below this CDDL HEADER, with the 16 3431 carlsonj * fields enclosed by brackets "[]" replaced with your own identifying 17 3431 carlsonj * information: Portions Copyright [yyyy] [name of copyright owner] 18 3431 carlsonj * 19 3431 carlsonj * CDDL HEADER END 20 3431 carlsonj */ 21 3431 carlsonj 22 3431 carlsonj /* 23 3431 carlsonj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 3431 carlsonj * Use is subject to license terms. 25 3431 carlsonj */ 26 3431 carlsonj 27 3431 carlsonj #pragma ident "%Z%%M% %I% %E% SMI" 28 3431 carlsonj 29 3431 carlsonj /* 30 3431 carlsonj * Dynamic Host Configuration Protocol version 6, for IPv6. Supports 31 3431 carlsonj * RFCs 3315, 3319, 3646, 3898, 4075, 4242, 4280, 4580, 4649, and 4704. 32 3431 carlsonj */ 33 3431 carlsonj 34 3431 carlsonj #include <stdio.h> 35 3431 carlsonj #include <stdlib.h> 36 3431 carlsonj #include <string.h> 37 3431 carlsonj #include <time.h> 38 3431 carlsonj #include <sys/types.h> 39 3431 carlsonj #include <sys/socket.h> 40 3431 carlsonj #include <netinet/in.h> 41 3431 carlsonj #include <netinet/dhcp6.h> 42 3431 carlsonj #include <arpa/inet.h> 43 3431 carlsonj #include <dhcp_impl.h> 44 3431 carlsonj #include <dhcp_inittab.h> 45 3431 carlsonj 46 3431 carlsonj #include "snoop.h" 47 3431 carlsonj 48 3431 carlsonj static const char *mtype_to_str(uint8_t); 49 3431 carlsonj static const char *option_to_str(uint8_t); 50 3431 carlsonj static const char *duidtype_to_str(uint16_t); 51 3431 carlsonj static const char *status_to_str(uint16_t); 52 3431 carlsonj static const char *entr_to_str(uint32_t); 53 3431 carlsonj static const char *reconf_to_str(uint8_t); 54 3431 carlsonj static const char *authproto_to_str(uint8_t); 55 3431 carlsonj static const char *authalg_to_str(uint8_t, uint8_t); 56 3431 carlsonj static const char *authrdm_to_str(uint8_t); 57 3431 carlsonj static const char *cwhat_to_str(uint8_t); 58 3431 carlsonj static const char *catype_to_str(uint8_t); 59 3431 carlsonj static void show_hex(const uint8_t *, int, const char *); 60 3431 carlsonj static void show_ascii(const uint8_t *, int, const char *); 61 3431 carlsonj static void show_address(const char *, const void *); 62 3431 carlsonj static void show_options(const uint8_t *, int); 63 3431 carlsonj 64 3431 carlsonj int 65 3431 carlsonj interpret_dhcpv6(int flags, const uint8_t *data, int len) 66 3431 carlsonj { 67 3431 carlsonj int olen = len; 68 3431 carlsonj char *line, *lstart; 69 3431 carlsonj dhcpv6_relay_t d6r; 70 3431 carlsonj dhcpv6_message_t d6m; 71 3431 carlsonj uint_t optlen; 72 3431 carlsonj uint16_t statuscode; 73 3431 carlsonj 74 3431 carlsonj if (len <= 0) { 75 3431 carlsonj (void) strlcpy(get_sum_line(), "DHCPv6?", MAXLINE); 76 3431 carlsonj return (0); 77 3431 carlsonj } 78 3431 carlsonj if (flags & F_SUM) { 79 3431 carlsonj uint_t ias; 80 3431 carlsonj dhcpv6_option_t *d6o; 81 3431 carlsonj in6_addr_t link, peer; 82 3431 carlsonj char linkstr[INET6_ADDRSTRLEN]; 83 3431 carlsonj char peerstr[INET6_ADDRSTRLEN]; 84 3431 carlsonj 85 3431 carlsonj line = lstart = get_sum_line(); 86 3431 carlsonj line += snprintf(line, MAXLINE, "DHCPv6 %s", 87 3431 carlsonj mtype_to_str(data[0])); 88 3431 carlsonj if (data[0] == DHCPV6_MSG_RELAY_FORW || 89 3431 carlsonj data[0] == DHCPV6_MSG_RELAY_REPL) { 90 3431 carlsonj if (len < sizeof (d6r)) { 91 3431 carlsonj (void) strlcpy(line, "?", 92 3431 carlsonj MAXLINE - (line - lstart)); 93 3431 carlsonj return (olen); 94 3431 carlsonj } 95 3431 carlsonj /* Not much in DHCPv6 is aligned. */ 96 3431 carlsonj (void) memcpy(&d6r, data, sizeof (d6r)); 97 3431 carlsonj (void) memcpy(&link, d6r.d6r_linkaddr, sizeof (link)); 98 3431 carlsonj (void) memcpy(&peer, d6r.d6r_peeraddr, sizeof (peer)); 99 3431 carlsonj line += snprintf(line, MAXLINE - (line - lstart), 100 3431 carlsonj " HC=%d link=%s peer=%s", d6r.d6r_hop_count, 101 3431 carlsonj inet_ntop(AF_INET6, &link, linkstr, 102 3431 carlsonj sizeof (linkstr)), 103 3431 carlsonj inet_ntop(AF_INET6, &peer, peerstr, 104 3431 carlsonj sizeof (peerstr))); 105 3431 carlsonj data += sizeof (d6r); 106 3431 carlsonj len -= sizeof (d6r); 107 3431 carlsonj } else { 108 3431 carlsonj if (len < sizeof (d6m)) { 109 3431 carlsonj (void) strlcpy(line, "?", 110 3431 carlsonj MAXLINE - (line - lstart)); 111 3431 carlsonj return (olen); 112 3431 carlsonj } 113 3431 carlsonj (void) memcpy(&d6m, data, sizeof (d6m)); 114 3431 carlsonj line += snprintf(line, MAXLINE - (line - lstart), 115 3431 carlsonj " xid=%x", DHCPV6_GET_TRANSID(&d6m)); 116 3431 carlsonj data += sizeof (d6m); 117 3431 carlsonj len -= sizeof (d6m); 118 3431 carlsonj } 119 3431 carlsonj ias = 0; 120 3431 carlsonj d6o = NULL; 121 3431 carlsonj while ((d6o = dhcpv6_find_option(data, len, d6o, 122 3431 carlsonj DHCPV6_OPT_IA_NA, NULL)) != NULL) 123 3431 carlsonj ias++; 124 3431 carlsonj if (ias > 0) 125 3431 carlsonj line += snprintf(line, MAXLINE - (line - lstart), 126 3431 carlsonj " IAs=%u", ias); 127 3431 carlsonj d6o = dhcpv6_find_option(data, len, NULL, 128 3431 carlsonj DHCPV6_OPT_STATUS_CODE, &optlen); 129 3431 carlsonj optlen -= sizeof (*d6o); 130 3431 carlsonj if (d6o != NULL && optlen >= sizeof (statuscode)) { 131 3431 carlsonj (void) memcpy(&statuscode, d6o + 1, 132 3431 carlsonj sizeof (statuscode)); 133 3431 carlsonj line += snprintf(line, MAXLINE - (line - lstart), 134 3431 carlsonj " status=%u", ntohs(statuscode)); 135 3431 carlsonj optlen -= sizeof (statuscode); 136 3431 carlsonj if (optlen > 0) { 137 3431 carlsonj line += snprintf(line, 138 3431 carlsonj MAXLINE - (line - lstart), " \"%.*s\"", 139 3431 carlsonj optlen, (char *)(d6o + 1) + 2); 140 3431 carlsonj } 141 3431 carlsonj } 142 3431 carlsonj d6o = dhcpv6_find_option(data, len, NULL, 143 3431 carlsonj DHCPV6_OPT_RELAY_MSG, &optlen); 144 3431 carlsonj optlen -= sizeof (*d6o); 145 3431 carlsonj if (d6o != NULL && optlen >= 1) { 146 3431 carlsonj line += snprintf(line, MAXLINE - (line - lstart), 147 3431 carlsonj " relay=%s", mtype_to_str(*(uint8_t *)(d6o + 1))); 148 3431 carlsonj } 149 3431 carlsonj } else if (flags & F_DTAIL) { 150 3431 carlsonj show_header("DHCPv6: ", 151 3431 carlsonj "Dynamic Host Configuration Protocol Version 6", len); 152 3431 carlsonj show_space(); 153 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 154 3431 carlsonj "Message type (msg-type) = %u (%s)", data[0], 155 3431 carlsonj mtype_to_str(data[0])); 156 3431 carlsonj if (data[0] == DHCPV6_MSG_RELAY_FORW || 157 3431 carlsonj data[0] == DHCPV6_MSG_RELAY_REPL) { 158 3431 carlsonj if (len < sizeof (d6r)) { 159 3431 carlsonj (void) strlcpy(get_line(0, 0), "Truncated", 160 3431 carlsonj get_line_remain()); 161 3431 carlsonj return (olen); 162 3431 carlsonj } 163 3431 carlsonj (void) memcpy(&d6r, data, sizeof (d6r)); 164 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 165 3431 carlsonj "Hop count = %u", d6r.d6r_hop_count); 166 3431 carlsonj show_address("Link address", d6r.d6r_linkaddr); 167 3431 carlsonj show_address("Peer address", d6r.d6r_peeraddr); 168 3431 carlsonj data += sizeof (d6r); 169 3431 carlsonj len -= sizeof (d6r); 170 3431 carlsonj } else { 171 3431 carlsonj if (len < sizeof (d6m)) { 172 3431 carlsonj (void) strlcpy(get_line(0, 0), "Truncated", 173 3431 carlsonj get_line_remain()); 174 3431 carlsonj return (olen); 175 3431 carlsonj } 176 3431 carlsonj (void) memcpy(&d6m, data, sizeof (d6m)); 177 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 178 3431 carlsonj "Transaction ID = %x", DHCPV6_GET_TRANSID(&d6m)); 179 3431 carlsonj data += sizeof (d6m); 180 3431 carlsonj len -= sizeof (d6m); 181 3431 carlsonj } 182 3431 carlsonj show_space(); 183 3431 carlsonj show_options(data, len); 184 3431 carlsonj show_space(); 185 3431 carlsonj } 186 3431 carlsonj return (olen); 187 3431 carlsonj } 188 3431 carlsonj 189 3431 carlsonj static const char * 190 3431 carlsonj mtype_to_str(uint8_t mtype) 191 3431 carlsonj { 192 3431 carlsonj switch (mtype) { 193 3431 carlsonj case DHCPV6_MSG_SOLICIT: 194 3431 carlsonj return ("Solicit"); 195 3431 carlsonj case DHCPV6_MSG_ADVERTISE: 196 3431 carlsonj return ("Advertise"); 197 3431 carlsonj case DHCPV6_MSG_REQUEST: 198 3431 carlsonj return ("Request"); 199 3431 carlsonj case DHCPV6_MSG_CONFIRM: 200 3431 carlsonj return ("Confirm"); 201 3431 carlsonj case DHCPV6_MSG_RENEW: 202 3431 carlsonj return ("Renew"); 203 3431 carlsonj case DHCPV6_MSG_REBIND: 204 3431 carlsonj return ("Rebind"); 205 3431 carlsonj case DHCPV6_MSG_REPLY: 206 3431 carlsonj return ("Reply"); 207 3431 carlsonj case DHCPV6_MSG_RELEASE: 208 3431 carlsonj return ("Release"); 209 3431 carlsonj case DHCPV6_MSG_DECLINE: 210 3431 carlsonj return ("Decline"); 211 3431 carlsonj case DHCPV6_MSG_RECONFIGURE: 212 3431 carlsonj return ("Reconfigure"); 213 3431 carlsonj case DHCPV6_MSG_INFO_REQ: 214 3431 carlsonj return ("Information-Request"); 215 3431 carlsonj case DHCPV6_MSG_RELAY_FORW: 216 3431 carlsonj return ("Relay-Forward"); 217 3431 carlsonj case DHCPV6_MSG_RELAY_REPL: 218 3431 carlsonj return ("Relay-Reply"); 219 3431 carlsonj default: 220 3431 carlsonj return ("Unknown"); 221 3431 carlsonj } 222 3431 carlsonj } 223 3431 carlsonj 224 3431 carlsonj static const char * 225 3431 carlsonj option_to_str(uint8_t mtype) 226 3431 carlsonj { 227 3431 carlsonj switch (mtype) { 228 3431 carlsonj case DHCPV6_OPT_CLIENTID: 229 3431 carlsonj return ("Client Identifier"); 230 3431 carlsonj case DHCPV6_OPT_SERVERID: 231 3431 carlsonj return ("Server Identifier"); 232 3431 carlsonj case DHCPV6_OPT_IA_NA: 233 3431 carlsonj return ("Identity Association for Non-temporary Addresses"); 234 3431 carlsonj case DHCPV6_OPT_IA_TA: 235 3431 carlsonj return ("Identity Association for Temporary Addresses"); 236 3431 carlsonj case DHCPV6_OPT_IAADDR: 237 3431 carlsonj return ("IA Address"); 238 3431 carlsonj case DHCPV6_OPT_ORO: 239 3431 carlsonj return ("Option Request"); 240 3431 carlsonj case DHCPV6_OPT_PREFERENCE: 241 3431 carlsonj return ("Preference"); 242 3431 carlsonj case DHCPV6_OPT_ELAPSED_TIME: 243 3431 carlsonj return ("Elapsed Time"); 244 3431 carlsonj case DHCPV6_OPT_RELAY_MSG: 245 3431 carlsonj return ("Relay Message"); 246 3431 carlsonj case DHCPV6_OPT_AUTH: 247 3431 carlsonj return ("Authentication"); 248 3431 carlsonj case DHCPV6_OPT_UNICAST: 249 3431 carlsonj return ("Server Unicast"); 250 3431 carlsonj case DHCPV6_OPT_STATUS_CODE: 251 3431 carlsonj return ("Status Code"); 252 3431 carlsonj case DHCPV6_OPT_RAPID_COMMIT: 253 3431 carlsonj return ("Rapid Commit"); 254 3431 carlsonj case DHCPV6_OPT_USER_CLASS: 255 3431 carlsonj return ("User Class"); 256 3431 carlsonj case DHCPV6_OPT_VENDOR_CLASS: 257 3431 carlsonj return ("Vendor Class"); 258 3431 carlsonj case DHCPV6_OPT_VENDOR_OPT: 259 3431 carlsonj return ("Vendor-specific Information"); 260 3431 carlsonj case DHCPV6_OPT_INTERFACE_ID: 261 3431 carlsonj return ("Interface-Id"); 262 3431 carlsonj case DHCPV6_OPT_RECONF_MSG: 263 3431 carlsonj return ("Reconfigure Message"); 264 3431 carlsonj case DHCPV6_OPT_RECONF_ACC: 265 3431 carlsonj return ("Reconfigure Accept"); 266 3431 carlsonj case DHCPV6_OPT_SIP_NAMES: 267 3431 carlsonj return ("SIP Servers Domain Name List"); 268 3431 carlsonj case DHCPV6_OPT_SIP_ADDR: 269 3431 carlsonj return ("SIP Servers IPv6 Address List"); 270 3431 carlsonj case DHCPV6_OPT_DNS_ADDR: 271 3431 carlsonj return ("DNS Recursive Name Server"); 272 3431 carlsonj case DHCPV6_OPT_DNS_SEARCH: 273 3431 carlsonj return ("Domain Search List"); 274 3431 carlsonj case DHCPV6_OPT_IA_PD: 275 3431 carlsonj return ("Identity Association for Prefix Delegation"); 276 3431 carlsonj case DHCPV6_OPT_IAPREFIX: 277 3431 carlsonj return ("IA_PD Prefix"); 278 3431 carlsonj case DHCPV6_OPT_NIS_SERVERS: 279 3431 carlsonj return ("Network Information Service Servers"); 280 3431 carlsonj case DHCPV6_OPT_NISP_SERVERS: 281 3431 carlsonj return ("Network Information Service V2 Servers"); 282 3431 carlsonj case DHCPV6_OPT_NIS_DOMAIN: 283 3431 carlsonj return ("Network Information Service Domain Name"); 284 3431 carlsonj case DHCPV6_OPT_NISP_DOMAIN: 285 3431 carlsonj return ("Network Information Service V2 Domain Name"); 286 3431 carlsonj case DHCPV6_OPT_SNTP_SERVERS: 287 3431 carlsonj return ("Simple Network Time Protocol Servers"); 288 3431 carlsonj case DHCPV6_OPT_INFO_REFTIME: 289 3431 carlsonj return ("Information Refresh Time"); 290 3431 carlsonj case DHCPV6_OPT_BCMCS_SRV_D: 291 3431 carlsonj return ("BCMCS Controller Domain Name List"); 292 3431 carlsonj case DHCPV6_OPT_BCMCS_SRV_A: 293 3431 carlsonj return ("BCMCS Controller IPv6 Address"); 294 3431 carlsonj case DHCPV6_OPT_GEOCONF_CVC: 295 3431 carlsonj return ("Civic Location"); 296 3431 carlsonj case DHCPV6_OPT_REMOTE_ID: 297 3431 carlsonj return ("Relay Agent Remote-ID"); 298 3431 carlsonj case DHCPV6_OPT_SUBSCRIBER: 299 3431 carlsonj return ("Relay Agent Subscriber-ID"); 300 3431 carlsonj case DHCPV6_OPT_CLIENT_FQDN: 301 3431 carlsonj return ("Client FQDN"); 302 3431 carlsonj default: 303 3431 carlsonj return ("Unknown"); 304 3431 carlsonj } 305 3431 carlsonj } 306 3431 carlsonj 307 3431 carlsonj static const char * 308 3431 carlsonj duidtype_to_str(uint16_t dtype) 309 3431 carlsonj { 310 3431 carlsonj switch (dtype) { 311 3431 carlsonj case DHCPV6_DUID_LLT: 312 3431 carlsonj return ("Link-layer Address Plus Time"); 313 3431 carlsonj case DHCPV6_DUID_EN: 314 3431 carlsonj return ("Enterprise Number"); 315 3431 carlsonj case DHCPV6_DUID_LL: 316 3431 carlsonj return ("Link-layer Address"); 317 3431 carlsonj default: 318 3431 carlsonj return ("Unknown"); 319 3431 carlsonj } 320 3431 carlsonj } 321 3431 carlsonj 322 3431 carlsonj static const char * 323 3431 carlsonj status_to_str(uint16_t status) 324 3431 carlsonj { 325 3431 carlsonj switch (status) { 326 3431 carlsonj case DHCPV6_STAT_SUCCESS: 327 3431 carlsonj return ("Success"); 328 3431 carlsonj case DHCPV6_STAT_UNSPECFAIL: 329 3431 carlsonj return ("Failure, reason unspecified"); 330 3431 carlsonj case DHCPV6_STAT_NOADDRS: 331 3431 carlsonj return ("No addresses for IAs"); 332 3431 carlsonj case DHCPV6_STAT_NOBINDING: 333 3431 carlsonj return ("Client binding unavailable"); 334 3431 carlsonj case DHCPV6_STAT_NOTONLINK: 335 3431 carlsonj return ("Prefix not on link"); 336 3431 carlsonj case DHCPV6_STAT_USEMCAST: 337 3431 carlsonj return ("Use multicast"); 338 3431 carlsonj case DHCPV6_STAT_NOPREFIX: 339 3431 carlsonj return ("No prefix available"); 340 3431 carlsonj default: 341 3431 carlsonj return ("Unknown"); 342 3431 carlsonj } 343 3431 carlsonj } 344 3431 carlsonj 345 3431 carlsonj static const char * 346 3431 carlsonj entr_to_str(uint32_t entr) 347 3431 carlsonj { 348 3431 carlsonj switch (entr) { 349 3431 carlsonj case DHCPV6_SUN_ENT: 350 3431 carlsonj return ("Sun Microsystems"); 351 3431 carlsonj default: 352 3431 carlsonj return ("Unknown"); 353 3431 carlsonj } 354 3431 carlsonj } 355 3431 carlsonj 356 3431 carlsonj static const char * 357 3431 carlsonj reconf_to_str(uint8_t msgtype) 358 3431 carlsonj { 359 3431 carlsonj switch (msgtype) { 360 3431 carlsonj case DHCPV6_RECONF_RENEW: 361 3431 carlsonj return ("Renew"); 362 3431 carlsonj case DHCPV6_RECONF_INFO: 363 3431 carlsonj return ("Information-request"); 364 3431 carlsonj default: 365 3431 carlsonj return ("Unknown"); 366 3431 carlsonj } 367 3431 carlsonj } 368 3431 carlsonj 369 3431 carlsonj static const char * 370 3431 carlsonj authproto_to_str(uint8_t aproto) 371 3431 carlsonj { 372 3431 carlsonj switch (aproto) { 373 3431 carlsonj case DHCPV6_PROTO_DELAYED: 374 3431 carlsonj return ("Delayed"); 375 3431 carlsonj case DHCPV6_PROTO_RECONFIG: 376 3431 carlsonj return ("Reconfigure Key"); 377 3431 carlsonj default: 378 3431 carlsonj return ("Unknown"); 379 3431 carlsonj } 380 3431 carlsonj } 381 3431 carlsonj 382 3431 carlsonj static const char * 383 3431 carlsonj authalg_to_str(uint8_t aproto, uint8_t aalg) 384 3431 carlsonj { 385 3431 carlsonj switch (aproto) { 386 3431 carlsonj case DHCPV6_PROTO_DELAYED: 387 3431 carlsonj case DHCPV6_PROTO_RECONFIG: 388 3431 carlsonj switch (aalg) { 389 3431 carlsonj case DHCPV6_ALG_HMAC_MD5: 390 3431 carlsonj return ("HMAC-MD5 Signature"); 391 3431 carlsonj default: 392 3431 carlsonj return ("Unknown"); 393 3431 carlsonj } 394 3431 carlsonj break; 395 3431 carlsonj default: 396 3431 carlsonj return ("Unknown"); 397 3431 carlsonj } 398 3431 carlsonj } 399 3431 carlsonj 400 3431 carlsonj static const char * 401 3431 carlsonj authrdm_to_str(uint8_t ardm) 402 3431 carlsonj { 403 3431 carlsonj switch (ardm) { 404 3431 carlsonj case DHCPV6_RDM_MONOCNT: 405 3431 carlsonj return ("Monotonic Counter"); 406 3431 carlsonj default: 407 3431 carlsonj return ("Unknown"); 408 3431 carlsonj } 409 3431 carlsonj } 410 3431 carlsonj 411 3431 carlsonj static const char * 412 3431 carlsonj cwhat_to_str(uint8_t what) 413 3431 carlsonj { 414 3431 carlsonj switch (what) { 415 3431 carlsonj case DHCPV6_CWHAT_SERVER: 416 3431 carlsonj return ("Server"); 417 3431 carlsonj case DHCPV6_CWHAT_NETWORK: 418 3431 carlsonj return ("Network"); 419 3431 carlsonj case DHCPV6_CWHAT_CLIENT: 420 3431 carlsonj return ("Client"); 421 3431 carlsonj default: 422 3431 carlsonj return ("Unknown"); 423 3431 carlsonj } 424 3431 carlsonj } 425 3431 carlsonj 426 3431 carlsonj static const char * 427 3431 carlsonj catype_to_str(uint8_t catype) 428 3431 carlsonj { 429 3431 carlsonj switch (catype) { 430 3431 carlsonj case CIVICADDR_LANG: 431 3431 carlsonj return ("Language; RFC 2277"); 432 3431 carlsonj case CIVICADDR_A1: 433 3431 carlsonj return ("National division (state)"); 434 3431 carlsonj case CIVICADDR_A2: 435 3431 carlsonj return ("County"); 436 3431 carlsonj case CIVICADDR_A3: 437 3431 carlsonj return ("City"); 438 3431 carlsonj case CIVICADDR_A4: 439 3431 carlsonj return ("City division"); 440 3431 carlsonj case CIVICADDR_A5: 441 3431 carlsonj return ("Neighborhood"); 442 3431 carlsonj case CIVICADDR_A6: 443 3431 carlsonj return ("Street group"); 444 3431 carlsonj case CIVICADDR_PRD: 445 3431 carlsonj return ("Leading street direction"); 446 3431 carlsonj case CIVICADDR_POD: 447 3431 carlsonj return ("Trailing street suffix"); 448 3431 carlsonj case CIVICADDR_STS: 449 3431 carlsonj return ("Street suffix or type"); 450 3431 carlsonj case CIVICADDR_HNO: 451 3431 carlsonj return ("House number"); 452 3431 carlsonj case CIVICADDR_HNS: 453 3431 carlsonj return ("House number suffix"); 454 3431 carlsonj case CIVICADDR_LMK: 455 3431 carlsonj return ("Landmark"); 456 3431 carlsonj case CIVICADDR_LOC: 457 3431 carlsonj return ("Additional location information"); 458 3431 carlsonj case CIVICADDR_NAM: 459 3431 carlsonj return ("Name/occupant"); 460 3431 carlsonj case CIVICADDR_PC: 461 3431 carlsonj return ("Postal Code/ZIP"); 462 3431 carlsonj case CIVICADDR_BLD: 463 3431 carlsonj return ("Building"); 464 3431 carlsonj case CIVICADDR_UNIT: 465 3431 carlsonj return ("Unit/apt/suite"); 466 3431 carlsonj case CIVICADDR_FLR: 467 3431 carlsonj return ("Floor"); 468 3431 carlsonj case CIVICADDR_ROOM: 469 3431 carlsonj return ("Room number"); 470 3431 carlsonj case CIVICADDR_TYPE: 471 3431 carlsonj return ("Place type"); 472 3431 carlsonj case CIVICADDR_PCN: 473 3431 carlsonj return ("Postal community name"); 474 3431 carlsonj case CIVICADDR_POBOX: 475 3431 carlsonj return ("Post office box"); 476 3431 carlsonj case CIVICADDR_ADDL: 477 3431 carlsonj return ("Additional code"); 478 3431 carlsonj case CIVICADDR_SEAT: 479 3431 carlsonj return ("Seat/desk"); 480 3431 carlsonj case CIVICADDR_ROAD: 481 3431 carlsonj return ("Primary road or street"); 482 3431 carlsonj case CIVICADDR_RSEC: 483 3431 carlsonj return ("Road section"); 484 3431 carlsonj case CIVICADDR_RBRA: 485 3431 carlsonj return ("Road branch"); 486 3431 carlsonj case CIVICADDR_RSBR: 487 3431 carlsonj return ("Road sub-branch"); 488 3431 carlsonj case CIVICADDR_SPRE: 489 3431 carlsonj return ("Street name pre-modifier"); 490 3431 carlsonj case CIVICADDR_SPOST: 491 3431 carlsonj return ("Street name post-modifier"); 492 3431 carlsonj case CIVICADDR_SCRIPT: 493 3431 carlsonj return ("Script"); 494 3431 carlsonj default: 495 3431 carlsonj return ("Unknown"); 496 3431 carlsonj } 497 3431 carlsonj } 498 3431 carlsonj 499 3431 carlsonj static void 500 3431 carlsonj show_hex(const uint8_t *data, int len, const char *name) 501 3431 carlsonj { 502 3431 carlsonj char buffer[16 * 3 + 1]; 503 3431 carlsonj int nlen; 504 3431 carlsonj int i; 505 3431 carlsonj char sep; 506 3431 carlsonj 507 3431 carlsonj nlen = strlen(name); 508 3431 carlsonj sep = '='; 509 3431 carlsonj while (len > 0) { 510 3431 carlsonj for (i = 0; i < 16 && i < len; i++) 511 3431 carlsonj (void) snprintf(buffer + 3 * i, 4, " %02x", *data++); 512 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), "%*s %c%s", 513 3431 carlsonj nlen, name, sep, buffer); 514 3431 carlsonj name = ""; 515 3431 carlsonj sep = ' '; 516 3431 carlsonj len -= i; 517 3431 carlsonj } 518 3431 carlsonj } 519 3431 carlsonj 520 3431 carlsonj static void 521 3431 carlsonj show_ascii(const uint8_t *data, int len, const char *name) 522 3431 carlsonj { 523 3431 carlsonj char buffer[64], *bp; 524 3431 carlsonj int nlen; 525 3431 carlsonj int i; 526 3431 carlsonj char sep; 527 3431 carlsonj 528 3431 carlsonj nlen = strlen(name); 529 3431 carlsonj sep = '='; 530 3431 carlsonj while (len > 0) { 531 3431 carlsonj bp = buffer; 532 3431 carlsonj for (i = 0; i < sizeof (buffer) - 4 && len > 0; len--) { 533 3431 carlsonj if (!isascii(*data) || !isprint(*data)) 534 3431 carlsonj bp += snprintf(bp, 5, "\\%03o", *data++); 535 3431 carlsonj else 536 3431 carlsonj *bp++; 537 3431 carlsonj } 538 3431 carlsonj *bp = '\0'; 539 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 540 3431 carlsonj "%*s %c \"%s\"", nlen, name, sep, buffer); 541 3431 carlsonj sep = ' '; 542 3431 carlsonj name = ""; 543 3431 carlsonj } 544 3431 carlsonj } 545 3431 carlsonj 546 3431 carlsonj static void 547 3431 carlsonj show_address(const char *addrname, const void *aptr) 548 3431 carlsonj { 549 3431 carlsonj char *hname; 550 3431 carlsonj char addrstr[INET6_ADDRSTRLEN]; 551 3431 carlsonj in6_addr_t addr; 552 3431 carlsonj 553 3431 carlsonj (void) memcpy(&addr, aptr, sizeof (in6_addr_t)); 554 3431 carlsonj (void) inet_ntop(AF_INET6, &addr, addrstr, sizeof (addrstr)); 555 3431 carlsonj hname = addrtoname(AF_INET6, &addr); 556 3431 carlsonj if (strcmp(hname, addrstr) == 0) { 557 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), "%s = %s", 558 3431 carlsonj addrname, addrstr); 559 3431 carlsonj } else { 560 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 561 3431 carlsonj "%s = %s (%s)", addrname, addrstr, hname); 562 3431 carlsonj } 563 3431 carlsonj } 564 3431 carlsonj 565 3431 carlsonj static void 566 3431 carlsonj nest_options(const uint8_t *data, uint_t olen, char *prefix, char *title) 567 3431 carlsonj { 568 3431 carlsonj char *str, *oldnest, *oldprefix; 569 3431 carlsonj 570 3431 carlsonj if (olen <= 0) 571 3431 carlsonj return; 572 3431 carlsonj oldprefix = prot_prefix; 573 3431 carlsonj oldnest = prot_nest_prefix; 574 3431 carlsonj str = malloc(strlen(prot_nest_prefix) + strlen(prot_prefix) + 1); 575 3431 carlsonj if (str == NULL) { 576 3431 carlsonj prot_nest_prefix = prot_prefix; 577 3431 carlsonj } else { 578 3431 carlsonj (void) sprintf(str, "%s%s", prot_nest_prefix, prot_prefix); 579 3431 carlsonj prot_nest_prefix = str; 580 3431 carlsonj } 581 3431 carlsonj show_header(prefix, title, 0); 582 3431 carlsonj show_options(data, olen); 583 3431 carlsonj free(str); 584 3431 carlsonj prot_prefix = oldprefix; 585 3431 carlsonj prot_nest_prefix = oldnest; 586 3431 carlsonj } 587 3431 carlsonj 588 3431 carlsonj static void 589 3431 carlsonj show_options(const uint8_t *data, int len) 590 3431 carlsonj { 591 3431 carlsonj dhcpv6_option_t d6o; 592 3431 carlsonj uint_t olen, retlen; 593 3431 carlsonj uint16_t val16; 594 3431 carlsonj uint16_t type; 595 3431 carlsonj uint32_t val32; 596 3431 carlsonj const uint8_t *ostart; 597 3431 carlsonj char *str, *sp; 598 3431 carlsonj char *oldnest; 599 3431 carlsonj 600 3431 carlsonj /* 601 3431 carlsonj * Be very careful with negative numbers; ANSI signed/unsigned 602 3431 carlsonj * comparison doesn't work as expected. 603 3431 carlsonj */ 604 3431 carlsonj while (len >= (signed)sizeof (d6o)) { 605 3431 carlsonj (void) memcpy(&d6o, data, sizeof (d6o)); 606 3431 carlsonj d6o.d6o_code = ntohs(d6o.d6o_code); 607 3431 carlsonj d6o.d6o_len = olen = ntohs(d6o.d6o_len); 608 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 609 3431 carlsonj "Option Code = %u (%s)", d6o.d6o_code, 610 3431 carlsonj option_to_str(d6o.d6o_code)); 611 3431 carlsonj ostart = data += sizeof (d6o); 612 3431 carlsonj len -= sizeof (d6o); 613 3431 carlsonj if (olen > len) { 614 3431 carlsonj (void) strlcpy(get_line(0, 0), "Option truncated", 615 3431 carlsonj get_line_remain()); 616 3431 carlsonj olen = len; 617 3431 carlsonj } 618 3431 carlsonj switch (d6o.d6o_code) { 619 3431 carlsonj case DHCPV6_OPT_CLIENTID: 620 3431 carlsonj case DHCPV6_OPT_SERVERID: 621 3431 carlsonj if (olen < sizeof (val16)) 622 3431 carlsonj break; 623 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 624 3431 carlsonj data += sizeof (val16); 625 3431 carlsonj olen -= sizeof (val16); 626 3431 carlsonj type = ntohs(val16); 627 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 628 3431 carlsonj " DUID Type = %u (%s)", type, 629 3431 carlsonj duidtype_to_str(type)); 630 3431 carlsonj if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) { 631 3431 carlsonj if (olen < sizeof (val16)) 632 3431 carlsonj break; 633 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 634 3431 carlsonj data += sizeof (val16); 635 3431 carlsonj olen -= sizeof (val16); 636 3431 carlsonj val16 = ntohs(val16); 637 3431 carlsonj (void) snprintf(get_line(0, 0), 638 3431 carlsonj get_line_remain(), 639 3431 carlsonj " Hardware Type = %u (%s)", val16, 640 3431 carlsonj arp_htype(type)); 641 3431 carlsonj } 642 3431 carlsonj if (type == DHCPV6_DUID_LLT) { 643 3431 carlsonj time_t timevalue; 644 3431 carlsonj 645 3431 carlsonj if (olen < sizeof (val32)) 646 3431 carlsonj break; 647 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 648 3431 carlsonj data += sizeof (val32); 649 3431 carlsonj olen -= sizeof (val32); 650 3431 carlsonj timevalue = ntohl(val32) + DUID_TIME_BASE; 651 3431 carlsonj (void) snprintf(get_line(0, 0), 652 3431 carlsonj get_line_remain(), 653 3431 carlsonj " Time = %lu (%.24s)", ntohl(val32), 654 3431 carlsonj ctime(&timevalue)); 655 3431 carlsonj } 656 3431 carlsonj if (type == DHCPV6_DUID_EN) { 657 3431 carlsonj if (olen < sizeof (val32)) 658 3431 carlsonj break; 659 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 660 3431 carlsonj data += sizeof (val32); 661 3431 carlsonj olen -= sizeof (val32); 662 3431 carlsonj val32 = ntohl(val32); 663 3431 carlsonj (void) snprintf(get_line(0, 0), 664 3431 carlsonj get_line_remain(), 665 3431 carlsonj " Enterprise Number = %lu (%s)", val32, 666 3431 carlsonj entr_to_str(val32)); 667 3431 carlsonj } 668 3431 carlsonj if (olen == 0) 669 3431 carlsonj break; 670 3431 carlsonj if ((str = malloc(olen * 3)) == NULL) 671 3431 carlsonj pr_err("interpret_dhcpv6: no mem"); 672 3431 carlsonj sp = str + snprintf(str, 3, "%02x", *data++); 673 3431 carlsonj while (--olen > 0) { 674 3431 carlsonj *sp++ = (type == DHCPV6_DUID_LLT || 675 3431 carlsonj type == DHCPV6_DUID_LL) ? ':' : ' '; 676 3431 carlsonj sp = sp + snprintf(sp, 3, "%02x", *data++); 677 3431 carlsonj } 678 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 679 3431 carlsonj (type == DHCPV6_DUID_LLT || 680 3431 carlsonj type == DHCPV6_DUID_LL) ? 681 3431 carlsonj " Link Layer Address = %s" : 682 3431 carlsonj " Identifier = %s", str); 683 3431 carlsonj free(str); 684 3431 carlsonj break; 685 3431 carlsonj case DHCPV6_OPT_IA_NA: 686 3431 carlsonj case DHCPV6_OPT_IA_PD: { 687 3431 carlsonj dhcpv6_ia_na_t d6in; 688 3431 carlsonj 689 3431 carlsonj if (olen < sizeof (d6in) - sizeof (d6o)) 690 3431 carlsonj break; 691 3431 carlsonj (void) memcpy(&d6in, data - sizeof (d6o), 692 3431 carlsonj sizeof (d6in)); 693 3431 carlsonj data += sizeof (d6in) - sizeof (d6o); 694 3431 carlsonj olen -= sizeof (d6in) - sizeof (d6o); 695 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 696 3431 carlsonj " IAID = %u", ntohl(d6in.d6in_iaid)); 697 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 698 3431 carlsonj " T1 (renew) = %u seconds", ntohl(d6in.d6in_t1)); 699 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 700 3431 carlsonj " T2 (rebind) = %u seconds", ntohl(d6in.d6in_t2)); 701 3431 carlsonj nest_options(data, olen, "IA: ", 702 3431 carlsonj "Identity Association"); 703 3431 carlsonj break; 704 3431 carlsonj } 705 3431 carlsonj case DHCPV6_OPT_IA_TA: { 706 3431 carlsonj dhcpv6_ia_ta_t d6it; 707 3431 carlsonj 708 3431 carlsonj if (olen < sizeof (d6it) - sizeof (d6o)) 709 3431 carlsonj break; 710 3431 carlsonj (void) memcpy(&d6it, data - sizeof (d6o), 711 3431 carlsonj sizeof (d6it)); 712 3431 carlsonj data += sizeof (d6it) - sizeof (d6o); 713 3431 carlsonj olen -= sizeof (d6it) - sizeof (d6o); 714 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 715 3431 carlsonj " IAID = %u", ntohl(d6it.d6it_iaid)); 716 3431 carlsonj nest_options(data, olen, "IA: ", 717 3431 carlsonj "Identity Association"); 718 3431 carlsonj break; 719 3431 carlsonj } 720 3431 carlsonj case DHCPV6_OPT_IAADDR: { 721 3431 carlsonj dhcpv6_iaaddr_t d6ia; 722 3431 carlsonj 723 3431 carlsonj if (olen < sizeof (d6ia) - sizeof (d6o)) 724 3431 carlsonj break; 725 3431 carlsonj (void) memcpy(&d6ia, data - sizeof (d6o), 726 3431 carlsonj sizeof (d6ia)); 727 3431 carlsonj data += sizeof (d6ia) - sizeof (d6o); 728 3431 carlsonj olen -= sizeof (d6ia) - sizeof (d6o); 729 3431 carlsonj show_address(" Address", &d6ia.d6ia_addr); 730 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 731 3431 carlsonj " Preferred lifetime = %u seconds", 732 3431 carlsonj ntohl(d6ia.d6ia_preflife)); 733 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 734 3431 carlsonj " Valid lifetime = %u seconds", 735 3431 carlsonj ntohl(d6ia.d6ia_vallife)); 736 3431 carlsonj nest_options(data, olen, "ADDR: ", "Address"); 737 3431 carlsonj break; 738 3431 carlsonj } 739 3431 carlsonj case DHCPV6_OPT_ORO: 740 3431 carlsonj while (olen >= sizeof (val16)) { 741 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 742 3431 carlsonj val16 = ntohs(val16); 743 3431 carlsonj (void) snprintf(get_line(0, 0), 744 3431 carlsonj get_line_remain(), 745 3431 carlsonj " Requested Option Code = %u (%s)", val16, 746 3431 carlsonj option_to_str(val16)); 747 3431 carlsonj data += sizeof (val16); 748 3431 carlsonj olen -= sizeof (val16); 749 3431 carlsonj } 750 3431 carlsonj break; 751 3431 carlsonj case DHCPV6_OPT_PREFERENCE: 752 3431 carlsonj if (olen > 0) { 753 3431 carlsonj (void) snprintf(get_line(0, 0), 754 3431 carlsonj get_line_remain(), 755 3431 carlsonj *data == 255 ? 756 3431 carlsonj " Preference = %u (immediate)" : 757 3431 carlsonj " Preference = %u", *data); 758 3431 carlsonj } 759 3431 carlsonj break; 760 3431 carlsonj case DHCPV6_OPT_ELAPSED_TIME: 761 3431 carlsonj if (olen == sizeof (val16)) { 762 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 763 3431 carlsonj val16 = ntohs(val16); 764 3431 carlsonj (void) snprintf(get_line(0, 0), 765 3431 carlsonj get_line_remain(), 766 3431 carlsonj " Elapsed Time = %u.%02u seconds", 767 3431 carlsonj val16 / 100, val16 % 100); 768 3431 carlsonj } 769 3431 carlsonj break; 770 3431 carlsonj case DHCPV6_OPT_RELAY_MSG: 771 3431 carlsonj if (olen > 0) { 772 3431 carlsonj oldnest = prot_nest_prefix; 773 3431 carlsonj prot_nest_prefix = prot_prefix; 774 3431 carlsonj retlen = interpret_dhcpv6(F_DTAIL, data, olen); 775 3431 carlsonj prot_prefix = prot_nest_prefix; 776 3431 carlsonj prot_nest_prefix = oldnest; 777 3431 carlsonj } 778 3431 carlsonj break; 779 3431 carlsonj case DHCPV6_OPT_AUTH: { 780 3431 carlsonj dhcpv6_auth_t d6a; 781 3431 carlsonj 782 3431 carlsonj if (olen < DHCPV6_AUTH_SIZE - sizeof (d6o)) 783 3431 carlsonj break; 784 3431 carlsonj (void) memcpy(&d6a, data - sizeof (d6o), 785 3431 carlsonj DHCPV6_AUTH_SIZE); 786 3431 carlsonj data += DHCPV6_AUTH_SIZE - sizeof (d6o); 787 3431 carlsonj olen += DHCPV6_AUTH_SIZE - sizeof (d6o); 788 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 789 3431 carlsonj " Protocol = %u (%s)", d6a.d6a_proto, 790 3431 carlsonj authproto_to_str(d6a.d6a_proto)); 791 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 792 3431 carlsonj " Algorithm = %u (%s)", d6a.d6a_alg, 793 3431 carlsonj authalg_to_str(d6a.d6a_proto, d6a.d6a_alg)); 794 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 795 3431 carlsonj " Replay Detection Method = %u (%s)", d6a.d6a_rdm, 796 3431 carlsonj authrdm_to_str(d6a.d6a_rdm)); 797 3431 carlsonj show_hex(d6a.d6a_replay, sizeof (d6a.d6a_replay), 798 3431 carlsonj " RDM Data"); 799 3431 carlsonj if (olen > 0) 800 3431 carlsonj show_hex(data, olen, " Auth Info"); 801 3431 carlsonj break; 802 3431 carlsonj } 803 3431 carlsonj case DHCPV6_OPT_UNICAST: 804 3431 carlsonj if (olen >= sizeof (in6_addr_t)) 805 3431 carlsonj show_address(" Server Address", data); 806 3431 carlsonj break; 807 3431 carlsonj case DHCPV6_OPT_STATUS_CODE: 808 3431 carlsonj if (olen < sizeof (val16)) 809 3431 carlsonj break; 810 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 811 3431 carlsonj val16 = ntohs(val16); 812 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 813 3431 carlsonj " Status Code = %u (%s)", val16, 814 3431 carlsonj status_to_str(val16)); 815 3431 carlsonj data += sizeof (val16); 816 3431 carlsonj olen -= sizeof (val16); 817 3431 carlsonj if (olen > 0) 818 3431 carlsonj (void) snprintf(get_line(0, 0), 819 3431 carlsonj get_line_remain(), " Text = \"%.*s\"", 820 3431 carlsonj olen, data); 821 3431 carlsonj break; 822 3431 carlsonj case DHCPV6_OPT_VENDOR_CLASS: 823 3431 carlsonj if (olen < sizeof (val32)) 824 3431 carlsonj break; 825 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 826 3431 carlsonj data += sizeof (val32); 827 3431 carlsonj olen -= sizeof (val32); 828 3431 carlsonj val32 = ntohl(val32); 829 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 830 3431 carlsonj " Enterprise Number = %lu (%s)", val32, 831 3431 carlsonj entr_to_str(val32)); 832 3431 carlsonj /* FALLTHROUGH */ 833 3431 carlsonj case DHCPV6_OPT_USER_CLASS: 834 3431 carlsonj while (olen >= sizeof (val16)) { 835 3431 carlsonj (void) memcpy(&val16, data, sizeof (val16)); 836 3431 carlsonj data += sizeof (val16); 837 3431 carlsonj olen -= sizeof (val16); 838 3431 carlsonj val16 = ntohs(val16); 839 3431 carlsonj if (val16 > olen) { 840 3431 carlsonj (void) strlcpy(get_line(0, 0), 841 3431 carlsonj " Truncated class", 842 3431 carlsonj get_line_remain()); 843 3431 carlsonj val16 = olen; 844 3431 carlsonj } 845 3431 carlsonj show_hex(data, olen, " Class"); 846 3431 carlsonj data += val16; 847 3431 carlsonj olen -= val16; 848 3431 carlsonj } 849 3431 carlsonj break; 850 3431 carlsonj case DHCPV6_OPT_VENDOR_OPT: { 851 3431 carlsonj dhcpv6_option_t sd6o; 852 3431 carlsonj 853 3431 carlsonj if (olen < sizeof (val32)) 854 3431 carlsonj break; 855 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 856 3431 carlsonj data += sizeof (val32); 857 3431 carlsonj olen -= sizeof (val32); 858 3431 carlsonj val32 = ntohl(val32); 859 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 860 3431 carlsonj " Enterprise Number = %lu (%s)", val32, 861 3431 carlsonj entr_to_str(val32)); 862 3431 carlsonj while (olen >= sizeof (sd6o)) { 863 3431 carlsonj (void) memcpy(&sd6o, data, sizeof (sd6o)); 864 3431 carlsonj sd6o.d6o_code = ntohs(sd6o.d6o_code); 865 3431 carlsonj sd6o.d6o_len = ntohs(sd6o.d6o_len); 866 3431 carlsonj (void) snprintf(get_line(0, 0), 867 3431 carlsonj get_line_remain(), 868 3431 carlsonj " Vendor Option Code = %u", d6o.d6o_code); 869 3431 carlsonj data += sizeof (d6o); 870 3431 carlsonj olen -= sizeof (d6o); 871 3431 carlsonj if (sd6o.d6o_len > olen) { 872 3431 carlsonj (void) strlcpy(get_line(0, 0), 873 3431 carlsonj " Vendor Option truncated", 874 3431 carlsonj get_line_remain()); 875 3431 carlsonj sd6o.d6o_len = olen; 876 3431 carlsonj } 877 3431 carlsonj if (sd6o.d6o_len > 0) { 878 3431 carlsonj show_hex(data, sd6o.d6o_len, 879 3431 carlsonj " Data"); 880 3431 carlsonj data += sd6o.d6o_len; 881 3431 carlsonj olen -= sd6o.d6o_len; 882 3431 carlsonj } 883 3431 carlsonj } 884 3431 carlsonj break; 885 3431 carlsonj } 886 3431 carlsonj case DHCPV6_OPT_REMOTE_ID: 887 3431 carlsonj if (olen < sizeof (val32)) 888 3431 carlsonj break; 889 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 890 3431 carlsonj data += sizeof (val32); 891 3431 carlsonj olen -= sizeof (val32); 892 3431 carlsonj val32 = ntohl(val32); 893 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 894 3431 carlsonj " Enterprise Number = %lu (%s)", val32, 895 3431 carlsonj entr_to_str(val32)); 896 3431 carlsonj /* FALLTHROUGH */ 897 3431 carlsonj case DHCPV6_OPT_INTERFACE_ID: 898 3431 carlsonj case DHCPV6_OPT_SUBSCRIBER: 899 3431 carlsonj if (olen > 0) 900 3431 carlsonj show_hex(data, olen, " ID"); 901 3431 carlsonj break; 902 3431 carlsonj case DHCPV6_OPT_RECONF_MSG: 903 3431 carlsonj if (olen > 0) { 904 3431 carlsonj (void) snprintf(get_line(0, 0), 905 3431 carlsonj get_line_remain(), 906 3431 carlsonj " Message Type = %u (%s)", *data, 907 3431 carlsonj reconf_to_str(*data)); 908 3431 carlsonj } 909 3431 carlsonj break; 910 3431 carlsonj case DHCPV6_OPT_SIP_NAMES: 911 3431 carlsonj case DHCPV6_OPT_DNS_SEARCH: 912 3431 carlsonj case DHCPV6_OPT_NIS_DOMAIN: 913 3431 carlsonj case DHCPV6_OPT_NISP_DOMAIN: 914 3431 carlsonj case DHCPV6_OPT_BCMCS_SRV_D: { 915 3431 carlsonj dhcp_symbol_t *symp; 916 3431 carlsonj char *sp2; 917 3431 carlsonj 918 3431 carlsonj symp = inittab_getbycode( 919 3431 carlsonj ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP, 920 3431 carlsonj d6o.d6o_code); 921 3431 carlsonj if (symp != NULL) { 922 3431 carlsonj str = inittab_decode(symp, data, olen, B_TRUE); 923 3431 carlsonj if (str != NULL) { 924 3431 carlsonj sp = str; 925 3431 carlsonj do { 926 3431 carlsonj sp2 = strchr(sp, ' '); 927 3431 carlsonj if (sp2 != NULL) 928 3431 carlsonj *sp2++ = '\0'; 929 3431 carlsonj (void) snprintf(get_line(0, 0), 930 3431 carlsonj get_line_remain(), 931 3431 carlsonj " Name = %s", sp); 932 3431 carlsonj } while ((sp = sp2) != NULL); 933 3431 carlsonj free(str); 934 3431 carlsonj } 935 3431 carlsonj free(symp); 936 3431 carlsonj } 937 3431 carlsonj break; 938 3431 carlsonj } 939 3431 carlsonj case DHCPV6_OPT_SIP_ADDR: 940 3431 carlsonj case DHCPV6_OPT_DNS_ADDR: 941 3431 carlsonj case DHCPV6_OPT_NIS_SERVERS: 942 3431 carlsonj case DHCPV6_OPT_NISP_SERVERS: 943 3431 carlsonj case DHCPV6_OPT_SNTP_SERVERS: 944 3431 carlsonj case DHCPV6_OPT_BCMCS_SRV_A: 945 3431 carlsonj while (olen >= sizeof (in6_addr_t)) { 946 3431 carlsonj show_address(" Address", data); 947 3431 carlsonj data += sizeof (in6_addr_t); 948 3431 carlsonj olen -= sizeof (in6_addr_t); 949 3431 carlsonj } 950 3431 carlsonj break; 951 3431 carlsonj case DHCPV6_OPT_IAPREFIX: { 952 3431 carlsonj dhcpv6_iaprefix_t d6ip; 953 3431 carlsonj 954 3431 carlsonj if (olen < DHCPV6_IAPREFIX_SIZE - sizeof (d6o)) 955 3431 carlsonj break; 956 3431 carlsonj (void) memcpy(&d6ip, data - sizeof (d6o), 957 3431 carlsonj DHCPV6_IAPREFIX_SIZE); 958 3431 carlsonj data += DHCPV6_IAPREFIX_SIZE - sizeof (d6o); 959 3431 carlsonj olen -= DHCPV6_IAPREFIX_SIZE - sizeof (d6o); 960 3431 carlsonj show_address(" Prefix", d6ip.d6ip_addr); 961 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 962 3431 carlsonj " Preferred lifetime = %u seconds", 963 3431 carlsonj ntohl(d6ip.d6ip_preflife)); 964 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 965 3431 carlsonj " Valid lifetime = %u seconds", 966 3431 carlsonj ntohl(d6ip.d6ip_vallife)); 967 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 968 3431 carlsonj " Prefix length = %u", d6ip.d6ip_preflen); 969 3431 carlsonj nest_options(data, olen, "ADDR: ", "Address"); 970 3431 carlsonj break; 971 3431 carlsonj } 972 3431 carlsonj case DHCPV6_OPT_INFO_REFTIME: 973 3431 carlsonj if (olen < sizeof (val32)) 974 3431 carlsonj break; 975 3431 carlsonj (void) memcpy(&val32, data, sizeof (val32)); 976 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 977 3431 carlsonj " Refresh Time = %lu seconds", ntohl(val32)); 978 3431 carlsonj break; 979 3431 carlsonj case DHCPV6_OPT_GEOCONF_CVC: { 980 3431 carlsonj dhcpv6_civic_t d6c; 981 3431 carlsonj int solen; 982 3431 carlsonj 983 3431 carlsonj if (olen < DHCPV6_CIVIC_SIZE - sizeof (d6o)) 984 3431 carlsonj break; 985 3431 carlsonj (void) memcpy(&d6c, data - sizeof (d6o), 986 3431 carlsonj DHCPV6_CIVIC_SIZE); 987 3431 carlsonj data += DHCPV6_CIVIC_SIZE - sizeof (d6o); 988 3431 carlsonj olen -= DHCPV6_CIVIC_SIZE - sizeof (d6o); 989 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 990 3431 carlsonj " What Location = %u (%s)", d6c.d6c_what, 991 3431 carlsonj cwhat_to_str(d6c.d6c_what)); 992 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 993 3431 carlsonj " Country Code = %.*s", sizeof (d6c.d6c_cc), 994 3431 carlsonj d6c.d6c_cc); 995 3431 carlsonj while (olen >= 2) { 996 3431 carlsonj (void) snprintf(get_line(0, 0), 997 3431 carlsonj get_line_remain(), 998 3431 carlsonj " CA Element = %u (%s)", *data, 999 3431 carlsonj catype_to_str(*data)); 1000 3431 carlsonj solen = data[1]; 1001 3431 carlsonj data += 2; 1002 3431 carlsonj olen -= 2; 1003 3431 carlsonj if (solen > olen) { 1004 3431 carlsonj (void) strlcpy(get_line(0, 0), 1005 3431 carlsonj " CA Element truncated", 1006 3431 carlsonj get_line_remain()); 1007 3431 carlsonj solen = olen; 1008 3431 carlsonj } 1009 3431 carlsonj if (solen > 0) { 1010 3431 carlsonj show_ascii(data, solen, " CA Data"); 1011 3431 carlsonj data += solen; 1012 3431 carlsonj olen -= solen; 1013 3431 carlsonj } 1014 3431 carlsonj } 1015 3431 carlsonj break; 1016 3431 carlsonj } 1017 3431 carlsonj case DHCPV6_OPT_CLIENT_FQDN: { 1018 3431 carlsonj dhcp_symbol_t *symp; 1019 3431 carlsonj 1020 3431 carlsonj if (olen == 0) 1021 3431 carlsonj break; 1022 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 1023 3431 carlsonj " Flags = %02x", *data); 1024 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 1025 3431 carlsonj " %s", getflag(*data, DHCPV6_FQDNF_S, 1026 3431 carlsonj "Perform AAAA RR updates", "No AAAA RR updates")); 1027 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 1028 3431 carlsonj " %s", getflag(*data, DHCPV6_FQDNF_O, 1029 3431 carlsonj "Server override updates", 1030 3431 carlsonj "No server override updates")); 1031 3431 carlsonj (void) snprintf(get_line(0, 0), get_line_remain(), 1032 3431 carlsonj " %s", getflag(*data, DHCPV6_FQDNF_N, 1033 3431 carlsonj "Server performs no updates", 1034 3431 carlsonj "Server performs updates")); 1035 3431 carlsonj symp = inittab_getbycode( 1036 3431 carlsonj ITAB_CAT_STANDARD | ITAB_CAT_V6, ITAB_CONS_SNOOP, 1037 3431 carlsonj d6o.d6o_code); 1038 3431 carlsonj if (symp != NULL) { 1039 3431 carlsonj str = inittab_decode(symp, data, olen, B_TRUE); 1040 3431 carlsonj if (str != NULL) { 1041 3431 carlsonj (void) snprintf(get_line(0, 0), 1042 3431 carlsonj get_line_remain(), 1043 3431 carlsonj " FQDN = %s", str); 1044 3431 carlsonj free(str); 1045 3431 carlsonj } 1046 3431 carlsonj free(symp); 1047 3431 carlsonj } 1048 3431 carlsonj break; 1049 3431 carlsonj } 1050 3431 carlsonj } 1051 3431 carlsonj data = ostart + d6o.d6o_len; 1052 3431 carlsonj len -= d6o.d6o_len; 1053 3431 carlsonj } 1054 3431 carlsonj if (len != 0) { 1055 3431 carlsonj (void) strlcpy(get_line(0, 0), "Option entry truncated", 1056 3431 carlsonj get_line_remain()); 1057 3431 carlsonj } 1058 3431 carlsonj } 1059