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