1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1481 kcpoon * Common Development and Distribution License (the "License"). 6 1481 kcpoon * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1481 kcpoon 22 0 stevel /* 23 9759 Vasumathi * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #include <ctype.h> 28 0 stevel #include <stdio.h> 29 0 stevel #include <stdlib.h> 30 0 stevel #include <fcntl.h> 31 0 stevel #include <string.h> 32 0 stevel #include <sys/types.h> 33 0 stevel #include <sys/socket.h> 34 0 stevel #include <sys/sysmacros.h> 35 0 stevel #include <netinet/in.h> 36 0 stevel #include <netinet/dhcp.h> 37 0 stevel #include <arpa/inet.h> 38 0 stevel #include <dhcp_inittab.h> 39 0 stevel #include <dhcp_symbol.h> 40 0 stevel #include "snoop.h" 41 0 stevel 42 0 stevel static const char *show_msgtype(unsigned char); 43 0 stevel static int show_options(unsigned char *, int); 44 0 stevel static void display_ip(int, char *, char *, unsigned char **); 45 0 stevel static void display_ascii(char *, char *, unsigned char **); 46 0 stevel static void display_number(char *, char *, unsigned char **); 47 0 stevel static void display_ascii_hex(char *, unsigned char **); 48 0 stevel static unsigned char bootmagic[] = BOOTMAGIC; /* rfc 1048 */ 49 0 stevel 50 0 stevel static char *option_types[] = { 51 0 stevel "", /* 0 */ 52 0 stevel "Subnet Mask", /* 1 */ 53 0 stevel "UTC Time Offset", /* 2 */ 54 0 stevel "Router", /* 3 */ 55 0 stevel "RFC868 Time Servers", /* 4 */ 56 0 stevel "IEN 116 Name Servers", /* 5 */ 57 0 stevel "DNS Servers", /* 6 */ 58 0 stevel "UDP LOG Servers", /* 7 */ 59 0 stevel "RFC 865 Cookie Servers", /* 8 */ 60 0 stevel "RFC 1179 Line Printer Servers (LPR)", /* 9 */ 61 0 stevel "Impress Servers", /* 10 */ 62 0 stevel "RFC 887 Resource Location Servers", /* 11 */ 63 0 stevel "Client Hostname", /* 12 */ 64 0 stevel "Boot File size in 512 byte Blocks", /* 13 */ 65 0 stevel "Merit Dump File", /* 14 */ 66 0 stevel "DNS Domain Name", /* 15 */ 67 0 stevel "SWAP Server", /* 16 */ 68 0 stevel "Client Root Path", /* 17 */ 69 0 stevel "BOOTP options extensions path", /* 18 */ 70 0 stevel "IP Forwarding Flag", /* 19 */ 71 0 stevel "NonLocal Source Routing Flag", /* 20 */ 72 0 stevel "Policy Filters for NonLocal Routing", /* 21 */ 73 0 stevel "Maximum Datagram Reassembly Size", /* 22 */ 74 0 stevel "Default IP Time To Live", /* 23 */ 75 0 stevel "Path MTU Aging Timeout", /* 24 */ 76 0 stevel "Path MTU Size Plateau Table", /* 25 */ 77 0 stevel "Interface MTU Size", /* 26 */ 78 0 stevel "All Subnets are Local Flag", /* 27 */ 79 0 stevel "Broadcast Address", /* 28 */ 80 0 stevel "Perform Mask Discovery Flag", /* 29 */ 81 0 stevel "Mask Supplier Flag", /* 30 */ 82 0 stevel "Perform Router Discovery Flag", /* 31 */ 83 0 stevel "Router Solicitation Address", /* 32 */ 84 0 stevel "Static Routes", /* 33 */ 85 0 stevel "Trailer Encapsulation Flag", /* 34 */ 86 0 stevel "ARP Cache Timeout Seconds", /* 35 */ 87 0 stevel "Ethernet Encapsulation Flag", /* 36 */ 88 0 stevel "TCP Default Time To Live", /* 37 */ 89 0 stevel "TCP Keepalive Interval Seconds", /* 38 */ 90 0 stevel "TCP Keepalive Garbage Flag", /* 39 */ 91 0 stevel "NIS Domainname", /* 40 */ 92 0 stevel "NIS Servers", /* 41 */ 93 0 stevel "Network Time Protocol Servers", /* 42 */ 94 0 stevel "Vendor Specific Options", /* 43 */ 95 0 stevel "NetBIOS RFC 1001/1002 Name Servers", /* 44 */ 96 0 stevel "NetBIOS Datagram Dist. Servers", /* 45 */ 97 0 stevel "NetBIOS Node Type", /* 46 */ 98 0 stevel "NetBIOS Scope", /* 47 */ 99 0 stevel "X Window Font Servers", /* 48 */ 100 0 stevel "X Window Display Manager Servers", /* 49 */ 101 0 stevel "Requested IP Address", /* 50 */ 102 0 stevel "IP Address Lease Time", /* 51 */ 103 0 stevel "Option Field Overload Flag", /* 52 */ 104 0 stevel "DHCP Message Type", /* 53 */ 105 0 stevel "DHCP Server Identifier", /* 54 */ 106 0 stevel "Option Request List", /* 55 */ 107 0 stevel "Error Message", /* 56 */ 108 0 stevel "Maximum DHCP Message Size", /* 57 */ 109 0 stevel "Renewal (T1) Time Value", /* 58 */ 110 0 stevel "Rebinding (T2) Time Value", /* 59 */ 111 0 stevel "Client Class Identifier =", /* 60 */ 112 0 stevel "Client Identifier =", /* 61 */ 113 0 stevel "Netware IP Domain =", /* 62 */ 114 0 stevel "Netware IP Options =", /* 63 */ 115 0 stevel "NISPLUS Domainname", /* 64 */ 116 0 stevel "NISPLUS Servers", /* 65 */ 117 0 stevel "TFTP Server Name", /* 66 */ 118 0 stevel "Option BootFile Name", /* 67 */ 119 0 stevel "Mobile IP Agents", /* 68 */ 120 0 stevel "Simple Mail (SMTP) Servers", /* 69 */ 121 0 stevel "Post Office (POP3) Servers", /* 70 */ 122 0 stevel "Net News (NNTP) Servers", /* 71 */ 123 0 stevel "WorldWideWeb Servers", /* 72 */ 124 0 stevel "Finger Servers", /* 73 */ 125 0 stevel "Internet Relay Chat (IRC) Servers", /* 74 */ 126 0 stevel "StreetTalk Servers", /* 75 */ 127 0 stevel "StreetTalk Directory Assist. Servers", /* 76 */ 128 0 stevel "User Class Identifier", /* 77 */ 129 0 stevel }; 130 0 stevel 131 0 stevel #define OPTIONS_ARRAY_SIZE 78 132 0 stevel 133 0 stevel int 134 1676 jpk interpret_dhcp(int flags, struct dhcp *dp, int len) 135 0 stevel { 136 0 stevel if (flags & F_SUM) { 137 0 stevel if ((memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) == 0) && 138 0 stevel (len >= BASE_PKT_SIZE + 3) && 139 0 stevel dp->options[0] == CD_DHCP_TYPE) { 140 0 stevel (void) sprintf(get_sum_line(), 141 0 stevel "DHCP/BOOTP %s", show_msgtype(dp->options[2])); 142 0 stevel } else { 143 0 stevel switch (ntohs(dp->op)) { 144 0 stevel case BOOTREQUEST: 145 0 stevel (void) sprintf(get_sum_line(), 146 0 stevel "DHCP/BOOTP BOOTREQUEST"); 147 0 stevel break; 148 0 stevel case BOOTREPLY: 149 0 stevel (void) sprintf(get_sum_line(), 150 0 stevel "DHCP/BOOTP BOOTREPLY"); 151 0 stevel break; 152 0 stevel } 153 0 stevel } 154 0 stevel } 155 0 stevel if (flags & F_DTAIL) { 156 0 stevel show_header("DHCP: ", "Dynamic Host Configuration Protocol", 157 0 stevel len); 158 0 stevel show_space(); 159 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->htype - 160 410 kcpoon dlc_header, 1), 161 0 stevel "Hardware address type (htype) = %d (%s)", dp->htype, 162 3431 carlsonj arp_htype(dp->htype)); 163 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->hlen - 164 410 kcpoon dlc_header, 1), 165 0 stevel "Hardware address length (hlen) = %d octets", dp->hlen); 166 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->hops - 167 410 kcpoon dlc_header, 1), 168 0 stevel "Relay agent hops = %d", dp->hops); 169 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->xid - 170 410 kcpoon dlc_header, 4), 171 0 stevel "Transaction ID = 0x%x", ntohl(dp->xid)); 172 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->secs - 173 410 kcpoon dlc_header, 2), 174 0 stevel "Time since boot = %d seconds", ntohs(dp->secs)); 175 410 kcpoon (void) sprintf(get_line((char *)(uintptr_t)dp->flags - 176 410 kcpoon dlc_header, 2), 177 0 stevel "Flags = 0x%.4x", ntohs(dp->flags)); 178 0 stevel (void) sprintf(get_line((char *)&dp->ciaddr - dlc_header, 4), 179 0 stevel "Client address (ciaddr) = %s", inet_ntoa(dp->ciaddr)); 180 0 stevel (void) sprintf(get_line((char *)&dp->yiaddr - dlc_header, 4), 181 0 stevel "Your client address (yiaddr) = %s", 182 0 stevel inet_ntoa(dp->yiaddr)); 183 0 stevel (void) sprintf(get_line((char *)&dp->siaddr - dlc_header, 4), 184 0 stevel "Next server address (siaddr) = %s", 185 0 stevel inet_ntoa(dp->siaddr)); 186 0 stevel (void) sprintf(get_line((char *)&dp->giaddr - dlc_header, 4), 187 0 stevel "Relay agent address (giaddr) = %s", 188 0 stevel inet_ntoa(dp->giaddr)); 189 0 stevel if (dp->htype == 1) { 190 0 stevel (void) sprintf(get_line((char *)dp->chaddr - 191 0 stevel dlc_header, dp->hlen), 192 0 stevel "Client hardware address (chaddr) = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", 193 0 stevel dp->chaddr[0], 194 0 stevel dp->chaddr[1], 195 0 stevel dp->chaddr[2], 196 0 stevel dp->chaddr[3], 197 0 stevel dp->chaddr[4], 198 0 stevel dp->chaddr[5]); 199 0 stevel } 200 0 stevel /* 201 0 stevel * Check cookie, process options 202 0 stevel */ 203 0 stevel if (memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) != 0) { 204 0 stevel (void) sprintf(get_line(0, 0), 205 0 stevel "Unrecognized cookie: 0x%.2X%.2X%.2X%.2X\n", 206 0 stevel dp->cookie[0], 207 0 stevel dp->cookie[1], 208 0 stevel dp->cookie[2], 209 0 stevel dp->cookie[3]); 210 0 stevel return (0); 211 0 stevel } 212 0 stevel show_space(); 213 0 stevel show_header("DHCP: ", "(Options) field options", len); 214 0 stevel show_space(); 215 0 stevel switch (show_options(dp->options, (len - BASE_PKT_SIZE))) { 216 0 stevel case 0: 217 0 stevel /* No option overloading */ 218 0 stevel if (*(unsigned char *)(dp->sname) != '\0') { 219 0 stevel (void) sprintf(get_line(0, 0), 220 0 stevel "Server Name = %s", dp->sname); 221 0 stevel } 222 0 stevel if (*(unsigned char *)(dp->file) != '\0') { 223 0 stevel (void) sprintf(get_line(0, 0), 224 0 stevel "Boot File Name = %s", dp->file); 225 0 stevel } 226 0 stevel break; 227 0 stevel case 1: 228 0 stevel /* file field used */ 229 0 stevel if (*(unsigned char *)(dp->sname) != '\0') { 230 0 stevel (void) sprintf(get_line(0, 0), 231 0 stevel "Server Name = %s", dp->sname); 232 0 stevel } 233 0 stevel show_space(); 234 0 stevel show_header("DHCP: ", "(File) field options", len); 235 0 stevel show_space(); 236 0 stevel (void) show_options(dp->file, 128); 237 0 stevel break; 238 0 stevel case 2: 239 0 stevel /* sname field used for options */ 240 0 stevel if (*(unsigned char *)(dp->file) != '\0') { 241 0 stevel (void) sprintf(get_line(0, 0), 242 0 stevel "Boot File Name = %s", dp->file); 243 0 stevel } 244 0 stevel show_space(); 245 0 stevel show_header("DHCP: ", "(Sname) field options", len); 246 0 stevel show_space(); 247 0 stevel (void) show_options(dp->sname, 64); 248 0 stevel break; 249 0 stevel case 3: 250 0 stevel show_space(); 251 0 stevel show_header("DHCP: ", "(File) field options", len); 252 0 stevel show_space(); 253 0 stevel (void) show_options(dp->file, 128); 254 0 stevel show_space(); 255 0 stevel show_header("DHCP: ", "(Sname) field options", len); 256 0 stevel show_space(); 257 0 stevel (void) show_options(dp->sname, 64); 258 0 stevel break; 259 0 stevel }; 260 0 stevel } 261 0 stevel return (len); 262 0 stevel } 263 3431 carlsonj 264 0 stevel static int 265 0 stevel show_options(unsigned char *cp, int len) 266 0 stevel { 267 0 stevel char *prmpt; 268 0 stevel unsigned char *end, *vend; 269 0 stevel unsigned char *start, save; 270 0 stevel int items, i; 271 0 stevel int nooverload = 0; 272 0 stevel ushort_t s_buf; 273 0 stevel struct in_addr tmp; 274 0 stevel char scratch[128]; 275 0 stevel dhcp_symbol_t *entry; 276 0 stevel char *decoded_opt; 277 0 stevel int opt_len; 278 0 stevel 279 0 stevel start = cp; 280 0 stevel end = (unsigned char *)cp + len; 281 0 stevel 282 0 stevel while (start < end) { 283 0 stevel if (*start == CD_PAD) { 284 0 stevel start++; 285 0 stevel continue; 286 0 stevel } 287 0 stevel if (*start == CD_END) 288 0 stevel break; /* done */ 289 0 stevel 290 0 stevel save = *start++; 291 0 stevel switch (save) { 292 0 stevel /* Network order IP address(es) */ 293 0 stevel case CD_SUBNETMASK: 294 0 stevel case CD_ROUTER_SOLICIT_SERV: 295 0 stevel case CD_BROADCASTADDR: 296 0 stevel case CD_REQUESTED_IP_ADDR: 297 0 stevel case CD_SERVER_ID: 298 0 stevel /* Single IP address */ 299 0 stevel if (*start != 4) { 300 0 stevel (void) sprintf(get_line(0, 0), 301 0 stevel "Error: Bad %s", option_types[save]); 302 0 stevel } else { 303 0 stevel start++; 304 0 stevel display_ip(1, "%s = %s", option_types[save], 305 0 stevel &start); 306 0 stevel } 307 0 stevel break; 308 0 stevel case CD_ROUTER: 309 0 stevel case CD_TIMESERV: 310 0 stevel case CD_IEN116_NAME_SERV: 311 0 stevel case CD_DNSSERV: 312 0 stevel case CD_LOG_SERV: 313 0 stevel case CD_COOKIE_SERV: 314 0 stevel case CD_LPR_SERV: 315 0 stevel case CD_IMPRESS_SERV: 316 0 stevel case CD_RESOURCE_SERV: 317 0 stevel case CD_SWAP_SERV: 318 0 stevel case CD_NIS_SERV: 319 0 stevel case CD_NTP_SERV: 320 0 stevel case CD_NETBIOS_NAME_SERV: 321 0 stevel case CD_NETBIOS_DIST_SERV: 322 0 stevel case CD_XWIN_FONT_SERV: 323 0 stevel case CD_XWIN_DISP_SERV: 324 0 stevel case CD_NISPLUS_SERVS: 325 0 stevel case CD_MOBILE_IP_AGENT: 326 0 stevel case CD_SMTP_SERVS: 327 0 stevel case CD_POP3_SERVS: 328 0 stevel case CD_NNTP_SERVS: 329 0 stevel case CD_WWW_SERVS: 330 0 stevel case CD_FINGER_SERVS: 331 0 stevel case CD_IRC_SERVS: 332 0 stevel case CD_STREETTALK_SERVS: 333 0 stevel case CD_STREETTALK_DA_SERVS: 334 0 stevel /* Multiple IP addresses */ 335 0 stevel if ((*start % 4) != 0) { 336 0 stevel (void) sprintf(get_line(0, 0), 337 0 stevel "Error: Bad %s address", 338 0 stevel option_types[save]); 339 0 stevel } else { 340 1481 kcpoon items = *start++ / 4; 341 1481 kcpoon display_ip(items, "%s at = %s", 342 0 stevel option_types[save], &start); 343 0 stevel } 344 0 stevel break; 345 0 stevel case CD_TFTP_SERV_NAME: 346 0 stevel case CD_HOSTNAME: 347 0 stevel case CD_DUMP_FILE: 348 0 stevel case CD_DNSDOMAIN: 349 0 stevel case CD_ROOT_PATH: 350 0 stevel case CD_NIS_DOMAIN: 351 0 stevel case CD_NETBIOS_SCOPE: 352 0 stevel case CD_MESSAGE: 353 0 stevel case CD_NISPLUS_DMAIN: 354 0 stevel case CD_OPT_BOOTFILE_NAME: 355 0 stevel case CD_USER_CLASS_ID: 356 0 stevel /* Ascii strings */ 357 0 stevel display_ascii("%s = %s", option_types[save], &start); 358 0 stevel break; 359 0 stevel case CD_TIMEOFFSET: 360 0 stevel case CD_IPTTL: 361 0 stevel case CD_PATH_MTU_TIMEOUT: 362 0 stevel case CD_ARP_TIMEOUT: 363 0 stevel case CD_TCP_TTL: 364 0 stevel case CD_TCP_KALIVE_INTVL: 365 0 stevel case CD_T1_TIME: 366 0 stevel case CD_T2_TIME: 367 0 stevel case CD_LEASE_TIME: 368 0 stevel /* Number: seconds */ 369 0 stevel display_number("%s = %d seconds", option_types[save], 370 0 stevel &start); 371 0 stevel break; 372 0 stevel case CD_IP_FORWARDING_ON: 373 0 stevel case CD_NON_LCL_ROUTE_ON: 374 0 stevel case CD_ALL_SUBNETS_LCL_ON: 375 0 stevel case CD_MASK_DISCVRY_ON: 376 0 stevel case CD_MASK_SUPPLIER_ON: 377 0 stevel case CD_ROUTER_DISCVRY_ON: 378 0 stevel case CD_TRAILER_ENCAPS_ON: 379 0 stevel case CD_ETHERNET_ENCAPS_ON: 380 0 stevel case CD_TCP_KALIVE_GRBG_ON: 381 0 stevel /* Number: hex flag */ 382 0 stevel display_number("%s flag = 0x%x", option_types[save], 383 0 stevel &start); 384 0 stevel break; 385 0 stevel case CD_MAXIPSIZE: 386 0 stevel case CD_MTU: 387 0 stevel case CD_MAX_DHCP_SIZE: 388 0 stevel /* Number: bytes */ 389 0 stevel display_number("%s = %d bytes", option_types[save], 390 0 stevel &start); 391 0 stevel break; 392 0 stevel case CD_CLASS_ID: 393 0 stevel case CD_CLIENT_ID: 394 0 stevel case CD_NW_IP_DOMAIN: 395 0 stevel case CD_NW_IP_OPTIONS: 396 0 stevel /* Hex ascii strings */ 397 0 stevel display_ascii_hex(option_types[save], &start); 398 0 stevel break; 399 0 stevel case CD_BOOT_SIZE: 400 0 stevel display_number("%s = %d 512 byte blocks", 401 0 stevel "Boot file size", &start); 402 0 stevel break; 403 0 stevel case CD_POLICY_FILTER: 404 0 stevel if ((*start % 8) != 0) { 405 0 stevel (void) sprintf(get_line(0, 0), 406 0 stevel "Error: Bad Policy Filter option"); 407 0 stevel } else { 408 0 stevel items = *start++ / 8; 409 0 stevel for (i = 0; i < items; i++) { 410 0 stevel display_ip(1, 411 0 stevel "%s = %s", 412 0 stevel "Policy Destination", 413 0 stevel &start); 414 0 stevel display_ip(1, "%s = %s", "Mask", 415 0 stevel &start); 416 0 stevel } 417 0 stevel } 418 0 stevel break; 419 0 stevel case CD_PATH_MTU_TABLE_SZ: 420 0 stevel if (*start % 2 != 0) { 421 0 stevel (void) sprintf(get_line(0, 0), 422 0 stevel "Error: Bad Path MTU Table"); 423 0 stevel } else { 424 0 stevel (void) sprintf(get_line(0, 0), 425 0 stevel "\tPath MTU Plateau Table:"); 426 0 stevel (void) sprintf(get_line(0, 0), 427 0 stevel "\t======================="); 428 0 stevel items = *start / sizeof (ushort_t); 429 0 stevel ++start; 430 0 stevel for (i = 0; i < items; i++) { 431 0 stevel if (IS_P2ALIGNED(start, 432 9759 Vasumathi sizeof (ushort_t))) { 433 0 stevel /* LINTED: improper alignment */ 434 0 stevel s_buf = *(ushort_t *)start; 435 0 stevel } else { 436 0 stevel memcpy((char *)&s_buf, 437 0 stevel start, sizeof (short)); 438 0 stevel } 439 0 stevel (void) sprintf(get_line(0, 0), 440 0 stevel "\t\tEntry %d:\t\t%d", i, 441 0 stevel ntohs(s_buf)); 442 0 stevel start += sizeof (ushort_t); 443 0 stevel } 444 0 stevel } 445 0 stevel break; 446 0 stevel case CD_STATIC_ROUTE: 447 0 stevel if ((*start % 8) != 0) { 448 0 stevel (void) sprintf(get_line(0, 0), 449 0 stevel "Error: Bad Static Route option: %d", 450 0 stevel *start); 451 0 stevel } else { 452 0 stevel items = *start++ / 8; 453 0 stevel for (i = 0; i < items; i++) { 454 0 stevel memcpy((char *)&tmp, start, 455 0 stevel sizeof (struct in_addr)); 456 0 stevel (void) strcpy(scratch, inet_ntoa(tmp)); 457 0 stevel start += sizeof (ulong_t); 458 0 stevel memcpy((char *)&tmp, start, 459 0 stevel sizeof (struct in_addr)); 460 0 stevel (void) sprintf(get_line(0, 0), 461 0 stevel "Static route from %s to %s", 462 0 stevel scratch, inet_ntoa(tmp)); 463 0 stevel start += sizeof (ulong_t); 464 0 stevel } 465 0 stevel } 466 0 stevel break; 467 0 stevel case CD_VENDOR_SPEC: 468 0 stevel i = *start++; 469 0 stevel (void) sprintf(get_line(0, 0), 470 0 stevel "Vendor-specific Options (%d total octets):", i); 471 0 stevel /* 472 0 stevel * We don't know what these things are, so just 473 0 stevel * display the option number, length, and value 474 0 stevel * (hex). 475 0 stevel */ 476 0 stevel vend = (uchar_t *)((uchar_t *)start + i); 477 0 stevel while (start < vend && *start != CD_END) { 478 0 stevel if (*start == CD_PAD) { 479 0 stevel start++; 480 0 stevel continue; 481 0 stevel } 482 0 stevel (void) sprintf(scratch, 483 0 stevel "\t(%.2d) %.2d octets", *start, 484 0 stevel *(uchar_t *)((uchar_t *)start + 1)); 485 0 stevel start++; 486 0 stevel display_ascii_hex(scratch, &start); 487 0 stevel } 488 0 stevel start = vend; /* in case CD_END found */ 489 0 stevel break; 490 0 stevel case CD_NETBIOS_NODE_TYPE: 491 0 stevel if (*start != 1) { 492 0 stevel (void) sprintf(get_line(0, 0), 493 0 stevel "Error: Bad '%s' parameter", 494 0 stevel option_types[CD_NETBIOS_NODE_TYPE]); 495 0 stevel } else { 496 0 stevel char *type; 497 0 stevel start++; 498 0 stevel switch (*start) { 499 0 stevel case 0x1: 500 0 stevel type = "Broadcast Node"; 501 0 stevel break; 502 0 stevel case 0x2: 503 0 stevel type = "Point To Point Node"; 504 0 stevel break; 505 0 stevel case 0x4: 506 0 stevel type = "Mixed Mode Node"; 507 0 stevel break; 508 0 stevel case 0x8: 509 0 stevel type = "Hybrid Node"; 510 0 stevel break; 511 0 stevel default: 512 0 stevel type = "??? Node"; 513 0 stevel break; 514 0 stevel }; 515 0 stevel (void) sprintf(get_line(0, 0), 516 0 stevel "%s = %s (%d)", 517 0 stevel option_types[CD_NETBIOS_NODE_TYPE], 518 0 stevel type, *start); 519 0 stevel start++; 520 0 stevel } 521 0 stevel break; 522 0 stevel case CD_OPTION_OVERLOAD: 523 0 stevel if (*start != 1) { 524 0 stevel (void) sprintf(get_line(0, 0), 525 0 stevel "Bad Option Overload value."); 526 0 stevel } else { 527 0 stevel start++; 528 0 stevel nooverload = *start++; 529 0 stevel } 530 0 stevel break; 531 0 stevel case CD_DHCP_TYPE: 532 0 stevel if (*start < 1 || *start > 7) { 533 0 stevel (void) sprintf(get_line(0, 0), 534 0 stevel "Bad DHCP Message Type."); 535 0 stevel } else { 536 0 stevel start++; 537 0 stevel (void) sprintf(get_line(0, 0), 538 0 stevel "Message type = %s", 539 0 stevel show_msgtype(*start)); 540 0 stevel start++; 541 0 stevel } 542 0 stevel break; 543 0 stevel case CD_REQUEST_LIST: 544 0 stevel opt_len = *start++; 545 0 stevel (void) sprintf(get_line(0, 0), 546 0 stevel "Requested Options:"); 547 0 stevel for (i = 0; i < opt_len; i++) { 548 0 stevel entry = NULL; 549 0 stevel if (*start < OPTIONS_ARRAY_SIZE) { 550 0 stevel prmpt = option_types[*start]; 551 0 stevel } else { 552 0 stevel entry = inittab_getbycode( 553 9759 Vasumathi ITAB_CAT_STANDARD|ITAB_CAT_SITE, 554 9759 Vasumathi ITAB_CONS_SNOOP, *start); 555 0 stevel if (entry == NULL) { 556 0 stevel if (*start >= DHCP_SITE_OPT && 557 0 stevel *start <= DHCP_END_SITE) { 558 0 stevel prmpt = "Site Option"; 559 0 stevel } else { 560 0 stevel prmpt = "Unrecognized " 561 9759 Vasumathi "Option"; 562 0 stevel } 563 0 stevel } else { 564 0 stevel prmpt = entry->ds_name; 565 0 stevel } 566 0 stevel } 567 0 stevel (void) sprintf(get_line(0, 0), 568 0 stevel "\t%2d (%s)", *start, prmpt); 569 0 stevel start++; 570 0 stevel free(entry); 571 0 stevel } 572 0 stevel break; 573 0 stevel default: 574 0 stevel opt_len = *start++; 575 0 stevel entry = inittab_getbycode( 576 9759 Vasumathi ITAB_CAT_STANDARD|ITAB_CAT_SITE, 577 9759 Vasumathi ITAB_CONS_SNOOP, save); 578 0 stevel if (entry == NULL) { 579 0 stevel if (save >= DHCP_SITE_OPT && 580 0 stevel save <= DHCP_END_SITE) 581 0 stevel prmpt = "Site"; 582 0 stevel else 583 0 stevel prmpt = "Unrecognized"; 584 0 stevel decoded_opt = NULL; 585 0 stevel } else { 586 0 stevel if (save < OPTIONS_ARRAY_SIZE) { 587 0 stevel prmpt = option_types[save]; 588 0 stevel } else { 589 0 stevel prmpt = entry->ds_name; 590 0 stevel } 591 0 stevel decoded_opt = inittab_decode(entry, start, 592 9759 Vasumathi opt_len, B_TRUE); 593 0 stevel } 594 0 stevel if (decoded_opt == NULL) { 595 0 stevel (void) sprintf(get_line(0, 0), 596 0 stevel "%s Option = %d, length = %d octets", 597 0 stevel prmpt, save, opt_len); 598 0 stevel start--; 599 0 stevel display_ascii_hex("\tValue =", &start); 600 0 stevel } else { 601 0 stevel (void) sprintf(get_line(0, 0), "%s = %s", prmpt, 602 9759 Vasumathi decoded_opt); 603 0 stevel start += opt_len; 604 0 stevel free(decoded_opt); 605 0 stevel } 606 0 stevel free(entry); 607 0 stevel break; 608 0 stevel }; 609 0 stevel } 610 0 stevel return (nooverload); 611 0 stevel } 612 3431 carlsonj 613 0 stevel static const char * 614 0 stevel show_msgtype(unsigned char type) 615 0 stevel { 616 0 stevel /* 617 0 stevel * note: the ordering here allows direct indexing of the table 618 0 stevel * based on the RFC2131 packet type value passed in. 619 0 stevel */ 620 0 stevel 621 0 stevel static const char *types[] = { 622 0 stevel "BOOTP", 623 0 stevel "DHCPDISCOVER", "DHCPOFFER", "DHCPREQUEST", "DHCPDECLINE", 624 0 stevel "DHCPACK", "DHCPNAK", "DHCPRELEASE", "DHCPINFORM" 625 0 stevel }; 626 0 stevel 627 9759 Vasumathi if (type >= (sizeof (types) / sizeof (*types)) || types[type] == NULL) 628 0 stevel return ("UNKNOWN"); 629 0 stevel 630 0 stevel return (types[type]); 631 0 stevel } 632 3431 carlsonj 633 0 stevel static void 634 0 stevel display_ip(int items, char *fmt, char *msg, unsigned char **opt) 635 0 stevel { 636 0 stevel struct in_addr tmp; 637 0 stevel int i; 638 0 stevel 639 0 stevel for (i = 0; i < items; i++) { 640 0 stevel memcpy((char *)&tmp, *opt, sizeof (struct in_addr)); 641 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, inet_ntoa(tmp)); 642 0 stevel *opt += 4; 643 0 stevel } 644 0 stevel } 645 3431 carlsonj 646 0 stevel static void 647 0 stevel display_ascii(char *fmt, char *msg, unsigned char **opt) 648 0 stevel { 649 0 stevel static unsigned char buf[256]; 650 410 kcpoon int len = **opt; 651 0 stevel unsigned char slen = len; 652 0 stevel 653 0 stevel if (len >= sizeof (buf)) 654 0 stevel len = sizeof (buf) - 1; 655 0 stevel (*opt)++; 656 0 stevel memcpy(buf, *opt, len); 657 0 stevel *(unsigned char *)(buf + len) = '\0'; 658 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, buf); 659 0 stevel (*opt) += slen; 660 0 stevel } 661 3431 carlsonj 662 0 stevel static void 663 0 stevel display_number(char *fmt, char *msg, unsigned char **opt) 664 0 stevel { 665 0 stevel int len = **opt; 666 0 stevel unsigned long l_buf = 0; 667 0 stevel unsigned short s_buf = 0; 668 0 stevel 669 0 stevel if (len > 4) { 670 0 stevel (*opt)++; 671 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, 0xdeadbeef); 672 0 stevel return; 673 0 stevel } 674 0 stevel switch (len) { 675 0 stevel case sizeof (uchar_t): 676 0 stevel (*opt)++; 677 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, **opt); 678 0 stevel break; 679 0 stevel case sizeof (ushort_t): 680 0 stevel (*opt)++; 681 0 stevel if (IS_P2ALIGNED(*opt, sizeof (ushort_t))) 682 0 stevel /* LINTED: improper alignment */ 683 0 stevel s_buf = *(unsigned short *)*opt; 684 0 stevel else 685 0 stevel memcpy((char *)&s_buf, *opt, len); 686 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, ntohs(s_buf)); 687 0 stevel break; 688 0 stevel case sizeof (ulong_t): 689 0 stevel (*opt)++; 690 0 stevel if (IS_P2ALIGNED(*opt, sizeof (ulong_t))) 691 0 stevel /* LINTED: improper alignment */ 692 0 stevel l_buf = *(unsigned long *)*opt; 693 0 stevel else 694 0 stevel memcpy((char *)&l_buf, *opt, len); 695 0 stevel (void) sprintf(get_line(0, 0), fmt, msg, ntohl(l_buf)); 696 0 stevel break; 697 0 stevel } 698 0 stevel (*opt) += len; 699 0 stevel } 700 3431 carlsonj 701 0 stevel static void 702 0 stevel display_ascii_hex(char *msg, unsigned char **opt) 703 0 stevel { 704 0 stevel int printable; 705 0 stevel char buffer[512]; 706 0 stevel char *line, *tmp, *ap, *fmt; 707 9759 Vasumathi int i, len = **opt; 708 0 stevel 709 0 stevel line = get_line(0, 0); 710 0 stevel 711 0 stevel (*opt)++; 712 0 stevel 713 0 stevel if (len >= 255) { 714 0 stevel (void) sprintf(line, "\t%s <TOO LONG>", msg); 715 0 stevel return; 716 0 stevel } 717 0 stevel 718 0 stevel for (printable = 1, tmp = (char *)(*opt), ap = buffer; 719 0 stevel tmp < (char *)&((*opt)[len]); tmp++) { 720 0 stevel if (isprint(*tmp)) 721 0 stevel *ap++ = *tmp; 722 0 stevel else { 723 0 stevel *ap++ = '.'; 724 0 stevel printable = 0; 725 0 stevel } 726 0 stevel } 727 0 stevel *ap = '\0'; 728 0 stevel 729 0 stevel if (!printable) { 730 0 stevel for (tmp = (char *)(*opt), ap = buffer; 731 9759 Vasumathi (tmp < (char *)&((*opt)[len])) && ((ap + 5) < &buffer[512]); 732 0 stevel tmp++) { 733 0 stevel ap += sprintf(ap, "0x%02X ", *(uchar_t *)(tmp)); 734 0 stevel } 735 9759 Vasumathi /* Truncate the trailing space */ 736 0 stevel *(--ap) = '\0'; 737 9759 Vasumathi /* More bytes to print in hex but no space in buffer */ 738 9759 Vasumathi if (tmp < (char *)&((*opt)[len])) { 739 9759 Vasumathi i = ap - buffer; 740 9759 Vasumathi buffer[i - 1] = '.'; 741 9759 Vasumathi buffer[i - 2] = '.'; 742 9759 Vasumathi buffer[i - 3] = '.'; 743 9759 Vasumathi } 744 0 stevel fmt = "%s\t%s (unprintable)"; 745 0 stevel } else { 746 0 stevel fmt = "%s\t\"%s\""; 747 0 stevel } 748 0 stevel (*opt) += len; 749 0 stevel (void) sprintf(line, fmt, msg, buffer); 750 0 stevel } 751