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 "TFTP Server Name", /* 66 */ 116 "Option BootFile Name", /* 67 */ 117 "Mobile IP Agents", /* 68 */ 118 "Simple Mail (SMTP) Servers", /* 69 */ 119 "Post Office (POP3) Servers", /* 70 */ 120 "Net News (NNTP) Servers", /* 71 */ 121 "WorldWideWeb Servers", /* 72 */ 122 "Finger Servers", /* 73 */ 123 "Internet Relay Chat (IRC) Servers", /* 74 */ 124 "StreetTalk Servers", /* 75 */ 125 "StreetTalk Directory Assist. Servers", /* 76 */ 126 "User Class Identifier", /* 77 */ 127 }; 128 129 #define OPTIONS_ARRAY_SIZE 78 130 131 int 132 interpret_dhcp(int flags, struct dhcp *dp, int len) 133 { 134 if (flags & F_SUM) { 135 if ((memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) == 0) && 136 (len >= BASE_PKT_SIZE + 3) && 137 dp->options[0] == CD_DHCP_TYPE) { 138 (void) sprintf(get_sum_line(), 139 "DHCP/BOOTP %s", show_msgtype(dp->options[2])); 140 } else { 141 switch (ntohs(dp->op)) { 142 case BOOTREQUEST: 143 (void) sprintf(get_sum_line(), 144 "DHCP/BOOTP BOOTREQUEST"); 145 break; 146 case BOOTREPLY: 147 (void) sprintf(get_sum_line(), 148 "DHCP/BOOTP BOOTREPLY"); 149 break; 150 } 151 } 152 } 153 if (flags & F_DTAIL) { 154 show_header("DHCP: ", "Dynamic Host Configuration Protocol", 155 len); 156 show_space(); 157 (void) sprintf(get_line((char *)(uintptr_t)dp->htype - 158 dlc_header, 1), 159 "Hardware address type (htype) = %d (%s)", dp->htype, 160 arp_htype(dp->htype)); 161 (void) sprintf(get_line((char *)(uintptr_t)dp->hlen - 162 dlc_header, 1), 163 "Hardware address length (hlen) = %d octets", dp->hlen); 164 (void) sprintf(get_line((char *)(uintptr_t)dp->hops - 165 dlc_header, 1), 166 "Relay agent hops = %d", dp->hops); 167 (void) sprintf(get_line((char *)(uintptr_t)dp->xid - 168 dlc_header, 4), 169 "Transaction ID = 0x%x", ntohl(dp->xid)); 170 (void) sprintf(get_line((char *)(uintptr_t)dp->secs - 171 dlc_header, 2), 172 "Time since boot = %d seconds", ntohs(dp->secs)); 173 (void) sprintf(get_line((char *)(uintptr_t)dp->flags - 174 dlc_header, 2), 175 "Flags = 0x%.4x", ntohs(dp->flags)); 176 (void) sprintf(get_line((char *)&dp->ciaddr - dlc_header, 4), 177 "Client address (ciaddr) = %s", inet_ntoa(dp->ciaddr)); 178 (void) sprintf(get_line((char *)&dp->yiaddr - dlc_header, 4), 179 "Your client address (yiaddr) = %s", 180 inet_ntoa(dp->yiaddr)); 181 (void) sprintf(get_line((char *)&dp->siaddr - dlc_header, 4), 182 "Next server address (siaddr) = %s", 183 inet_ntoa(dp->siaddr)); 184 (void) sprintf(get_line((char *)&dp->giaddr - dlc_header, 4), 185 "Relay agent address (giaddr) = %s", 186 inet_ntoa(dp->giaddr)); 187 if (dp->htype == 1) { 188 (void) sprintf(get_line((char *)dp->chaddr - 189 dlc_header, dp->hlen), 190 "Client hardware address (chaddr) = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", 191 dp->chaddr[0], 192 dp->chaddr[1], 193 dp->chaddr[2], 194 dp->chaddr[3], 195 dp->chaddr[4], 196 dp->chaddr[5]); 197 } 198 /* 199 * Check cookie, process options 200 */ 201 if (memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) != 0) { 202 (void) sprintf(get_line(0, 0), 203 "Unrecognized cookie: 0x%.2X%.2X%.2X%.2X\n", 204 dp->cookie[0], 205 dp->cookie[1], 206 dp->cookie[2], 207 dp->cookie[3]); 208 return (0); 209 } 210 show_space(); 211 show_header("DHCP: ", "(Options) field options", len); 212 show_space(); 213 switch (show_options(dp->options, (len - BASE_PKT_SIZE))) { 214 case 0: 215 /* No option overloading */ 216 if (*(unsigned char *)(dp->sname) != '\0') { 217 (void) sprintf(get_line(0, 0), 218 "Server Name = %s", dp->sname); 219 } 220 if (*(unsigned char *)(dp->file) != '\0') { 221 (void) sprintf(get_line(0, 0), 222 "Boot File Name = %s", dp->file); 223 } 224 break; 225 case 1: 226 /* file field used */ 227 if (*(unsigned char *)(dp->sname) != '\0') { 228 (void) sprintf(get_line(0, 0), 229 "Server Name = %s", dp->sname); 230 } 231 show_space(); 232 show_header("DHCP: ", "(File) field options", len); 233 show_space(); 234 (void) show_options(dp->file, 128); 235 break; 236 case 2: 237 /* sname field used for options */ 238 if (*(unsigned char *)(dp->file) != '\0') { 239 (void) sprintf(get_line(0, 0), 240 "Boot File Name = %s", dp->file); 241 } 242 show_space(); 243 show_header("DHCP: ", "(Sname) field options", len); 244 show_space(); 245 (void) show_options(dp->sname, 64); 246 break; 247 case 3: 248 show_space(); 249 show_header("DHCP: ", "(File) field options", len); 250 show_space(); 251 (void) show_options(dp->file, 128); 252 show_space(); 253 show_header("DHCP: ", "(Sname) field options", len); 254 show_space(); 255 (void) show_options(dp->sname, 64); 256 break; 257 }; 258 } 259 return (len); 260 } 261 262 static int 263 show_options(unsigned char *cp, int len) 264 { 265 char *prmpt; 266 unsigned char *end, *vend; 267 unsigned char *start, save; 268 int items, i; 269 int nooverload = 0; 270 ushort_t s_buf; 271 struct in_addr tmp; 272 char scratch[128]; 273 dhcp_symbol_t *entry; 274 char *decoded_opt; 275 int opt_len; 276 277 start = cp; 278 end = (unsigned char *)cp + len; 279 280 while (start < end) { 281 if (*start == CD_PAD) { 282 start++; 283 continue; 284 } 285 if (*start == CD_END) 286 break; /* done */ 287 288 save = *start++; 289 switch (save) { 290 /* Network order IP address(es) */ 291 case CD_SUBNETMASK: 292 case CD_ROUTER_SOLICIT_SERV: 293 case CD_BROADCASTADDR: 294 case CD_REQUESTED_IP_ADDR: 295 case CD_SERVER_ID: 296 /* Single IP address */ 297 if (*start != 4) { 298 (void) sprintf(get_line(0, 0), 299 "Error: Bad %s", option_types[save]); 300 } else { 301 start++; 302 display_ip(1, "%s = %s", option_types[save], 303 &start); 304 } 305 break; 306 case CD_ROUTER: 307 case CD_TIMESERV: 308 case CD_IEN116_NAME_SERV: 309 case CD_DNSSERV: 310 case CD_LOG_SERV: 311 case CD_COOKIE_SERV: 312 case CD_LPR_SERV: 313 case CD_IMPRESS_SERV: 314 case CD_RESOURCE_SERV: 315 case CD_SWAP_SERV: 316 case CD_NIS_SERV: 317 case CD_NTP_SERV: 318 case CD_NETBIOS_NAME_SERV: 319 case CD_NETBIOS_DIST_SERV: 320 case CD_XWIN_FONT_SERV: 321 case CD_XWIN_DISP_SERV: 322 case CD_MOBILE_IP_AGENT: 323 case CD_SMTP_SERVS: 324 case CD_POP3_SERVS: 325 case CD_NNTP_SERVS: 326 case CD_WWW_SERVS: 327 case CD_FINGER_SERVS: 328 case CD_IRC_SERVS: 329 case CD_STREETTALK_SERVS: 330 case CD_STREETTALK_DA_SERVS: 331 /* Multiple IP addresses */ 332 if ((*start % 4) != 0) { 333 (void) sprintf(get_line(0, 0), 334 "Error: Bad %s address", 335 option_types[save]); 336 } else { 337 items = *start++ / 4; 338 display_ip(items, "%s at = %s", 339 option_types[save], &start); 340 } 341 break; 342 case CD_TFTP_SERV_NAME: 343 case CD_HOSTNAME: 344 case CD_DUMP_FILE: 345 case CD_DNSDOMAIN: 346 case CD_ROOT_PATH: 347 case CD_NIS_DOMAIN: 348 case CD_NETBIOS_SCOPE: 349 case CD_MESSAGE: 350 case CD_OPT_BOOTFILE_NAME: 351 case CD_USER_CLASS_ID: 352 /* Ascii strings */ 353 display_ascii("%s = %s", option_types[save], &start); 354 break; 355 case CD_TIMEOFFSET: 356 case CD_IPTTL: 357 case CD_PATH_MTU_TIMEOUT: 358 case CD_ARP_TIMEOUT: 359 case CD_TCP_TTL: 360 case CD_TCP_KALIVE_INTVL: 361 case CD_T1_TIME: 362 case CD_T2_TIME: 363 case CD_LEASE_TIME: 364 /* Number: seconds */ 365 display_number("%s = %d seconds", option_types[save], 366 &start); 367 break; 368 case CD_IP_FORWARDING_ON: 369 case CD_NON_LCL_ROUTE_ON: 370 case CD_ALL_SUBNETS_LCL_ON: 371 case CD_MASK_DISCVRY_ON: 372 case CD_MASK_SUPPLIER_ON: 373 case CD_ROUTER_DISCVRY_ON: 374 case CD_TRAILER_ENCAPS_ON: 375 case CD_ETHERNET_ENCAPS_ON: 376 case CD_TCP_KALIVE_GRBG_ON: 377 /* Number: hex flag */ 378 display_number("%s flag = 0x%x", option_types[save], 379 &start); 380 break; 381 case CD_MAXIPSIZE: 382 case CD_MTU: 383 case CD_MAX_DHCP_SIZE: 384 /* Number: bytes */ 385 display_number("%s = %d bytes", option_types[save], 386 &start); 387 break; 388 case CD_CLASS_ID: 389 case CD_CLIENT_ID: 390 case CD_NW_IP_DOMAIN: 391 case CD_NW_IP_OPTIONS: 392 /* Hex ascii strings */ 393 display_ascii_hex(option_types[save], &start); 394 break; 395 case CD_BOOT_SIZE: 396 display_number("%s = %d 512 byte blocks", 397 "Boot file size", &start); 398 break; 399 case CD_POLICY_FILTER: 400 if ((*start % 8) != 0) { 401 (void) sprintf(get_line(0, 0), 402 "Error: Bad Policy Filter option"); 403 } else { 404 items = *start++ / 8; 405 for (i = 0; i < items; i++) { 406 display_ip(1, 407 "%s = %s", 408 "Policy Destination", 409 &start); 410 display_ip(1, "%s = %s", "Mask", 411 &start); 412 } 413 } 414 break; 415 case CD_PATH_MTU_TABLE_SZ: 416 if (*start % 2 != 0) { 417 (void) sprintf(get_line(0, 0), 418 "Error: Bad Path MTU Table"); 419 } else { 420 (void) sprintf(get_line(0, 0), 421 "\tPath MTU Plateau Table:"); 422 (void) sprintf(get_line(0, 0), 423 "\t======================="); 424 items = *start / sizeof (ushort_t); 425 ++start; 426 for (i = 0; i < items; i++) { 427 if (IS_P2ALIGNED(start, 428 sizeof (ushort_t))) { 429 /* LINTED: improper alignment */ 430 s_buf = *(ushort_t *)start; 431 } else { 432 memcpy((char *)&s_buf, 433 start, sizeof (short)); 434 } 435 (void) sprintf(get_line(0, 0), 436 "\t\tEntry %d:\t\t%d", i, 437 ntohs(s_buf)); 438 start += sizeof (ushort_t); 439 } 440 } 441 break; 442 case CD_STATIC_ROUTE: 443 if ((*start % 8) != 0) { 444 (void) sprintf(get_line(0, 0), 445 "Error: Bad Static Route option: %d", 446 *start); 447 } else { 448 items = *start++ / 8; 449 for (i = 0; i < items; i++) { 450 memcpy((char *)&tmp, start, 451 sizeof (struct in_addr)); 452 (void) strcpy(scratch, inet_ntoa(tmp)); 453 start += sizeof (ulong_t); 454 memcpy((char *)&tmp, start, 455 sizeof (struct in_addr)); 456 (void) sprintf(get_line(0, 0), 457 "Static route from %s to %s", 458 scratch, inet_ntoa(tmp)); 459 start += sizeof (ulong_t); 460 } 461 } 462 break; 463 case CD_VENDOR_SPEC: 464 i = *start++; 465 (void) sprintf(get_line(0, 0), 466 "Vendor-specific Options (%d total octets):", i); 467 /* 468 * We don't know what these things are, so just 469 * display the option number, length, and value 470 * (hex). 471 */ 472 vend = (uchar_t *)((uchar_t *)start + i); 473 while (start < vend && *start != CD_END) { 474 if (*start == CD_PAD) { 475 start++; 476 continue; 477 } 478 (void) sprintf(scratch, 479 "\t(%.2d) %.2d octets", *start, 480 *(uchar_t *)((uchar_t *)start + 1)); 481 start++; 482 display_ascii_hex(scratch, &start); 483 } 484 start = vend; /* in case CD_END found */ 485 break; 486 case CD_NETBIOS_NODE_TYPE: 487 if (*start != 1) { 488 (void) sprintf(get_line(0, 0), 489 "Error: Bad '%s' parameter", 490 option_types[CD_NETBIOS_NODE_TYPE]); 491 } else { 492 char *type; 493 start++; 494 switch (*start) { 495 case 0x1: 496 type = "Broadcast Node"; 497 break; 498 case 0x2: 499 type = "Point To Point Node"; 500 break; 501 case 0x4: 502 type = "Mixed Mode Node"; 503 break; 504 case 0x8: 505 type = "Hybrid Node"; 506 break; 507 default: 508 type = "??? Node"; 509 break; 510 }; 511 (void) sprintf(get_line(0, 0), 512 "%s = %s (%d)", 513 option_types[CD_NETBIOS_NODE_TYPE], 514 type, *start); 515 start++; 516 } 517 break; 518 case CD_OPTION_OVERLOAD: 519 if (*start != 1) { 520 (void) sprintf(get_line(0, 0), 521 "Bad Option Overload value."); 522 } else { 523 start++; 524 nooverload = *start++; 525 } 526 break; 527 case CD_DHCP_TYPE: 528 if (*start < 1 || *start > 7) { 529 (void) sprintf(get_line(0, 0), 530 "Bad DHCP Message Type."); 531 } else { 532 start++; 533 (void) sprintf(get_line(0, 0), 534 "Message type = %s", 535 show_msgtype(*start)); 536 start++; 537 } 538 break; 539 case CD_REQUEST_LIST: 540 opt_len = *start++; 541 (void) sprintf(get_line(0, 0), 542 "Requested Options:"); 543 for (i = 0; i < opt_len; i++) { 544 entry = NULL; 545 if (*start < OPTIONS_ARRAY_SIZE) { 546 prmpt = option_types[*start]; 547 } else { 548 entry = inittab_getbycode( 549 ITAB_CAT_STANDARD|ITAB_CAT_SITE, 550 ITAB_CONS_SNOOP, *start); 551 if (entry == NULL) { 552 if (*start >= DHCP_SITE_OPT && 553 *start <= DHCP_END_SITE) { 554 prmpt = "Site Option"; 555 } else { 556 prmpt = "Unrecognized " 557 "Option"; 558 } 559 } else { 560 prmpt = entry->ds_name; 561 } 562 } 563 (void) sprintf(get_line(0, 0), 564 "\t%2d (%s)", *start, prmpt); 565 start++; 566 free(entry); 567 } 568 break; 569 default: 570 opt_len = *start++; 571 entry = inittab_getbycode( 572 ITAB_CAT_STANDARD|ITAB_CAT_SITE, 573 ITAB_CONS_SNOOP, save); 574 if (entry == NULL) { 575 if (save >= DHCP_SITE_OPT && 576 save <= DHCP_END_SITE) 577 prmpt = "Site"; 578 else 579 prmpt = "Unrecognized"; 580 decoded_opt = NULL; 581 } else { 582 if (save < OPTIONS_ARRAY_SIZE) { 583 prmpt = option_types[save]; 584 } else { 585 prmpt = entry->ds_name; 586 } 587 decoded_opt = inittab_decode(entry, start, 588 opt_len, B_TRUE); 589 } 590 if (decoded_opt == NULL) { 591 (void) sprintf(get_line(0, 0), 592 "%s Option = %d, length = %d octets", 593 prmpt, save, opt_len); 594 start--; 595 display_ascii_hex("\tValue =", &start); 596 } else { 597 (void) sprintf(get_line(0, 0), "%s = %s", prmpt, 598 decoded_opt); 599 start += opt_len; 600 free(decoded_opt); 601 } 602 free(entry); 603 break; 604 }; 605 } 606 return (nooverload); 607 } 608 609 static const char * 610 show_msgtype(unsigned char type) 611 { 612 /* 613 * note: the ordering here allows direct indexing of the table 614 * based on the RFC2131 packet type value passed in. 615 */ 616 617 static const char *types[] = { 618 "BOOTP", 619 "DHCPDISCOVER", "DHCPOFFER", "DHCPREQUEST", "DHCPDECLINE", 620 "DHCPACK", "DHCPNAK", "DHCPRELEASE", "DHCPINFORM" 621 }; 622 623 if (type >= (sizeof (types) / sizeof (*types)) || types[type] == NULL) 624 return ("UNKNOWN"); 625 626 return (types[type]); 627 } 628 629 static void 630 display_ip(int items, char *fmt, char *msg, unsigned char **opt) 631 { 632 struct in_addr tmp; 633 int i; 634 635 for (i = 0; i < items; i++) { 636 memcpy((char *)&tmp, *opt, sizeof (struct in_addr)); 637 (void) sprintf(get_line(0, 0), fmt, msg, inet_ntoa(tmp)); 638 *opt += 4; 639 } 640 } 641 642 static void 643 display_ascii(char *fmt, char *msg, unsigned char **opt) 644 { 645 static unsigned char buf[256]; 646 int len = **opt; 647 unsigned char slen = len; 648 649 if (len >= sizeof (buf)) 650 len = sizeof (buf) - 1; 651 (*opt)++; 652 memcpy(buf, *opt, len); 653 *(unsigned char *)(buf + len) = '\0'; 654 (void) sprintf(get_line(0, 0), fmt, msg, buf); 655 (*opt) += slen; 656 } 657 658 static void 659 display_number(char *fmt, char *msg, unsigned char **opt) 660 { 661 int len = **opt; 662 unsigned long l_buf = 0; 663 unsigned short s_buf = 0; 664 665 if (len > 4) { 666 (*opt)++; 667 (void) sprintf(get_line(0, 0), fmt, msg, 0xdeadbeef); 668 return; 669 } 670 switch (len) { 671 case sizeof (uchar_t): 672 (*opt)++; 673 (void) sprintf(get_line(0, 0), fmt, msg, **opt); 674 break; 675 case sizeof (ushort_t): 676 (*opt)++; 677 if (IS_P2ALIGNED(*opt, sizeof (ushort_t))) 678 /* LINTED: improper alignment */ 679 s_buf = *(unsigned short *)*opt; 680 else 681 memcpy((char *)&s_buf, *opt, len); 682 (void) sprintf(get_line(0, 0), fmt, msg, ntohs(s_buf)); 683 break; 684 case sizeof (ulong_t): 685 (*opt)++; 686 if (IS_P2ALIGNED(*opt, sizeof (ulong_t))) 687 /* LINTED: improper alignment */ 688 l_buf = *(unsigned long *)*opt; 689 else 690 memcpy((char *)&l_buf, *opt, len); 691 (void) sprintf(get_line(0, 0), fmt, msg, ntohl(l_buf)); 692 break; 693 } 694 (*opt) += len; 695 } 696 697 static void 698 display_ascii_hex(char *msg, unsigned char **opt) 699 { 700 int printable; 701 char buffer[512]; 702 char *line, *tmp, *ap, *fmt; 703 int i, len = **opt; 704 705 line = get_line(0, 0); 706 707 (*opt)++; 708 709 if (len >= 255) { 710 (void) sprintf(line, "\t%s <TOO LONG>", msg); 711 return; 712 } 713 714 for (printable = 1, tmp = (char *)(*opt), ap = buffer; 715 tmp < (char *)&((*opt)[len]); tmp++) { 716 if (isprint(*tmp)) 717 *ap++ = *tmp; 718 else { 719 *ap++ = '.'; 720 printable = 0; 721 } 722 } 723 *ap = '\0'; 724 725 if (!printable) { 726 for (tmp = (char *)(*opt), ap = buffer; 727 (tmp < (char *)&((*opt)[len])) && ((ap + 5) < &buffer[512]); 728 tmp++) { 729 ap += sprintf(ap, "0x%02X ", *(uchar_t *)(tmp)); 730 } 731 /* Truncate the trailing space */ 732 *(--ap) = '\0'; 733 /* More bytes to print in hex but no space in buffer */ 734 if (tmp < (char *)&((*opt)[len])) { 735 i = ap - buffer; 736 buffer[i - 1] = '.'; 737 buffer[i - 2] = '.'; 738 buffer[i - 3] = '.'; 739 } 740 fmt = "%s\t%s (unprintable)"; 741 } else { 742 fmt = "%s\t\"%s\""; 743 } 744 (*opt) += len; 745 (void) sprintf(line, fmt, msg, buffer); 746 } 747