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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1991-2003 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 extern char *dlc_header; 45 static char *show_htype(int); 46 static const char *show_msgtype(unsigned char); 47 static int show_options(unsigned char *, int); 48 static void display_ip(int, char *, char *, unsigned char **); 49 static void display_ascii(char *, char *, unsigned char **); 50 static void display_number(char *, char *, unsigned char **); 51 static void display_ascii_hex(char *, unsigned char **); 52 static unsigned char bootmagic[] = BOOTMAGIC; /* rfc 1048 */ 53 54 static char *option_types[] = { 55 "", /* 0 */ 56 "Subnet Mask", /* 1 */ 57 "UTC Time Offset", /* 2 */ 58 "Router", /* 3 */ 59 "RFC868 Time Servers", /* 4 */ 60 "IEN 116 Name Servers", /* 5 */ 61 "DNS Servers", /* 6 */ 62 "UDP LOG Servers", /* 7 */ 63 "RFC 865 Cookie Servers", /* 8 */ 64 "RFC 1179 Line Printer Servers (LPR)", /* 9 */ 65 "Impress Servers", /* 10 */ 66 "RFC 887 Resource Location Servers", /* 11 */ 67 "Client Hostname", /* 12 */ 68 "Boot File size in 512 byte Blocks", /* 13 */ 69 "Merit Dump File", /* 14 */ 70 "DNS Domain Name", /* 15 */ 71 "SWAP Server", /* 16 */ 72 "Client Root Path", /* 17 */ 73 "BOOTP options extensions path", /* 18 */ 74 "IP Forwarding Flag", /* 19 */ 75 "NonLocal Source Routing Flag", /* 20 */ 76 "Policy Filters for NonLocal Routing", /* 21 */ 77 "Maximum Datagram Reassembly Size", /* 22 */ 78 "Default IP Time To Live", /* 23 */ 79 "Path MTU Aging Timeout", /* 24 */ 80 "Path MTU Size Plateau Table", /* 25 */ 81 "Interface MTU Size", /* 26 */ 82 "All Subnets are Local Flag", /* 27 */ 83 "Broadcast Address", /* 28 */ 84 "Perform Mask Discovery Flag", /* 29 */ 85 "Mask Supplier Flag", /* 30 */ 86 "Perform Router Discovery Flag", /* 31 */ 87 "Router Solicitation Address", /* 32 */ 88 "Static Routes", /* 33 */ 89 "Trailer Encapsulation Flag", /* 34 */ 90 "ARP Cache Timeout Seconds", /* 35 */ 91 "Ethernet Encapsulation Flag", /* 36 */ 92 "TCP Default Time To Live", /* 37 */ 93 "TCP Keepalive Interval Seconds", /* 38 */ 94 "TCP Keepalive Garbage Flag", /* 39 */ 95 "NIS Domainname", /* 40 */ 96 "NIS Servers", /* 41 */ 97 "Network Time Protocol Servers", /* 42 */ 98 "Vendor Specific Options", /* 43 */ 99 "NetBIOS RFC 1001/1002 Name Servers", /* 44 */ 100 "NetBIOS Datagram Dist. Servers", /* 45 */ 101 "NetBIOS Node Type", /* 46 */ 102 "NetBIOS Scope", /* 47 */ 103 "X Window Font Servers", /* 48 */ 104 "X Window Display Manager Servers", /* 49 */ 105 "Requested IP Address", /* 50 */ 106 "IP Address Lease Time", /* 51 */ 107 "Option Field Overload Flag", /* 52 */ 108 "DHCP Message Type", /* 53 */ 109 "DHCP Server Identifier", /* 54 */ 110 "Option Request List", /* 55 */ 111 "Error Message", /* 56 */ 112 "Maximum DHCP Message Size", /* 57 */ 113 "Renewal (T1) Time Value", /* 58 */ 114 "Rebinding (T2) Time Value", /* 59 */ 115 "Client Class Identifier =", /* 60 */ 116 "Client Identifier =", /* 61 */ 117 "Netware IP Domain =", /* 62 */ 118 "Netware IP Options =", /* 63 */ 119 "NISPLUS Domainname", /* 64 */ 120 "NISPLUS Servers", /* 65 */ 121 "TFTP Server Name", /* 66 */ 122 "Option BootFile Name", /* 67 */ 123 "Mobile IP Agents", /* 68 */ 124 "Simple Mail (SMTP) Servers", /* 69 */ 125 "Post Office (POP3) Servers", /* 70 */ 126 "Net News (NNTP) Servers", /* 71 */ 127 "WorldWideWeb Servers", /* 72 */ 128 "Finger Servers", /* 73 */ 129 "Internet Relay Chat (IRC) Servers", /* 74 */ 130 "StreetTalk Servers", /* 75 */ 131 "StreetTalk Directory Assist. Servers", /* 76 */ 132 "User Class Identifier", /* 77 */ 133 }; 134 135 #define OPTIONS_ARRAY_SIZE 78 136 137 int 138 interpret_dhcp(int flags, PKT *dp, int len) 139 { 140 if (flags & F_SUM) { 141 if ((memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) == 0) && 142 (len >= BASE_PKT_SIZE + 3) && 143 dp->options[0] == CD_DHCP_TYPE) { 144 (void) sprintf(get_sum_line(), 145 "DHCP/BOOTP %s", show_msgtype(dp->options[2])); 146 } else { 147 switch (ntohs(dp->op)) { 148 case BOOTREQUEST: 149 (void) sprintf(get_sum_line(), 150 "DHCP/BOOTP BOOTREQUEST"); 151 break; 152 case BOOTREPLY: 153 (void) sprintf(get_sum_line(), 154 "DHCP/BOOTP BOOTREPLY"); 155 break; 156 } 157 } 158 } 159 if (flags & F_DTAIL) { 160 show_header("DHCP: ", "Dynamic Host Configuration Protocol", 161 len); 162 show_space(); 163 (void) sprintf(get_line((char *)dp->htype - dlc_header, 1), 164 "Hardware address type (htype) = %d (%s)", dp->htype, 165 show_htype(dp->htype)); 166 (void) sprintf(get_line((char *)dp->hlen - dlc_header, 1), 167 "Hardware address length (hlen) = %d octets", dp->hlen); 168 (void) sprintf(get_line((char *)dp->hops - dlc_header, 1), 169 "Relay agent hops = %d", dp->hops); 170 (void) sprintf(get_line((char *)dp->xid - dlc_header, 4), 171 "Transaction ID = 0x%x", ntohl(dp->xid)); 172 (void) sprintf(get_line((char *)dp->secs - dlc_header, 2), 173 "Time since boot = %d seconds", ntohs(dp->secs)); 174 (void) sprintf(get_line((char *)dp->flags - 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 static int 262 show_options(unsigned char *cp, int len) 263 { 264 char *prmpt; 265 unsigned char *end, *vend; 266 unsigned char *start, save; 267 int items, i; 268 int nooverload = 0; 269 ushort_t s_buf; 270 struct in_addr tmp; 271 char scratch[128]; 272 dhcp_symbol_t *entry; 273 char *decoded_opt; 274 int opt_len; 275 276 start = cp; 277 end = (unsigned char *)cp + len; 278 279 while (start < end) { 280 if (*start == CD_PAD) { 281 start++; 282 continue; 283 } 284 if (*start == CD_END) 285 break; /* done */ 286 287 save = *start++; 288 switch (save) { 289 /* Network order IP address(es) */ 290 case CD_SUBNETMASK: 291 case CD_ROUTER_SOLICIT_SERV: 292 case CD_BROADCASTADDR: 293 case CD_REQUESTED_IP_ADDR: 294 case CD_SERVER_ID: 295 /* Single IP address */ 296 if (*start != 4) { 297 (void) sprintf(get_line(0, 0), 298 "Error: Bad %s", option_types[save]); 299 } else { 300 start++; 301 display_ip(1, "%s = %s", option_types[save], 302 &start); 303 } 304 break; 305 case CD_ROUTER: 306 case CD_TIMESERV: 307 case CD_IEN116_NAME_SERV: 308 case CD_DNSSERV: 309 case CD_LOG_SERV: 310 case CD_COOKIE_SERV: 311 case CD_LPR_SERV: 312 case CD_IMPRESS_SERV: 313 case CD_RESOURCE_SERV: 314 case CD_SWAP_SERV: 315 case CD_NIS_SERV: 316 case CD_NTP_SERV: 317 case CD_NETBIOS_NAME_SERV: 318 case CD_NETBIOS_DIST_SERV: 319 case CD_XWIN_FONT_SERV: 320 case CD_XWIN_DISP_SERV: 321 case CD_NISPLUS_SERVS: 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 display_ip((*start++ / 4), "%s at = %s", 338 option_types[save], &start); 339 } 340 break; 341 case CD_TFTP_SERV_NAME: 342 case CD_HOSTNAME: 343 case CD_DUMP_FILE: 344 case CD_DNSDOMAIN: 345 case CD_ROOT_PATH: 346 case CD_NIS_DOMAIN: 347 case CD_NETBIOS_SCOPE: 348 case CD_MESSAGE: 349 case CD_NISPLUS_DMAIN: 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 static char * 609 show_htype(int t) 610 { 611 switch (t) { 612 case 1: 613 return ("Ethernet (10Mb)"); 614 case 2: 615 return ("Experimental Ethernet (3MB)"); 616 case 3: 617 return ("Amateur Radio AX.25"); 618 case 4: 619 return ("Proteon ProNET Token Ring"); 620 case 5: 621 return ("Chaos"); 622 case 6: 623 return ("IEEE 802"); 624 case 7: 625 return ("ARCNET"); 626 case 8: 627 return ("Hyperchannel"); 628 case 9: 629 return ("Lanstar"); 630 case 10: 631 return ("Autonet"); 632 case 11: 633 return ("LocalTalk"); 634 case 12: 635 return ("LocalNet"); 636 case 13: 637 return ("Ultra Link"); 638 case 14: 639 return ("SMDS"); 640 case 15: 641 return ("Frame Relay"); 642 case 16: 643 return ("ATM"); 644 case ARPHRD_IB: 645 return ("IPIB"); 646 }; 647 return ("UNKNOWN"); 648 } 649 static const char * 650 show_msgtype(unsigned char type) 651 { 652 /* 653 * note: the ordering here allows direct indexing of the table 654 * based on the RFC2131 packet type value passed in. 655 */ 656 657 static const char *types[] = { 658 "BOOTP", 659 "DHCPDISCOVER", "DHCPOFFER", "DHCPREQUEST", "DHCPDECLINE", 660 "DHCPACK", "DHCPNAK", "DHCPRELEASE", "DHCPINFORM" 661 }; 662 663 if (type > (sizeof (types) / sizeof (*types)) || types[type] == NULL) 664 return ("UNKNOWN"); 665 666 return (types[type]); 667 } 668 static void 669 display_ip(int items, char *fmt, char *msg, unsigned char **opt) 670 { 671 struct in_addr tmp; 672 int i; 673 674 for (i = 0; i < items; i++) { 675 memcpy((char *)&tmp, *opt, sizeof (struct in_addr)); 676 (void) sprintf(get_line(0, 0), fmt, msg, inet_ntoa(tmp)); 677 *opt += 4; 678 } 679 } 680 static void 681 display_ascii(char *fmt, char *msg, unsigned char **opt) 682 { 683 static unsigned char buf[256]; 684 unsigned char len = **opt; 685 unsigned char slen = len; 686 687 if (len >= sizeof (buf)) 688 len = sizeof (buf) - 1; 689 (*opt)++; 690 memcpy(buf, *opt, len); 691 *(unsigned char *)(buf + len) = '\0'; 692 (void) sprintf(get_line(0, 0), fmt, msg, buf); 693 (*opt) += slen; 694 } 695 static void 696 display_number(char *fmt, char *msg, unsigned char **opt) 697 { 698 int len = **opt; 699 unsigned long l_buf = 0; 700 unsigned short s_buf = 0; 701 702 if (len > 4) { 703 (*opt)++; 704 (void) sprintf(get_line(0, 0), fmt, msg, 0xdeadbeef); 705 return; 706 } 707 switch (len) { 708 case sizeof (uchar_t): 709 (*opt)++; 710 (void) sprintf(get_line(0, 0), fmt, msg, **opt); 711 break; 712 case sizeof (ushort_t): 713 (*opt)++; 714 if (IS_P2ALIGNED(*opt, sizeof (ushort_t))) 715 /* LINTED: improper alignment */ 716 s_buf = *(unsigned short *)*opt; 717 else 718 memcpy((char *)&s_buf, *opt, len); 719 (void) sprintf(get_line(0, 0), fmt, msg, ntohs(s_buf)); 720 break; 721 case sizeof (ulong_t): 722 (*opt)++; 723 if (IS_P2ALIGNED(*opt, sizeof (ulong_t))) 724 /* LINTED: improper alignment */ 725 l_buf = *(unsigned long *)*opt; 726 else 727 memcpy((char *)&l_buf, *opt, len); 728 (void) sprintf(get_line(0, 0), fmt, msg, ntohl(l_buf)); 729 break; 730 } 731 (*opt) += len; 732 } 733 static void 734 display_ascii_hex(char *msg, unsigned char **opt) 735 { 736 int printable; 737 char buffer[512]; 738 char *line, *tmp, *ap, *fmt; 739 int i, j, len = **opt; 740 741 line = get_line(0, 0); 742 743 (*opt)++; 744 745 if (len >= 255) { 746 (void) sprintf(line, "\t%s <TOO LONG>", msg); 747 return; 748 } 749 750 for (printable = 1, tmp = (char *)(*opt), ap = buffer; 751 tmp < (char *)&((*opt)[len]); tmp++) { 752 if (isprint(*tmp)) 753 *ap++ = *tmp; 754 else { 755 *ap++ = '.'; 756 printable = 0; 757 } 758 } 759 *ap = '\0'; 760 761 if (!printable) { 762 for (tmp = (char *)(*opt), ap = buffer; 763 (tmp < (char *)&((*opt)[len])) && (ap < &buffer[512]); 764 tmp++) { 765 ap += sprintf(ap, "0x%02X ", *(uchar_t *)(tmp)); 766 } 767 *(--ap) = '\0'; 768 i = ap - buffer; 769 fmt = "%s\t%s (unprintable)"; 770 } else { 771 i = strlen(buffer); 772 fmt = "%s\t\"%s\""; 773 } 774 (*opt) += len; 775 j = strlen(msg) + (MAXLINE / 2) - 30; 776 if (i > j) { 777 buffer[j - 1] = '.'; 778 buffer[j - 2] = '.'; 779 buffer[j - 3] = '.'; 780 buffer[j] = '\0'; 781 } 782 (void) sprintf(line, fmt, msg, buffer); 783 } 784