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