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