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