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