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 <stdio.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <ctype.h>
32*0Sstevel@tonic-gate #include <string.h>
33*0Sstevel@tonic-gate #include <fcntl.h>
34*0Sstevel@tonic-gate #include <string.h>
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <time.h>
37*0Sstevel@tonic-gate #include <sys/time.h>
38*0Sstevel@tonic-gate #include <sys/bufmod.h>
39*0Sstevel@tonic-gate #include <setjmp.h>
40*0Sstevel@tonic-gate #include <varargs.h>
41*0Sstevel@tonic-gate #include <sys/socket.h>
42*0Sstevel@tonic-gate #include <sys/sockio.h>
43*0Sstevel@tonic-gate #include <net/if.h>
44*0Sstevel@tonic-gate #include <netinet/in_systm.h>
45*0Sstevel@tonic-gate #include <netinet/in.h>
46*0Sstevel@tonic-gate #include <netinet/ip.h>
47*0Sstevel@tonic-gate #include <netinet/if_ether.h>
48*0Sstevel@tonic-gate #include <rpc/types.h>
49*0Sstevel@tonic-gate #include <rpc/xdr.h>
50*0Sstevel@tonic-gate #include <sys/dlpi.h>
51*0Sstevel@tonic-gate #include <inttypes.h>
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #include "snoop.h"
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate char *dlc_header;
56*0Sstevel@tonic-gate char *src_name, *dst_name;
57*0Sstevel@tonic-gate int pi_frame;
58*0Sstevel@tonic-gate int pi_time_hour;
59*0Sstevel@tonic-gate int pi_time_min;
60*0Sstevel@tonic-gate int pi_time_sec;
61*0Sstevel@tonic-gate int pi_time_usec;
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate #ifndef MIN
64*0Sstevel@tonic-gate #define	MIN(a, b) ((a) < (b) ? (a) : (b))
65*0Sstevel@tonic-gate #endif
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static void hexdump(char *, int);
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate /*
70*0Sstevel@tonic-gate  * This routine invokes the packet interpreters
71*0Sstevel@tonic-gate  * on a packet.  There's some messing around
72*0Sstevel@tonic-gate  * setting up a few packet-externals before
73*0Sstevel@tonic-gate  * starting with the ethernet interpreter.
74*0Sstevel@tonic-gate  * Yes, we assume here that all packets will
75*0Sstevel@tonic-gate  * be ethernet packets.
76*0Sstevel@tonic-gate  */
77*0Sstevel@tonic-gate void
78*0Sstevel@tonic-gate process_pkt(struct sb_hdr *hdrp, char *pktp, int num, int flags)
79*0Sstevel@tonic-gate {
80*0Sstevel@tonic-gate 	int drops, pktlen;
81*0Sstevel@tonic-gate 	struct timeval *tvp;
82*0Sstevel@tonic-gate 	struct tm *tm;
83*0Sstevel@tonic-gate 	extern int x_offset;
84*0Sstevel@tonic-gate 	extern int x_length;
85*0Sstevel@tonic-gate 	int offset, length;
86*0Sstevel@tonic-gate 	static struct timeval ptv;
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	if (hdrp == NULL)
89*0Sstevel@tonic-gate 		return;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	tvp = &hdrp->sbh_timestamp;
92*0Sstevel@tonic-gate 	if (ptv.tv_sec == 0)
93*0Sstevel@tonic-gate 		ptv = *tvp;
94*0Sstevel@tonic-gate 	drops  = hdrp->sbh_drops;
95*0Sstevel@tonic-gate 	pktlen = hdrp->sbh_msglen;
96*0Sstevel@tonic-gate 	if (pktlen <= 0)
97*0Sstevel@tonic-gate 		return;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	/* set up externals */
100*0Sstevel@tonic-gate 	dlc_header = pktp;
101*0Sstevel@tonic-gate 	pi_frame = num;
102*0Sstevel@tonic-gate 	tm = localtime(&tvp->tv_sec);
103*0Sstevel@tonic-gate 	pi_time_hour = tm->tm_hour;
104*0Sstevel@tonic-gate 	pi_time_min  = tm->tm_min;
105*0Sstevel@tonic-gate 	pi_time_sec  = tm->tm_sec;
106*0Sstevel@tonic-gate 	pi_time_usec = tvp->tv_usec;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	src_name = "?";
109*0Sstevel@tonic-gate 	dst_name = "*";
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	click(hdrp->sbh_origlen);
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	(*interface->interpreter)(flags, dlc_header, hdrp->sbh_msglen,
114*0Sstevel@tonic-gate 	    hdrp->sbh_origlen);
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	show_pktinfo(flags, num, src_name, dst_name, &ptv, tvp, drops,
117*0Sstevel@tonic-gate 	    hdrp->sbh_origlen);
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	if (x_offset >= 0) {
120*0Sstevel@tonic-gate 		offset = MIN(x_offset, hdrp->sbh_msglen);
121*0Sstevel@tonic-gate 		offset -= (offset % 2);  /* round down */
122*0Sstevel@tonic-gate 		length = MIN(hdrp->sbh_msglen - offset, x_length);
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 		hexdump(dlc_header + offset, length);
125*0Sstevel@tonic-gate 	}
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	ptv = *tvp;
128*0Sstevel@tonic-gate }
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate /*
132*0Sstevel@tonic-gate  * *************************************************************
133*0Sstevel@tonic-gate  * The following routines constitute a library
134*0Sstevel@tonic-gate  * used by the packet interpreters to facilitate
135*0Sstevel@tonic-gate  * the display of packet data.  This library
136*0Sstevel@tonic-gate  * of routines helps provide a consistent
137*0Sstevel@tonic-gate  * "look and feel".
138*0Sstevel@tonic-gate  */
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate /*
142*0Sstevel@tonic-gate  * Display the value of a flag bit in
143*0Sstevel@tonic-gate  * a byte together with some text that
144*0Sstevel@tonic-gate  * corresponds to its value - whether
145*0Sstevel@tonic-gate  * true or false.
146*0Sstevel@tonic-gate  */
147*0Sstevel@tonic-gate char *
148*0Sstevel@tonic-gate getflag(int val, int mask, char *s_true, char *s_false)
149*0Sstevel@tonic-gate {
150*0Sstevel@tonic-gate 	static char buff[80];
151*0Sstevel@tonic-gate 	char *p;
152*0Sstevel@tonic-gate 	int set;
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	(void) strcpy(buff, ".... .... = ");
155*0Sstevel@tonic-gate 	if (s_false == NULL)
156*0Sstevel@tonic-gate 		s_false = s_true;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	for (p = &buff[8]; p >= buff; p--) {
159*0Sstevel@tonic-gate 		if (*p == ' ')
160*0Sstevel@tonic-gate 			p--;
161*0Sstevel@tonic-gate 		if (mask & 0x1) {
162*0Sstevel@tonic-gate 			set = val & mask & 0x1;
163*0Sstevel@tonic-gate 			*p = set ? '1':'0';
164*0Sstevel@tonic-gate 			(void) strcat(buff, set ? s_true: s_false);
165*0Sstevel@tonic-gate 			break;
166*0Sstevel@tonic-gate 		}
167*0Sstevel@tonic-gate 		mask >>= 1;
168*0Sstevel@tonic-gate 		val  >>= 1;
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 	return (buff);
171*0Sstevel@tonic-gate }
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate XDR xdrm;
174*0Sstevel@tonic-gate jmp_buf xdr_err;
175*0Sstevel@tonic-gate int xdr_totlen;
176*0Sstevel@tonic-gate char *prot_prefix;
177*0Sstevel@tonic-gate char *prot_nest_prefix = "";
178*0Sstevel@tonic-gate char *prot_title;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate void
181*0Sstevel@tonic-gate show_header(char *pref, char *str, int len)
182*0Sstevel@tonic-gate {
183*0Sstevel@tonic-gate 	prot_prefix = pref;
184*0Sstevel@tonic-gate 	prot_title = str;
185*0Sstevel@tonic-gate 	(void) sprintf(get_detail_line(0, len), "%s%s----- %s -----",
186*0Sstevel@tonic-gate 	    prot_nest_prefix, pref, str);
187*0Sstevel@tonic-gate }
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate void
190*0Sstevel@tonic-gate xdr_init(char *addr, int len)
191*0Sstevel@tonic-gate {
192*0Sstevel@tonic-gate 	xdr_totlen = len;
193*0Sstevel@tonic-gate 	xdrmem_create(&xdrm, addr, len, XDR_DECODE);
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate char *
197*0Sstevel@tonic-gate get_line(int begin, int end)
198*0Sstevel@tonic-gate {
199*0Sstevel@tonic-gate 	char *line;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	line = get_detail_line(begin, end);
202*0Sstevel@tonic-gate 	(void) strcpy(line, prot_nest_prefix);
203*0Sstevel@tonic-gate 	(void) strcat(line, prot_prefix);
204*0Sstevel@tonic-gate 	return (line + strlen(line));
205*0Sstevel@tonic-gate }
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate int
208*0Sstevel@tonic-gate get_line_remain(void)
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate 	return (MAXLINE - strlen(prot_nest_prefix) - strlen(prot_prefix));
211*0Sstevel@tonic-gate }
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate void
214*0Sstevel@tonic-gate show_line(char *str)
215*0Sstevel@tonic-gate {
216*0Sstevel@tonic-gate 	(void) strcpy(get_line(0, 0), str);
217*0Sstevel@tonic-gate }
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate char
220*0Sstevel@tonic-gate getxdr_char()
221*0Sstevel@tonic-gate {
222*0Sstevel@tonic-gate 	char s;
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	if (xdr_char(&xdrm, &s))
225*0Sstevel@tonic-gate 		return (s);
226*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
227*0Sstevel@tonic-gate 	/* NOTREACHED */
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate char
231*0Sstevel@tonic-gate showxdr_char(char *fmt)
232*0Sstevel@tonic-gate {
233*0Sstevel@tonic-gate 	int pos; char val;
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	pos = getxdr_pos();
236*0Sstevel@tonic-gate 	val = getxdr_char();
237*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
238*0Sstevel@tonic-gate 	return (val);
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate uchar_t
242*0Sstevel@tonic-gate getxdr_u_char()
243*0Sstevel@tonic-gate {
244*0Sstevel@tonic-gate 	uchar_t s;
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	if (xdr_u_char(&xdrm, &s))
247*0Sstevel@tonic-gate 		return (s);
248*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
249*0Sstevel@tonic-gate 	/* NOTREACHED */
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate uchar_t
253*0Sstevel@tonic-gate showxdr_u_char(char *fmt)
254*0Sstevel@tonic-gate {
255*0Sstevel@tonic-gate 	int pos;
256*0Sstevel@tonic-gate 	uchar_t val;
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	pos = getxdr_pos();
259*0Sstevel@tonic-gate 	val = getxdr_u_char();
260*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
261*0Sstevel@tonic-gate 	return (val);
262*0Sstevel@tonic-gate }
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate short
265*0Sstevel@tonic-gate getxdr_short()
266*0Sstevel@tonic-gate {
267*0Sstevel@tonic-gate 	short s;
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	if (xdr_short(&xdrm, &s))
270*0Sstevel@tonic-gate 		return (s);
271*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
272*0Sstevel@tonic-gate 	/* NOTREACHED */
273*0Sstevel@tonic-gate }
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate short
276*0Sstevel@tonic-gate showxdr_short(char *fmt)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 	int pos; short val;
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate 	pos = getxdr_pos();
281*0Sstevel@tonic-gate 	val = getxdr_short();
282*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
283*0Sstevel@tonic-gate 	return (val);
284*0Sstevel@tonic-gate }
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate ushort_t
287*0Sstevel@tonic-gate getxdr_u_short()
288*0Sstevel@tonic-gate {
289*0Sstevel@tonic-gate 	ushort_t s;
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	if (xdr_u_short(&xdrm, &s))
292*0Sstevel@tonic-gate 		return (s);
293*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
294*0Sstevel@tonic-gate 	/* NOTREACHED */
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate ushort_t
298*0Sstevel@tonic-gate showxdr_u_short(char *fmt)
299*0Sstevel@tonic-gate {
300*0Sstevel@tonic-gate 	int pos;
301*0Sstevel@tonic-gate 	ushort_t val;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	pos = getxdr_pos();
304*0Sstevel@tonic-gate 	val = getxdr_u_short();
305*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
306*0Sstevel@tonic-gate 	return (val);
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate long
310*0Sstevel@tonic-gate getxdr_long()
311*0Sstevel@tonic-gate {
312*0Sstevel@tonic-gate 	long l;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	if (xdr_long(&xdrm, &l))
315*0Sstevel@tonic-gate 		return (l);
316*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
317*0Sstevel@tonic-gate 	/* NOTREACHED */
318*0Sstevel@tonic-gate }
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate long
321*0Sstevel@tonic-gate showxdr_long(char *fmt)
322*0Sstevel@tonic-gate {
323*0Sstevel@tonic-gate 	int pos; long val;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	pos = getxdr_pos();
326*0Sstevel@tonic-gate 	val = getxdr_long();
327*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
328*0Sstevel@tonic-gate 	return (val);
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate ulong_t
332*0Sstevel@tonic-gate getxdr_u_long()
333*0Sstevel@tonic-gate {
334*0Sstevel@tonic-gate 	ulong_t l;
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	if (xdr_u_long(&xdrm, &l))
337*0Sstevel@tonic-gate 		return (l);
338*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
339*0Sstevel@tonic-gate 	/* NOTREACHED */
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate ulong_t
343*0Sstevel@tonic-gate showxdr_u_long(char *fmt)
344*0Sstevel@tonic-gate {
345*0Sstevel@tonic-gate 	int pos;
346*0Sstevel@tonic-gate 	ulong_t val;
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	pos = getxdr_pos();
349*0Sstevel@tonic-gate 	val = getxdr_u_long();
350*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
351*0Sstevel@tonic-gate 	return (val);
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate longlong_t
355*0Sstevel@tonic-gate getxdr_longlong()
356*0Sstevel@tonic-gate {
357*0Sstevel@tonic-gate 	longlong_t l;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	if (xdr_longlong_t(&xdrm, &l))
360*0Sstevel@tonic-gate 		return (l);
361*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
362*0Sstevel@tonic-gate 	/* NOTREACHED */
363*0Sstevel@tonic-gate }
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate longlong_t
366*0Sstevel@tonic-gate showxdr_longlong(char *fmt)
367*0Sstevel@tonic-gate {
368*0Sstevel@tonic-gate 	int pos; longlong_t val;
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	pos = getxdr_pos();
371*0Sstevel@tonic-gate 	val = getxdr_longlong();
372*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
373*0Sstevel@tonic-gate 	return (val);
374*0Sstevel@tonic-gate }
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate u_longlong_t
377*0Sstevel@tonic-gate getxdr_u_longlong()
378*0Sstevel@tonic-gate {
379*0Sstevel@tonic-gate 	u_longlong_t l;
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 	if (xdr_u_longlong_t(&xdrm, &l))
382*0Sstevel@tonic-gate 		return (l);
383*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
384*0Sstevel@tonic-gate 	/* NOTREACHED */
385*0Sstevel@tonic-gate }
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate u_longlong_t
388*0Sstevel@tonic-gate showxdr_u_longlong(char *fmt)
389*0Sstevel@tonic-gate {
390*0Sstevel@tonic-gate 	int pos; u_longlong_t val;
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	pos = getxdr_pos();
393*0Sstevel@tonic-gate 	val = getxdr_u_longlong();
394*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
395*0Sstevel@tonic-gate 	return (val);
396*0Sstevel@tonic-gate }
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate bool_t
399*0Sstevel@tonic-gate getxdr_bool()
400*0Sstevel@tonic-gate {
401*0Sstevel@tonic-gate 	bool_t b;
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	if (xdr_bool(&xdrm, &b))
404*0Sstevel@tonic-gate 		return (b);
405*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
406*0Sstevel@tonic-gate 	/* NOTREACHED */
407*0Sstevel@tonic-gate }
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate bool_t
410*0Sstevel@tonic-gate showxdr_bool(char *fmt)
411*0Sstevel@tonic-gate {
412*0Sstevel@tonic-gate 	int pos; bool_t val;
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate 	pos = getxdr_pos();
415*0Sstevel@tonic-gate 	val = getxdr_bool();
416*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt,
417*0Sstevel@tonic-gate 	    val ? "True" : "False");
418*0Sstevel@tonic-gate 	return (val);
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate char *
422*0Sstevel@tonic-gate getxdr_opaque(char *p, int len)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 	if (xdr_opaque(&xdrm, p, len))
425*0Sstevel@tonic-gate 		return (p);
426*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
427*0Sstevel@tonic-gate 	/* NOTREACHED */
428*0Sstevel@tonic-gate }
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate char *
431*0Sstevel@tonic-gate getxdr_string(char *p, /* len+1 bytes or longer */
432*0Sstevel@tonic-gate 	int len)
433*0Sstevel@tonic-gate {
434*0Sstevel@tonic-gate 	if (xdr_string(&xdrm, &p, len))
435*0Sstevel@tonic-gate 		return (p);
436*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
437*0Sstevel@tonic-gate 	/* NOTREACHED */
438*0Sstevel@tonic-gate }
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate char *
441*0Sstevel@tonic-gate showxdr_string(int len, /* XDR length */
442*0Sstevel@tonic-gate 	char *fmt)
443*0Sstevel@tonic-gate {
444*0Sstevel@tonic-gate 	static int buff_len = 0;
445*0Sstevel@tonic-gate 	static char *buff = NULL;
446*0Sstevel@tonic-gate 	int pos;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	/*
449*0Sstevel@tonic-gate 	 * XDR strings don't necessarily have a trailing null over the
450*0Sstevel@tonic-gate 	 * wire.  However, the XDR code will put one in for us.  Make sure
451*0Sstevel@tonic-gate 	 * we have allocated room for it.
452*0Sstevel@tonic-gate 	 */
453*0Sstevel@tonic-gate 	len++;
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate 	if ((len > buff_len) || (buff_len == 0)) {
456*0Sstevel@tonic-gate 		if (buff)
457*0Sstevel@tonic-gate 			free(buff);
458*0Sstevel@tonic-gate 		if ((buff = (char *)malloc(len)) == NULL)
459*0Sstevel@tonic-gate 			pr_err("showxdr_string: no mem");
460*0Sstevel@tonic-gate 		buff_len = len;
461*0Sstevel@tonic-gate 	}
462*0Sstevel@tonic-gate 	pos = getxdr_pos();
463*0Sstevel@tonic-gate 	getxdr_string(buff, len);
464*0Sstevel@tonic-gate 	(void) strcpy(buff+60, "...");
465*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, buff);
466*0Sstevel@tonic-gate 	return (buff);
467*0Sstevel@tonic-gate }
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate char *
470*0Sstevel@tonic-gate getxdr_bytes(uint_t *lenp)
471*0Sstevel@tonic-gate {
472*0Sstevel@tonic-gate 	static char buff[1024];
473*0Sstevel@tonic-gate 	char *p = buff;
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	if (xdr_bytes(&xdrm, &p, lenp, 1024))
476*0Sstevel@tonic-gate 		return (buff);
477*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
478*0Sstevel@tonic-gate 	/* NOTREACHED */
479*0Sstevel@tonic-gate }
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate char *
482*0Sstevel@tonic-gate getxdr_context(char *p, int len)
483*0Sstevel@tonic-gate {
484*0Sstevel@tonic-gate 	ushort_t size;
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	size = getxdr_u_short();
487*0Sstevel@tonic-gate 	if (((int)size > 0) && ((int)size < len) && getxdr_opaque(p, size))
488*0Sstevel@tonic-gate 		return (p);
489*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
490*0Sstevel@tonic-gate 	/* NOTREACHED */
491*0Sstevel@tonic-gate }
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate char *
494*0Sstevel@tonic-gate showxdr_context(char *fmt)
495*0Sstevel@tonic-gate {
496*0Sstevel@tonic-gate 	ushort_t size;
497*0Sstevel@tonic-gate 	static char buff[1024];
498*0Sstevel@tonic-gate 	int pos;
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 	pos = getxdr_pos();
501*0Sstevel@tonic-gate 	size = getxdr_u_short();
502*0Sstevel@tonic-gate 	if (((int)size > 0) && ((int)size < 1024) &&
503*0Sstevel@tonic-gate 	    getxdr_opaque(buff, size)) {
504*0Sstevel@tonic-gate 		(void) sprintf(get_line(pos, getxdr_pos()), fmt, buff);
505*0Sstevel@tonic-gate 		return (buff);
506*0Sstevel@tonic-gate 	}
507*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
508*0Sstevel@tonic-gate 	/* NOTREACHED */
509*0Sstevel@tonic-gate }
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate enum_t
512*0Sstevel@tonic-gate getxdr_enum()
513*0Sstevel@tonic-gate {
514*0Sstevel@tonic-gate 	enum_t e;
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 	if (xdr_enum(&xdrm, &e))
517*0Sstevel@tonic-gate 		return (e);
518*0Sstevel@tonic-gate 	longjmp(xdr_err, 1);
519*0Sstevel@tonic-gate 	/* NOTREACHED */
520*0Sstevel@tonic-gate }
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate void
523*0Sstevel@tonic-gate xdr_skip(int delta)
524*0Sstevel@tonic-gate {
525*0Sstevel@tonic-gate 	uint_t pos;
526*0Sstevel@tonic-gate 	if (delta % 4 != 0 || delta < 0)
527*0Sstevel@tonic-gate 		longjmp(xdr_err, 1);
528*0Sstevel@tonic-gate 	/* Check for overflow */
529*0Sstevel@tonic-gate 	pos = xdr_getpos(&xdrm);
530*0Sstevel@tonic-gate 	if ((pos + delta) < pos)
531*0Sstevel@tonic-gate 		longjmp(xdr_err, 1);
532*0Sstevel@tonic-gate 	/* xdr_setpos() checks for buffer overrun */
533*0Sstevel@tonic-gate 	if (xdr_setpos(&xdrm, pos + delta) == FALSE)
534*0Sstevel@tonic-gate 		longjmp(xdr_err, 1);
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate int
538*0Sstevel@tonic-gate getxdr_pos()
539*0Sstevel@tonic-gate {
540*0Sstevel@tonic-gate 	return (xdr_getpos(&xdrm));
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate void
544*0Sstevel@tonic-gate setxdr_pos(int pos)
545*0Sstevel@tonic-gate {
546*0Sstevel@tonic-gate 	xdr_setpos(&xdrm, pos);
547*0Sstevel@tonic-gate }
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate void
550*0Sstevel@tonic-gate show_space()
551*0Sstevel@tonic-gate {
552*0Sstevel@tonic-gate 	(void) get_line(0, 0);
553*0Sstevel@tonic-gate }
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate void
556*0Sstevel@tonic-gate show_trailer()
557*0Sstevel@tonic-gate {
558*0Sstevel@tonic-gate 	show_space();
559*0Sstevel@tonic-gate }
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate char *
562*0Sstevel@tonic-gate getxdr_date()
563*0Sstevel@tonic-gate {
564*0Sstevel@tonic-gate 	time_t sec;
565*0Sstevel@tonic-gate 	int  usec;
566*0Sstevel@tonic-gate 	static char buff[64];
567*0Sstevel@tonic-gate 	char *p;
568*0Sstevel@tonic-gate 	struct tm my_time;	/* private buffer to avoid collision */
569*0Sstevel@tonic-gate 				/* between gmtime and strftime */
570*0Sstevel@tonic-gate 	struct tm *tmp;
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 	sec  = getxdr_long();
573*0Sstevel@tonic-gate 	usec = getxdr_long();
574*0Sstevel@tonic-gate 	if (sec == -1)
575*0Sstevel@tonic-gate 		return ("-1 ");
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 	if (sec < 3600 * 24 * 365) {	/* assume not a date */
578*0Sstevel@tonic-gate 		(void) sprintf(buff, "%d.%06d", sec, usec);
579*0Sstevel@tonic-gate 	} else {
580*0Sstevel@tonic-gate 		tmp = gmtime(&sec);
581*0Sstevel@tonic-gate 		(void) memcpy(&my_time, tmp, sizeof (struct tm));
582*0Sstevel@tonic-gate 		strftime(buff, sizeof (buff), "%d-%h-%y %T.", &my_time);
583*0Sstevel@tonic-gate 		p = buff + strlen(buff);
584*0Sstevel@tonic-gate 		(void) sprintf(p, "%06d GMT", usec);
585*0Sstevel@tonic-gate 	}
586*0Sstevel@tonic-gate 	return (buff);
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate char *
590*0Sstevel@tonic-gate showxdr_date(char *fmt)
591*0Sstevel@tonic-gate {
592*0Sstevel@tonic-gate 	int pos;
593*0Sstevel@tonic-gate 	char *p;
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 	pos = getxdr_pos();
596*0Sstevel@tonic-gate 	p = getxdr_date();
597*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
598*0Sstevel@tonic-gate 	return (p);
599*0Sstevel@tonic-gate }
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate char *
602*0Sstevel@tonic-gate getxdr_date_ns(void)
603*0Sstevel@tonic-gate {
604*0Sstevel@tonic-gate 	time_t sec, nsec;
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	sec  = getxdr_long();
607*0Sstevel@tonic-gate 	nsec = getxdr_long();
608*0Sstevel@tonic-gate 	if (sec == -1)
609*0Sstevel@tonic-gate 		return ("-1 ");
610*0Sstevel@tonic-gate 	else
611*0Sstevel@tonic-gate 		return (format_time(sec, nsec));
612*0Sstevel@tonic-gate }
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate /*
615*0Sstevel@tonic-gate  * Format the given time.
616*0Sstevel@tonic-gate  */
617*0Sstevel@tonic-gate char *
618*0Sstevel@tonic-gate format_time(int64_t sec, uint32_t nsec)
619*0Sstevel@tonic-gate {
620*0Sstevel@tonic-gate 	static char buff[64];
621*0Sstevel@tonic-gate 	char *p;
622*0Sstevel@tonic-gate 	struct tm my_time;	/* private buffer to avoid collision */
623*0Sstevel@tonic-gate 				/* between gmtime and strftime */
624*0Sstevel@tonic-gate 	struct tm *tmp;
625*0Sstevel@tonic-gate 
626*0Sstevel@tonic-gate 	if (sec < 3600 * 24 * 365) {
627*0Sstevel@tonic-gate 		/* assume not a date; includes negative times */
628*0Sstevel@tonic-gate 		(void) sprintf(buff, "%lld.%06d", sec, nsec);
629*0Sstevel@tonic-gate 	} else if (sec > INT32_MAX) {
630*0Sstevel@tonic-gate 		/*
631*0Sstevel@tonic-gate 		 * XXX No routines are available yet for formatting 64-bit
632*0Sstevel@tonic-gate 		 * times.
633*0Sstevel@tonic-gate 		 */
634*0Sstevel@tonic-gate 		(void) sprintf(buff, "%lld.%06d", sec, nsec);
635*0Sstevel@tonic-gate 	} else {
636*0Sstevel@tonic-gate 		time_t sec32 = (time_t)sec;
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate 		tmp = gmtime(&sec32);
639*0Sstevel@tonic-gate 		memcpy(&my_time, tmp, sizeof (struct tm));
640*0Sstevel@tonic-gate 		strftime(buff, sizeof (buff), "%d-%h-%y %T.", &my_time);
641*0Sstevel@tonic-gate 		p = buff + strlen(buff);
642*0Sstevel@tonic-gate 		(void) sprintf(p, "%09d GMT", nsec);
643*0Sstevel@tonic-gate 	}
644*0Sstevel@tonic-gate 	return (buff);
645*0Sstevel@tonic-gate }
646*0Sstevel@tonic-gate 
647*0Sstevel@tonic-gate char *
648*0Sstevel@tonic-gate showxdr_date_ns(char *fmt)
649*0Sstevel@tonic-gate {
650*0Sstevel@tonic-gate 	int pos;
651*0Sstevel@tonic-gate 	char *p;
652*0Sstevel@tonic-gate 
653*0Sstevel@tonic-gate 	pos = getxdr_pos();
654*0Sstevel@tonic-gate 	p = getxdr_date_ns();
655*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
656*0Sstevel@tonic-gate 	return (p);
657*0Sstevel@tonic-gate }
658*0Sstevel@tonic-gate 
659*0Sstevel@tonic-gate char *
660*0Sstevel@tonic-gate getxdr_time()
661*0Sstevel@tonic-gate {
662*0Sstevel@tonic-gate 	time_t sec;
663*0Sstevel@tonic-gate 	static char buff[64];
664*0Sstevel@tonic-gate 	struct tm my_time;	/* private buffer to avoid collision */
665*0Sstevel@tonic-gate 				/* between gmtime and strftime */
666*0Sstevel@tonic-gate 	struct tm *tmp;
667*0Sstevel@tonic-gate 
668*0Sstevel@tonic-gate 	sec  = getxdr_long();
669*0Sstevel@tonic-gate 	if (sec == -1)
670*0Sstevel@tonic-gate 		return ("-1 ");
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate 	if (sec < 3600 * 24 * 365) {	/* assume not a date */
673*0Sstevel@tonic-gate 		(void) sprintf(buff, "%d", sec);
674*0Sstevel@tonic-gate 	} else {
675*0Sstevel@tonic-gate 		tmp = gmtime(&sec);
676*0Sstevel@tonic-gate 		memcpy(&my_time, tmp, sizeof (struct tm));
677*0Sstevel@tonic-gate 		strftime(buff, sizeof (buff), "%d-%h-%y %T", &my_time);
678*0Sstevel@tonic-gate 	}
679*0Sstevel@tonic-gate 	return (buff);
680*0Sstevel@tonic-gate }
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate char *
683*0Sstevel@tonic-gate showxdr_time(char *fmt)
684*0Sstevel@tonic-gate {
685*0Sstevel@tonic-gate 	int pos;
686*0Sstevel@tonic-gate 	char *p;
687*0Sstevel@tonic-gate 
688*0Sstevel@tonic-gate 	pos = getxdr_pos();
689*0Sstevel@tonic-gate 	p = getxdr_time();
690*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
691*0Sstevel@tonic-gate 	return (p);
692*0Sstevel@tonic-gate }
693*0Sstevel@tonic-gate 
694*0Sstevel@tonic-gate char *
695*0Sstevel@tonic-gate getxdr_hex(int len)
696*0Sstevel@tonic-gate {
697*0Sstevel@tonic-gate 	int i, j;
698*0Sstevel@tonic-gate 	static char hbuff[1024];
699*0Sstevel@tonic-gate 	char rbuff[1024];
700*0Sstevel@tonic-gate 	static char *hexstr = "0123456789ABCDEF";
701*0Sstevel@tonic-gate 	char toobig = 0;
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 	if (len == 0) {
704*0Sstevel@tonic-gate 		hbuff[0] = '\0';
705*0Sstevel@tonic-gate 		return (hbuff);
706*0Sstevel@tonic-gate 	}
707*0Sstevel@tonic-gate 	if (len > 1024)
708*0Sstevel@tonic-gate 		len = 1024;
709*0Sstevel@tonic-gate 	if (len < 0 || xdr_opaque(&xdrm, rbuff, len) == FALSE) {
710*0Sstevel@tonic-gate 		longjmp(xdr_err, 1);
711*0Sstevel@tonic-gate 	}
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate 	if (len * 2 > sizeof (hbuff)) {
714*0Sstevel@tonic-gate 		toobig++;
715*0Sstevel@tonic-gate 		len = sizeof (hbuff) / 2;
716*0Sstevel@tonic-gate 	}
717*0Sstevel@tonic-gate 
718*0Sstevel@tonic-gate 	j = 0;
719*0Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
720*0Sstevel@tonic-gate 		hbuff[j++] = hexstr[rbuff[i] >> 4 & 0x0f];
721*0Sstevel@tonic-gate 		hbuff[j++] = hexstr[rbuff[i] & 0x0f];
722*0Sstevel@tonic-gate 	}
723*0Sstevel@tonic-gate 
724*0Sstevel@tonic-gate 	if (toobig) {
725*0Sstevel@tonic-gate 		hbuff[len * 2 - strlen("<Too Long>")] = '\0';
726*0Sstevel@tonic-gate 		strcat(hbuff, "<Too Long>");
727*0Sstevel@tonic-gate 	} else
728*0Sstevel@tonic-gate 		hbuff[j] = '\0';
729*0Sstevel@tonic-gate 
730*0Sstevel@tonic-gate 	return (hbuff);
731*0Sstevel@tonic-gate }
732*0Sstevel@tonic-gate 
733*0Sstevel@tonic-gate char *
734*0Sstevel@tonic-gate showxdr_hex(int len, char *fmt)
735*0Sstevel@tonic-gate {
736*0Sstevel@tonic-gate 	int pos;
737*0Sstevel@tonic-gate 	char *p;
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate 	pos = getxdr_pos();
740*0Sstevel@tonic-gate 	p = getxdr_hex(len);
741*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
742*0Sstevel@tonic-gate 	return (p);
743*0Sstevel@tonic-gate }
744*0Sstevel@tonic-gate 
745*0Sstevel@tonic-gate static void
746*0Sstevel@tonic-gate hexdump(char *data, int datalen)
747*0Sstevel@tonic-gate {
748*0Sstevel@tonic-gate 	char *p;
749*0Sstevel@tonic-gate 	ushort_t *p16 = (ushort_t *)data;
750*0Sstevel@tonic-gate 	char *p8 = data;
751*0Sstevel@tonic-gate 	int i, left, len;
752*0Sstevel@tonic-gate 	int chunk = 16;  /* 16 bytes per line */
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate 	printf("\n");
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 	for (p = data; p < data + datalen; p += chunk) {
757*0Sstevel@tonic-gate 		printf("\t%4d: ", p - data);
758*0Sstevel@tonic-gate 		left = (data + datalen) - p;
759*0Sstevel@tonic-gate 		len = MIN(chunk, left);
760*0Sstevel@tonic-gate 		for (i = 0; i < (len / 2); i++)
761*0Sstevel@tonic-gate 			printf("%04x ", ntohs(*p16++) & 0xffff);
762*0Sstevel@tonic-gate 		if (len % 2) {
763*0Sstevel@tonic-gate 			printf("%02x   ", *((unsigned char *)p16));
764*0Sstevel@tonic-gate 		}
765*0Sstevel@tonic-gate 		for (i = 0; i < (chunk - left) / 2; i++)
766*0Sstevel@tonic-gate 			printf("     ");
767*0Sstevel@tonic-gate 
768*0Sstevel@tonic-gate 		printf("   ");
769*0Sstevel@tonic-gate 		for (i = 0; i < len; i++, p8++)
770*0Sstevel@tonic-gate 			printf("%c", isprint(*p8) ? *p8 : '.');
771*0Sstevel@tonic-gate 		printf("\n");
772*0Sstevel@tonic-gate 	}
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	printf("\n");
775*0Sstevel@tonic-gate }
776