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  0  stevel  * Common Development and Distribution License, Version 1.0 only
      6  0  stevel  * (the "License").  You may not use this file except in compliance
      7  0  stevel  * with the License.
      8  0  stevel  *
      9  0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  0  stevel  * or http://www.opensolaris.org/os/licensing.
     11  0  stevel  * See the License for the specific language governing permissions
     12  0  stevel  * and limitations under the License.
     13  0  stevel  *
     14  0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     15  0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     17  0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     18  0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  0  stevel  *
     20  0  stevel  * CDDL HEADER END
     21  0  stevel  */
     22  0  stevel /*
     23  0  stevel  * Copyright (c) 1991, 1999 by Sun Microsystems, Inc.
     24  0  stevel  * All rights reserved.
     25  0  stevel  */
     26  0  stevel 
     27  0  stevel #ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS	*/
     28  0  stevel 
     29  0  stevel #include <sys/types.h>
     30  0  stevel #include <sys/errno.h>
     31  0  stevel #include <sys/tiuser.h>
     32  0  stevel #include <setjmp.h>
     33  0  stevel #include <string.h>
     34  0  stevel 
     35  0  stevel #include <rpc/types.h>
     36  0  stevel #include <rpc/xdr.h>
     37  0  stevel #include <rpc/auth.h>
     38  0  stevel #include <rpc/clnt.h>
     39  0  stevel #include <rpc/rpc_msg.h>
     40  0  stevel #include "snoop.h"
     41  0  stevel #include "snoop_nfs.h"
     42  0  stevel 
     43  0  stevel #include <sys/stat.h>
     44  0  stevel #include <sys/param.h>
     45  0  stevel #include <rpcsvc/nfs_prot.h>
     46  0  stevel 
     47  0  stevel #ifndef MIN
     48  0  stevel #define	MIN(a, b)	((a) < (b) ? (a) : (b))
     49  0  stevel #endif
     50  0  stevel 
     51  0  stevel extern jmp_buf xdr_err;
     52  0  stevel 
     53  0  stevel static void nfscall3(int);
     54  0  stevel static void nfsreply3(int);
     55  0  stevel static char *perms(int);
     56  0  stevel static char *filetype(int);
     57  0  stevel static char *sum_access(void);
     58  0  stevel static char *sum_readdirres(void);
     59  0  stevel static char *sum_readdirplusres(void);
     60  0  stevel static char *sum_createhow(void);
     61  0  stevel static char *sum_stablehow(void);
     62  0  stevel static void detail_sattr3(void);
     63  0  stevel static void detail_diropargs3(void);
     64  0  stevel static void detail_readdirres(void);
     65  0  stevel static void detail_readdirplusres(void);
     66  0  stevel static void detail_fattr3(void);
     67  0  stevel static void detail_access(void);
     68  0  stevel static void detail_mode(int);
     69  0  stevel static void detail_wcc_attr(void);
     70  0  stevel static void detail_pre_op_attr(char *);
     71  0  stevel static void detail_wcc_data(char *);
     72  0  stevel static void skip_postop(void);
     73  0  stevel static void skip_wcc_data(void);
     74  0  stevel static void skip_sattr3(void);
     75  0  stevel 
     76  0  stevel #define	DONT_CHANGE		0
     77  0  stevel #define	SET_TO_SERVER_TIME	1
     78  0  stevel #define	SET_TO_CLIENT_TIME	2
     79  0  stevel 
     80  0  stevel #define	UNCHECKED	0
     81  0  stevel #define	GUARDED		1
     82  0  stevel #define	EXCLUSIVE	2
     83  0  stevel 
     84  0  stevel #define	ACCESS3_READ	0x0001
     85  0  stevel #define	ACCESS3_LOOKUP	0x0002
     86  0  stevel #define	ACCESS3_MODIFY	0x0004
     87  0  stevel #define	ACCESS3_EXTEND	0x0008
     88  0  stevel #define	ACCESS3_DELETE	0x0010
     89  0  stevel #define	ACCESS3_EXECUTE	0x0020
     90  0  stevel 
     91  0  stevel #define	UNSTABLE	0
     92  0  stevel #define	DATA_SYNC	1
     93  0  stevel #define	FILE_SYNC	2
     94  0  stevel 
     95  0  stevel #define	NF3REG		1	/* regular file */
     96  0  stevel #define	NF3DIR		2	/* directory */
     97  0  stevel #define	NF3BLK		3	/* block special */
     98  0  stevel #define	NF3CHR		4	/* character special */
     99  0  stevel #define	NF3LNK		5	/* symbolic link */
    100  0  stevel #define	NF3SOCK		6	/* unix domain socket */
    101  0  stevel #define	NF3FIFO		7	/* named pipe */
    102  0  stevel 
    103  0  stevel #define	NFS3_FHSIZE	64
    104  0  stevel 
    105  0  stevel static char *procnames_short[] = {
    106  0  stevel 	"NULL3",	/*  0 */
    107  0  stevel 	"GETATTR3",	/*  1 */
    108  0  stevel 	"SETATTR3",	/*  2 */
    109  0  stevel 	"LOOKUP3",	/*  3 */
    110  0  stevel 	"ACCESS3",	/*  4 */
    111  0  stevel 	"READLINK3",	/*  5 */
    112  0  stevel 	"READ3",	/*  6 */
    113  0  stevel 	"WRITE3",	/*  7 */
    114  0  stevel 	"CREATE3",	/*  8 */
    115  0  stevel 	"MKDIR3",	/*  9 */
    116  0  stevel 	"SYMLINK3",	/* 10 */
    117  0  stevel 	"MKNOD3",	/* 11 */
    118  0  stevel 	"REMOVE3",	/* 12 */
    119  0  stevel 	"RMDIR3",	/* 13 */
    120  0  stevel 	"RENAME3",	/* 14 */
    121  0  stevel 	"LINK3",	/* 15 */
    122  0  stevel 	"READDIR3",	/* 16 */
    123  0  stevel 	"READDIRPLUS3",	/* 17 */
    124  0  stevel 	"FSSTAT3",	/* 18 */
    125  0  stevel 	"FSINFO3",	/* 19 */
    126  0  stevel 	"PATHCONF3",	/* 20 */
    127  0  stevel 	"COMMIT3",	/* 21 */
    128  0  stevel };
    129  0  stevel 
    130  0  stevel static char *procnames_long[] = {
    131  0  stevel 	"Null procedure",		/*  0 */
    132  0  stevel 	"Get file attributes",		/*  1 */
    133  0  stevel 	"Set file attributes",		/*  2 */
    134  0  stevel 	"Look up file name",		/*  3 */
    135  0  stevel 	"Check access permission",	/*  4 */
    136  0  stevel 	"Read from symbolic link",	/*  5 */
    137  0  stevel 	"Read from file",		/*  6 */
    138  0  stevel 	"Write to file",		/*  7 */
    139  0  stevel 	"Create file",			/*  8 */
    140  0  stevel 	"Make directory",		/*  9 */
    141  0  stevel 	"Make symbolic link",		/* 10 */
    142  0  stevel 	"Make special file",		/* 11 */
    143  0  stevel 	"Remove file",			/* 12 */
    144  0  stevel 	"Remove directory",		/* 13 */
    145  0  stevel 	"Rename",			/* 14 */
    146  0  stevel 	"Link",				/* 15 */
    147  0  stevel 	"Read from directory",		/* 16 */
    148  0  stevel 	"Read from directory - plus",	/* 17 */
    149  0  stevel 	"Get filesystem statistics",	/* 18 */
    150  0  stevel 	"Get filesystem information",	/* 19 */
    151  0  stevel 	"Get POSIX information",	/* 20 */
    152  0  stevel 	"Commit to stable storage",	/* 21 */
    153  0  stevel };
    154  0  stevel 
    155  0  stevel #define	MAXPROC	21
    156  0  stevel 
    157  0  stevel void
    158  0  stevel interpret_nfs3(flags, type, xid, vers, proc, data, len)
    159  0  stevel 	int flags, type, xid, vers, proc;
    160  0  stevel 	char *data;
    161  0  stevel 	int len;
    162  0  stevel {
    163  0  stevel 	char *line;
    164  0  stevel 	char buff[NFS_MAXPATHLEN + 1];	/* protocol allows longer */
    165  0  stevel 	u_longlong_t off;
    166  0  stevel 	int sz, how;
    167  0  stevel 	char *fh, *name;
    168  0  stevel 
    169  0  stevel 	if (proc < 0 || proc > MAXPROC)
    170  0  stevel 		return;
    171  0  stevel 
    172  0  stevel 	if (flags & F_SUM) {
    173  0  stevel 		line = get_sum_line();
    174  0  stevel 
    175  0  stevel 		if (type == CALL) {
    176  0  stevel 			(void) sprintf(line, "NFS C %s",
    177  0  stevel 				procnames_short[proc]);
    178  0  stevel 			line += strlen(line);
    179  0  stevel 			switch (proc) {
    180  0  stevel 			case NFSPROC3_GETATTR:
    181  0  stevel 			case NFSPROC3_READLINK:
    182  0  stevel 			case NFSPROC3_FSSTAT:
    183  0  stevel 			case NFSPROC3_FSINFO:
    184  0  stevel 			case NFSPROC3_PATHCONF:
    185  0  stevel 				(void) sprintf(line, sum_nfsfh3());
    186  0  stevel 				break;
    187  0  stevel 			case NFSPROC3_SETATTR:
    188  0  stevel 				(void) sprintf(line, sum_nfsfh3());
    189  0  stevel 				break;
    190  0  stevel 			case NFSPROC3_READDIR:
    191  0  stevel 				fh = sum_nfsfh3();
    192  0  stevel 				off = getxdr_u_longlong();
    193  0  stevel 				(void) getxdr_u_longlong();
    194  0  stevel 				sz = getxdr_u_long();
    195  0  stevel 				(void) sprintf(line, "%s Cookie=%llu for %lu",
    196  0  stevel 					fh, off, sz);
    197  0  stevel 				break;
    198  0  stevel 			case NFSPROC3_READDIRPLUS:
    199  0  stevel 				fh = sum_nfsfh3();
    200  0  stevel 				off = getxdr_u_longlong();
    201  0  stevel 				(void) getxdr_u_longlong();
    202  0  stevel 				sz = getxdr_u_long();
    203  0  stevel 				(void) sprintf(line,
    204  0  stevel 						"%s Cookie=%llu for %lu/%lu",
    205  0  stevel 						fh, off, sz, getxdr_u_long());
    206  0  stevel 				break;
    207  0  stevel 			case NFSPROC3_ACCESS:
    208  0  stevel 				fh = sum_nfsfh3();
    209  0  stevel 				(void) sprintf(line, "%s (%s)",
    210  0  stevel 					fh, sum_access());
    211  0  stevel 				break;
    212  0  stevel 			case NFSPROC3_LOOKUP:
    213  0  stevel 			case NFSPROC3_REMOVE:
    214  0  stevel 			case NFSPROC3_RMDIR:
    215  0  stevel 			case NFSPROC3_MKDIR:
    216  0  stevel 				fh = sum_nfsfh3();
    217  0  stevel 				(void) sprintf(line, "%s %s",
    218  0  stevel 					fh, getxdr_string(buff,
    219  0  stevel 						NFS_MAXPATHLEN));
    220  0  stevel 				break;
    221  0  stevel 			case NFSPROC3_CREATE:
    222  0  stevel 				fh = sum_nfsfh3();
    223  0  stevel 				name = getxdr_string(buff, NFS_MAXPATHLEN);
    224  0  stevel 				(void) sprintf(line, "%s (%s) %s",
    225  0  stevel 					fh, sum_createhow(), name);
    226  0  stevel 				break;
    227  0  stevel 			case NFSPROC3_MKNOD:
    228  0  stevel 				fh = sum_nfsfh3();
    229  0  stevel 				name = getxdr_string(buff, NFS_MAXPATHLEN);
    230  0  stevel 				how = getxdr_long();
    231  0  stevel 				(void) sprintf(line, "%s (%s) %s",
    232  0  stevel 					fh, filetype(how), name);
    233  0  stevel 				break;
    234  0  stevel 			case NFSPROC3_READ:
    235  0  stevel 				fh = sum_nfsfh3();
    236  0  stevel 				off = getxdr_u_longlong();
    237  0  stevel 				sz = getxdr_u_long();
    238  0  stevel 				(void) sprintf(line, "%s at %llu for %lu",
    239  0  stevel 					fh, off, sz);
    240  0  stevel 				break;
    241  0  stevel 			case NFSPROC3_WRITE:
    242  0  stevel 				fh = sum_nfsfh3();
    243  0  stevel 				off = getxdr_u_longlong();
    244  0  stevel 				sz = getxdr_u_long();
    245  0  stevel 				(void) sprintf(line, "%s at %llu for %lu (%s)",
    246  0  stevel 					fh, off, sz, sum_stablehow());
    247  0  stevel 				break;
    248  0  stevel 			case NFSPROC3_SYMLINK:
    249  0  stevel 				fh = sum_nfsfh3();
    250  0  stevel 				(void) sprintf(line, "%s %s",
    251  0  stevel 					fh, getxdr_string(buff,
    252  0  stevel 						NFS_MAXPATHLEN));
    253  0  stevel 				skip_sattr3();
    254  0  stevel 				line += strlen(line);
    255  0  stevel 				(void) sprintf(line, " to %s",
    256  0  stevel 					getxdr_string(buff, NFS_MAXPATHLEN));
    257  0  stevel 				break;
    258  0  stevel 			case NFSPROC3_RENAME:
    259  0  stevel 				fh = sum_nfsfh3();
    260  0  stevel 				(void) sprintf(line, "%s %s",
    261  0  stevel 					fh, getxdr_string(buff,
    262  0  stevel 						NFS_MAXPATHLEN));
    263  0  stevel 				line += strlen(line);
    264  0  stevel 				fh = sum_nfsfh3();
    265  0  stevel 				(void) sprintf(line, " to%s %s",
    266  0  stevel 					fh, getxdr_string(buff,
    267  0  stevel 						NFS_MAXPATHLEN));
    268  0  stevel 				break;
    269  0  stevel 			case NFSPROC3_LINK:
    270  0  stevel 				fh = sum_nfsfh3();
    271  0  stevel 				(void) sprintf(line, "%s", fh);
    272  0  stevel 				line += strlen(line);
    273  0  stevel 				fh = sum_nfsfh3();
    274  0  stevel 				(void) sprintf(line, " to%s %s",
    275  0  stevel 					fh, getxdr_string(buff,
    276  0  stevel 						NFS_MAXPATHLEN));
    277  0  stevel 				break;
    278  0  stevel 			case NFSPROC3_COMMIT:
    279  0  stevel 				fh = sum_nfsfh3();
    280  0  stevel 				off = getxdr_u_longlong();
    281  0  stevel 				sz  = getxdr_u_long();
    282  0  stevel 				(void) sprintf(line, "%s at %llu for %lu",
    283  0  stevel 					fh, off, sz);
    284  0  stevel 				break;
    285  0  stevel 			default:
    286  0  stevel 				break;
    287  0  stevel 			}
    288  0  stevel 
    289  0  stevel 			check_retransmit(line, xid);
    290  0  stevel 		} else {
    291  0  stevel 			(void) sprintf(line, "NFS R %s ",
    292  0  stevel 				procnames_short[proc]);
    293  0  stevel 			line += strlen(line);
    294  0  stevel 			switch (proc) {
    295  0  stevel 			case NFSPROC3_LOOKUP:
    296  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK)
    297  0  stevel 					(void) strcat(line, sum_nfsfh3());
    298  0  stevel 				break;
    299  0  stevel 			case NFSPROC3_CREATE:
    300  0  stevel 			case NFSPROC3_MKDIR:
    301  0  stevel 			case NFSPROC3_SYMLINK:
    302  0  stevel 			case NFSPROC3_MKNOD:
    303  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK) {
    304  0  stevel 					if (getxdr_bool())
    305  0  stevel 						(void) strcat(line,
    306  0  stevel 							    sum_nfsfh3());
    307  0  stevel 				}
    308  0  stevel 				break;
    309  0  stevel 			case NFSPROC3_READLINK:
    310  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK) {
    311  0  stevel 					line += strlen(line);
    312  0  stevel 					skip_postop();
    313  0  stevel 					(void) sprintf(line, " (Path=%s)",
    314  0  stevel 						getxdr_string(buff,
    315  0  stevel 						    NFS_MAXPATHLEN));
    316  0  stevel 				}
    317  0  stevel 				break;
    318  0  stevel 			case NFSPROC3_GETATTR:
    319  0  stevel 			case NFSPROC3_SETATTR:
    320  0  stevel 			case NFSPROC3_REMOVE:
    321  0  stevel 			case NFSPROC3_RMDIR:
    322  0  stevel 			case NFSPROC3_RENAME:
    323  0  stevel 			case NFSPROC3_LINK:
    324  0  stevel 			case NFSPROC3_FSSTAT:
    325  0  stevel 			case NFSPROC3_FSINFO:
    326  0  stevel 			case NFSPROC3_PATHCONF:
    327  0  stevel 				(void) sum_nfsstat3(line);
    328  0  stevel 				break;
    329  0  stevel 			case NFSPROC3_ACCESS:
    330  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK) {
    331  0  stevel 					line += strlen(line);
    332  0  stevel 					skip_postop();
    333  0  stevel 					(void) sprintf(line, " (%s)",
    334  0  stevel 						sum_access());
    335  0  stevel 				}
    336  0  stevel 				break;
    337  0  stevel 			case NFSPROC3_WRITE:
    338  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK) {
    339  0  stevel 					line += strlen(line);
    340  0  stevel 					skip_wcc_data();
    341  0  stevel 					sz = getxdr_u_long();
    342  0  stevel 					(void) sprintf(line, " %d (%s)",
    343  0  stevel 						sz, sum_stablehow());
    344  0  stevel 				}
    345  0  stevel 				break;
    346  0  stevel 			case NFSPROC3_READDIR:
    347  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK)
    348  0  stevel 					(void) strcat(line, sum_readdirres());
    349  0  stevel 				break;
    350  0  stevel 			case NFSPROC3_READ:
    351  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK) {
    352  0  stevel 					line += strlen(line);
    353  0  stevel 					skip_postop();
    354  0  stevel 					(void) sprintf(line, " (%lu bytes)",
    355  0  stevel 						getxdr_u_long());
    356  0  stevel 					if (getxdr_bool())
    357  0  stevel 						(void) strcat(line, " EOF");
    358  0  stevel 				}
    359  0  stevel 				break;
    360  0  stevel 			case NFSPROC3_READDIRPLUS:
    361  0  stevel 				if (sum_nfsstat3(line) == NFS3_OK)
    362  0  stevel 					(void) strcat(line,
    363  0  stevel 						    sum_readdirplusres());
    364  0  stevel 				break;
    365  0  stevel 			case NFSPROC3_COMMIT:
    366  0  stevel 				(void) sum_nfsstat3(line);
    367  0  stevel 				break;
    368  0  stevel 			default:
    369  0  stevel 				break;
    370  0  stevel 			}
    371  0  stevel 		}
    372  0  stevel 	}
    373  0  stevel 
    374  0  stevel 	if (flags & F_DTAIL) {
    375  0  stevel 		show_header("NFS:  ", "Sun NFS", len);
    376  0  stevel 		show_space();
    377  0  stevel 		(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
    378  0  stevel 			proc, procnames_long[proc]);
    379  0  stevel 		if (type == CALL)
    380  0  stevel 			nfscall3(proc);
    381  0  stevel 		else
    382  0  stevel 			nfsreply3(proc);
    383  0  stevel 		show_trailer();
    384  0  stevel 	}
    385  0  stevel }
    386  0  stevel 
    387  0  stevel /*
    388  0  stevel  *  Print out version 3 NFS call packets
    389  0  stevel  */
    390  0  stevel static void
    391  0  stevel nfscall3(proc)
    392  0  stevel 	int proc;
    393  0  stevel {
    394  0  stevel 	int h;
    395  0  stevel 
    396  0  stevel 	switch (proc) {
    397  0  stevel 	case NFSPROC3_GETATTR:
    398  0  stevel 	case NFSPROC3_READLINK:
    399  0  stevel 	case NFSPROC3_FSINFO:
    400  0  stevel 	case NFSPROC3_FSSTAT:
    401  0  stevel 	case NFSPROC3_PATHCONF:
    402  0  stevel 		detail_nfsfh3();
    403  0  stevel 		break;
    404  0  stevel 	case NFSPROC3_SETATTR:
    405  0  stevel 		detail_nfsfh3();
    406  0  stevel 		detail_sattr3();
    407  0  stevel 		if (getxdr_bool())
    408  0  stevel 			(void) showxdr_date_ns("Guard = %s");
    409  0  stevel 		break;
    410  0  stevel 	case NFSPROC3_LOOKUP:
    411  0  stevel 	case NFSPROC3_REMOVE:
    412  0  stevel 	case NFSPROC3_RMDIR:
    413  0  stevel 		detail_diropargs3();
    414  0  stevel 		break;
    415  0  stevel 	case NFSPROC3_ACCESS:
    416  0  stevel 		detail_nfsfh3();
    417  0  stevel 		detail_access();
    418  0  stevel 		break;
    419  0  stevel 	case NFSPROC3_MKDIR:
    420  0  stevel 		detail_diropargs3();
    421  0  stevel 		detail_sattr3();
    422  0  stevel 		break;
    423  0  stevel 	case NFSPROC3_CREATE:
    424  0  stevel 		detail_diropargs3();
    425  0  stevel 		h = getxdr_u_long();
    426  0  stevel 		if (h == EXCLUSIVE)
    427  0  stevel 			showxdr_hex(8, "Guard = %s");
    428  0  stevel 		else {
    429  0  stevel 			(void) sprintf(get_line(0, 0), "Method = %s",
    430  0  stevel 			h == UNCHECKED ? "Unchecked" : "Guarded");
    431  0  stevel 			detail_sattr3();
    432  0  stevel 		}
    433  0  stevel 		break;
    434  0  stevel 	case NFSPROC3_MKNOD:
    435  0  stevel 		detail_diropargs3();
    436  0  stevel 		h = getxdr_u_long();
    437  0  stevel 		(void) sprintf(get_line(0, 0), "File type = %s",
    438  0  stevel 			filetype(h));
    439  0  stevel 		switch (h) {
    440  0  stevel 		case NF3CHR:
    441  0  stevel 		case NF3BLK:
    442  0  stevel 			detail_sattr3();
    443  0  stevel 			showxdr_u_long("Major = %lu");
    444  0  stevel 			showxdr_u_long("Minor = %lu");
    445  0  stevel 			break;
    446  0  stevel 		case NF3SOCK:
    447  0  stevel 		case NF3FIFO:
    448  0  stevel 			detail_sattr3();
    449  0  stevel 			break;
    450  0  stevel 		}
    451  0  stevel 		break;
    452  0  stevel 	case NFSPROC3_WRITE:
    453  0  stevel 		detail_nfsfh3();
    454  0  stevel 		(void) showxdr_u_longlong("Offset = %llu");
    455  0  stevel 		(void) showxdr_u_long("Size   = %lu");
    456  0  stevel 		(void) sprintf(get_line(0, 0), "Stable = %s",
    457  0  stevel 				sum_stablehow());
    458  0  stevel 		break;
    459  0  stevel 	case NFSPROC3_RENAME:
    460  0  stevel 		detail_diropargs3();
    461  0  stevel 		detail_diropargs3();
    462  0  stevel 		break;
    463  0  stevel 	case NFSPROC3_LINK:
    464  0  stevel 		detail_nfsfh3();
    465  0  stevel 		detail_diropargs3();
    466  0  stevel 		break;
    467  0  stevel 	case NFSPROC3_SYMLINK:
    468  0  stevel 		detail_diropargs3();
    469  0  stevel 		detail_sattr3();
    470  0  stevel 		(void) showxdr_string(MAXPATHLEN, "Path = %s");
    471  0  stevel 		break;
    472  0  stevel 	case NFSPROC3_READDIR:
    473  0  stevel 		detail_nfsfh3();
    474  0  stevel 		(void) showxdr_u_longlong("Cookie   = %llu");
    475  0  stevel 		(void) showxdr_hex(8, "Verifier = %s");
    476  0  stevel 		(void) showxdr_u_long("Count = %lu");
    477  0  stevel 		break;
    478  0  stevel 	case NFSPROC3_READDIRPLUS:
    479  0  stevel 		detail_nfsfh3();
    480  0  stevel 		(void) showxdr_u_longlong("Cookie   = %llu");
    481  0  stevel 		(void) showxdr_hex(8, "Verifier = %s");
    482  0  stevel 		(void) showxdr_u_long("Dircount = %lu");
    483  0  stevel 		(void) showxdr_u_long("Maxcount = %lu");
    484  0  stevel 		break;
    485  0  stevel 	case NFSPROC3_READ:
    486  0  stevel 	case NFSPROC3_COMMIT:
    487  0  stevel 		detail_nfsfh3();
    488  0  stevel 		(void) showxdr_u_longlong("Offset = %llu");
    489  0  stevel 		(void) showxdr_long("Count = %lu");
    490  0  stevel 		break;
    491  0  stevel 	default:
    492  0  stevel 		break;
    493  0  stevel 	}
    494  0  stevel }
    495  0  stevel 
    496  0  stevel /*
    497  0  stevel  *  Print out version 3 NFS reply packets
    498  0  stevel  */
    499  0  stevel static void
    500  0  stevel nfsreply3(proc)
    501  0  stevel 	int proc;
    502  0  stevel {
    503  0  stevel 	int bits;
    504  0  stevel 
    505  0  stevel 	switch (proc) {
    506  0  stevel 	case NFSPROC3_GETATTR:
    507  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    508  0  stevel 			detail_fattr3();
    509  0  stevel 		}
    510  0  stevel 		break;
    511  0  stevel 	case NFSPROC3_SETATTR:
    512  0  stevel 		(void) detail_nfsstat3();
    513  0  stevel 		detail_wcc_data("");
    514  0  stevel 		break;
    515  0  stevel 	case NFSPROC3_WRITE:
    516  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    517  0  stevel 			detail_wcc_data("");
    518  0  stevel 			(void) showxdr_u_long("Count = %lu bytes written");
    519  0  stevel 			(void) sprintf(get_line(0, 0), "Stable = %s",
    520  0  stevel 					sum_stablehow());
    521  0  stevel 			(void) showxdr_hex(8, "Verifier = %s");
    522  0  stevel 		} else
    523  0  stevel 			detail_wcc_data("");
    524  0  stevel 		break;
    525  0  stevel 	case NFSPROC3_LOOKUP:
    526  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    527  0  stevel 			detail_nfsfh3();
    528  0  stevel 			detail_post_op_attr("(object)");
    529  0  stevel 		}
    530  0  stevel 		detail_post_op_attr("(directory)");
    531  0  stevel 		break;
    532  0  stevel 	case NFSPROC3_CREATE:
    533  0  stevel 	case NFSPROC3_MKDIR:
    534  0  stevel 	case NFSPROC3_SYMLINK:
    535  0  stevel 	case NFSPROC3_MKNOD:
    536  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    537  0  stevel 			if (getxdr_bool())
    538  0  stevel 				detail_nfsfh3();
    539  0  stevel 			else
    540  0  stevel 				(void) sprintf(get_line(0, 0),
    541  0  stevel 						"(No file handle available)");
    542  0  stevel 			detail_post_op_attr("");
    543  0  stevel 		}
    544  0  stevel 		detail_wcc_data("");
    545  0  stevel 		break;
    546  0  stevel 	case NFSPROC3_READLINK:
    547  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    548  0  stevel 			detail_post_op_attr("");
    549  0  stevel 			(void) showxdr_string(MAXPATHLEN, "Path = %s");
    550  0  stevel 		} else
    551  0  stevel 			detail_post_op_attr("");
    552  0  stevel 		break;
    553  0  stevel 	case NFSPROC3_READ:
    554  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    555  0  stevel 			detail_post_op_attr("");
    556  0  stevel 			(void) showxdr_u_long("Count = %lu bytes read");
    557  0  stevel 			(void) showxdr_bool("End of file = %s");
    558  0  stevel 		} else
    559  0  stevel 			detail_post_op_attr("");
    560  0  stevel 		break;
    561  0  stevel 	case NFSPROC3_ACCESS:
    562  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    563  0  stevel 			detail_post_op_attr("");
    564  0  stevel 			(void) sprintf(get_line(0, 0), "Access = %s",
    565  0  stevel 					sum_access());
    566  0  stevel 		} else
    567  0  stevel 			detail_post_op_attr("");
    568  0  stevel 		break;
    569  0  stevel 	case NFSPROC3_REMOVE:
    570  0  stevel 	case NFSPROC3_RMDIR:
    571  0  stevel 		(void) detail_nfsstat3();
    572  0  stevel 		detail_wcc_data("");
    573  0  stevel 		break;
    574  0  stevel 	case NFSPROC3_RENAME:
    575  0  stevel 		(void) detail_nfsstat3();
    576  0  stevel 		detail_wcc_data("(from directory)");
    577  0  stevel 		detail_wcc_data("(to directory)");
    578  0  stevel 		break;
    579  0  stevel 	case NFSPROC3_LINK:
    580  0  stevel 		(void) detail_nfsstat3();
    581  0  stevel 		detail_post_op_attr("");
    582  0  stevel 		detail_wcc_data("");
    583  0  stevel 		break;
    584  0  stevel 	case NFSPROC3_READDIR:
    585  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    586  0  stevel 			detail_readdirres();
    587  0  stevel 		} else
    588  0  stevel 			detail_post_op_attr("");
    589  0  stevel 		break;
    590  0  stevel 	case NFSPROC3_READDIRPLUS:
    591  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    592  0  stevel 			detail_readdirplusres();
    593  0  stevel 		} else
    594  0  stevel 			detail_post_op_attr("");
    595  0  stevel 		break;
    596  0  stevel 	case NFSPROC3_FSSTAT:
    597  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    598  0  stevel 			detail_post_op_attr("");
    599  0  stevel 			(void) showxdr_u_longlong(
    600  0  stevel 				"Total space = %llu bytes");
    601  0  stevel 			(void) showxdr_u_longlong(
    602  0  stevel 				"Available space = %llu bytes");
    603  0  stevel 			(void) showxdr_u_longlong(
    604  0  stevel 				"Available space - this user = %llu bytes");
    605  0  stevel 			(void) showxdr_u_longlong(
    606  0  stevel 				"Total file slots = %llu");
    607  0  stevel 			(void) showxdr_u_longlong(
    608  0  stevel 				"Available file slots = %llu");
    609  0  stevel 			(void) showxdr_u_longlong(
    610  0  stevel 				"Available file slots - this user = %llu");
    611  0  stevel 			(void) showxdr_u_long("Invariant time = %lu sec");
    612  0  stevel 		} else
    613  0  stevel 			detail_post_op_attr("");
    614  0  stevel 		break;
    615  0  stevel 	case NFSPROC3_FSINFO:
    616  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    617  0  stevel 			detail_post_op_attr("");
    618  0  stevel 			(void) show_line("Read transfer sizes:");
    619  0  stevel 			(void) showxdr_u_long("   Maximum = %lu bytes");
    620  0  stevel 			(void) showxdr_u_long("   Preferred = %lu bytes");
    621  0  stevel 			(void) showxdr_u_long(
    622  0  stevel 			    "   Suggested multiple = %lu bytes");
    623  0  stevel 			(void) show_line("Write transfer sizes:");
    624  0  stevel 			(void) showxdr_u_long("   Maximum = %lu bytes");
    625  0  stevel 			(void) showxdr_u_long("   Preferred = %lu bytes");
    626  0  stevel 			(void) showxdr_u_long(
    627  0  stevel 			    "   Suggested multiple = %lu bytes");
    628  0  stevel 			(void) show_line("Directory read size:");
    629  0  stevel 			(void) showxdr_u_long("   Preferred = %lu bytes");
    630  0  stevel 			(void) show_line("File system limits:");
    631  0  stevel 			(void) showxdr_u_longlong(
    632  0  stevel 			    "   Max file size = %llu bytes");
    633  0  stevel 			(void) showxdr_date_ns(
    634  0  stevel 			    "   Server minimum time discrimination = %s sec");
    635  0  stevel 			bits = showxdr_u_long("Properties = 0x%02x");
    636  0  stevel 			(void) sprintf(get_line(0, 0), "	%s",
    637  0  stevel 				getflag(bits, FSF3_LINK,
    638  0  stevel 				"Hard links supported",
    639  0  stevel 				"(hard links not supported)"));
    640  0  stevel 			(void) sprintf(get_line(0, 0), "	%s",
    641  0  stevel 				getflag(bits, FSF3_SYMLINK,
    642  0  stevel 				"Symbolic links supported",
    643  0  stevel 				"(symbolic links not supported)"));
    644  0  stevel 			(void) sprintf(get_line(0, 0), "	%s",
    645  0  stevel 				getflag(bits, FSF3_HOMOGENEOUS,
    646  0  stevel 				"Pathconf cannot vary per file",
    647  0  stevel 				"(pathconf can vary per file)"));
    648  0  stevel 			(void) sprintf(get_line(0, 0), "	%s",
    649  0  stevel 				getflag(bits, FSF3_CANSETTIME,
    650  0  stevel 				"Server can always set file times",
    651  0  stevel 				"(server cannot always set file times)"));
    652  0  stevel 		} else
    653  0  stevel 			detail_post_op_attr("");
    654  0  stevel 		break;
    655  0  stevel 	case NFSPROC3_PATHCONF:
    656  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    657  0  stevel 			detail_post_op_attr("");
    658  0  stevel 			(void) showxdr_u_long("Link max = %lu");
    659  0  stevel 			(void) showxdr_u_long("Name max = %lu");
    660  0  stevel 			(void) showxdr_bool("No trunc         = %s");
    661  0  stevel 			(void) showxdr_bool("Chown restricted = %s");
    662  0  stevel 			(void) showxdr_bool("Case insensitive = %s");
    663  0  stevel 			(void) showxdr_bool("Case preserving  = %s");
    664  0  stevel 		} else
    665  0  stevel 			detail_post_op_attr("");
    666  0  stevel 		break;
    667  0  stevel 	case NFSPROC3_COMMIT:
    668  0  stevel 		if (detail_nfsstat3() == NFS3_OK) {
    669  0  stevel 			detail_wcc_data("");
    670  0  stevel 			(void) showxdr_hex(8, "Verifier = %s");
    671  0  stevel 		} else
    672  0  stevel 			detail_wcc_data("");
    673  0  stevel 		break;
    674  0  stevel 	default:
    675  0  stevel 		break;
    676  0  stevel 	}
    677  0  stevel }
    678  0  stevel 
    679  0  stevel static void
    680  0  stevel detail_diropargs3()
    681  0  stevel {
    682  0  stevel 
    683  0  stevel 	detail_nfsfh3();
    684  0  stevel 	(void) showxdr_string(MAXPATHLEN, "File name = %s");
    685  0  stevel }
    686  0  stevel 
    687  0  stevel int
    688  0  stevel sum_nfsstat3(line)
    689  0  stevel 	char *line;
    690  0  stevel {
    691  0  stevel 	ulong_t status;
    692  0  stevel 	char *p;
    693  0  stevel 
    694  0  stevel 	status = getxdr_long();
    695  0  stevel 	switch (status) {
    696  0  stevel 	case NFS3_OK:		p = "OK"; break;
    697  0  stevel 	case NFS3ERR_PERM:	p = "Not owner"; break;
    698  0  stevel 	case NFS3ERR_NOENT:	p = "No such file or directory"; break;
    699  0  stevel 	case NFS3ERR_IO:	p = "I/O error"; break;
    700  0  stevel 	case NFS3ERR_NXIO:	p = "No such device or address"; break;
    701  0  stevel 	case NFS3ERR_ACCES:	p = "Permission denied"; break;
    702  0  stevel 	case NFS3ERR_EXIST:	p = "File exists"; break;
    703  0  stevel 	case NFS3ERR_XDEV:	p = "Attempted cross-device link"; break;
    704  0  stevel 	case NFS3ERR_NODEV:	p = "No such device"; break;
    705  0  stevel 	case NFS3ERR_NOTDIR:	p = "Not a directory"; break;
    706  0  stevel 	case NFS3ERR_ISDIR:	p = "Is a directory"; break;
    707  0  stevel 	case NFS3ERR_INVAL:	p = "Invalid argument"; break;
    708  0  stevel 	case NFS3ERR_FBIG:	p = "File too large"; break;
    709  0  stevel 	case NFS3ERR_NOSPC:	p = "No space left on device"; break;
    710  0  stevel 	case NFS3ERR_ROFS:	p = "Read-only file system"; break;
    711  0  stevel 	case NFS3ERR_MLINK:	p = "Too many links"; break;
    712  0  stevel 	case NFS3ERR_NAMETOOLONG:p = "File name too long"; break;
    713  0  stevel 	case NFS3ERR_NOTEMPTY:	p = "Directory not empty"; break;
    714  0  stevel 	case NFS3ERR_DQUOT:	p = "Disc quota exceeded"; break;
    715  0  stevel 	case NFS3ERR_STALE:	p = "Stale NFS file handle"; break;
    716  0  stevel 	case NFS3ERR_REMOTE:	p = "Too many levels of remote in path"; break;
    717  0  stevel 	case NFS3ERR_BADHANDLE:	p = "Illegal NFS file handle"; break;
    718  0  stevel 	case NFS3ERR_NOT_SYNC:	p = "Update synch mismatch"; break;
    719  0  stevel 	case NFS3ERR_BAD_COOKIE:p = "Readdir cookie is stale"; break;
    720  0  stevel 	case NFS3ERR_NOTSUPP:	p = "Operation not supported"; break;
    721  0  stevel 	case NFS3ERR_TOOSMALL:	p = "Buffer/request too small"; break;
    722  0  stevel 	case NFS3ERR_SERVERFAULT:p = "Server fault"; break;
    723  0  stevel 	case NFS3ERR_BADTYPE:	p = "Bad type"; break;
    724  0  stevel 	case NFS3ERR_JUKEBOX:	p = "File is temporarily unavailable"; break;
    725  0  stevel 	default:		p = "(unknown error)"; break;
    726  0  stevel 	}
    727  0  stevel 
    728  0  stevel 	(void) strcpy(line, p);
    729  0  stevel 	return (status);
    730  0  stevel }
    731  0  stevel 
    732  0  stevel int
    733  0  stevel detail_nfsstat3()
    734  0  stevel {
    735  0  stevel 	ulong_t status;
    736  0  stevel 	char buff[64];
    737  0  stevel 	int pos;
    738  0  stevel 
    739  0  stevel 	pos = getxdr_pos();
    740  0  stevel 	status = sum_nfsstat3(buff);
    741  0  stevel 
    742  0  stevel 	(void) sprintf(get_line(pos, getxdr_pos()), "Status = %d (%s)",
    743  0  stevel 		status, buff);
    744  0  stevel 
    745  0  stevel 	return ((int)status);
    746  0  stevel }
    747  0  stevel 
    748  0  stevel static void
    749  0  stevel skip_postop()
    750  0  stevel {
    751  0  stevel 
    752  0  stevel 	if (getxdr_bool())
    753  0  stevel 		xdr_skip(21 * 4);	/* XDR size of fattr3 */
    754  0  stevel }
    755  0  stevel 
    756  0  stevel static void
    757  0  stevel skip_wcc_data()
    758  0  stevel {
    759  0  stevel 
    760  0  stevel 	if (getxdr_bool() > 0)
    761  0  stevel 		xdr_skip(3 * 8);
    762  0  stevel 	skip_postop();
    763  0  stevel }
    764  0  stevel 
    765  0  stevel static void
    766  0  stevel skip_sattr3()
    767  0  stevel {
    768  0  stevel 
    769  0  stevel 	if (getxdr_bool() > 0)
    770  0  stevel 		xdr_skip(4);		/* mode */
    771  0  stevel 	if (getxdr_bool() > 0)
    772  0  stevel 		xdr_skip(4);		/* uid */
    773  0  stevel 	if (getxdr_bool() > 0)
    774  0  stevel 		xdr_skip(4);		/* gid */
    775  0  stevel 	if (getxdr_bool() > 0)
    776  0  stevel 		xdr_skip(8);		/* size */
    777  0  stevel 	if (getxdr_bool() > 0)
    778  0  stevel 		xdr_skip(8);		/* atime */
    779  0  stevel 	if (getxdr_bool() > 0)
    780  0  stevel 		xdr_skip(8);		/* mtime */
    781  0  stevel }
    782  0  stevel 
    783  0  stevel char *
    784  0  stevel sum_nfsfh3()
    785  0  stevel {
    786  0  stevel 	int len;
    787  0  stevel 	int fh;
    788  0  stevel 	static char buff[16];
    789  0  stevel 
    790  0  stevel 	len = getxdr_long();
    791  0  stevel 	fh = sum_filehandle(len);
    792  0  stevel 	(void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
    793  0  stevel 	return (buff);
    794  0  stevel }
    795  0  stevel 
    796  0  stevel void
    797  0  stevel detail_nfsfh3()
    798  0  stevel {
    799  0  stevel 	int pos;
    800  0  stevel 	int i, l, len;
    801  0  stevel 	int fh;
    802  0  stevel 
    803  0  stevel 	len = getxdr_long();
    804  0  stevel 	pos = getxdr_pos();
    805  0  stevel 	fh = sum_filehandle(len);
    806  0  stevel 	setxdr_pos(pos);
    807  0  stevel 	(void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
    808  0  stevel 	i = 0;
    809  0  stevel 	while (i < len) {
    810  0  stevel 		l = MIN(len - i, 32);
    811  0  stevel 		(void) showxdr_hex(l, " %s");
    812  0  stevel 		i += l;
    813  0  stevel 	}
    814  0  stevel }
    815  0  stevel 
    816  0  stevel static char *
    817  0  stevel sum_access()
    818  0  stevel {
    819  0  stevel 	int bits;
    820  0  stevel 	static char buff[64];
    821  0  stevel 
    822  0  stevel 	bits = getxdr_u_long();
    823  0  stevel 	buff[0] = '\0';
    824  0  stevel 
    825  0  stevel 	if (bits & ACCESS3_READ)
    826  0  stevel 		(void) strcat(buff, "read,");
    827  0  stevel 	if (bits & ACCESS3_LOOKUP)
    828  0  stevel 		(void) strcat(buff, "lookup,");
    829  0  stevel 	if (bits & ACCESS3_MODIFY)
    830  0  stevel 		(void) strcat(buff, "modify,");
    831  0  stevel 	if (bits & ACCESS3_EXTEND)
    832  0  stevel 		(void) strcat(buff, "extend,");
    833  0  stevel 	if (bits & ACCESS3_DELETE)
    834  0  stevel 		(void) strcat(buff, "delete,");
    835  0  stevel 	if (bits & ACCESS3_EXECUTE)
    836  0  stevel 		(void) strcat(buff, "execute,");
    837  0  stevel 	if (buff[0] != '\0')
    838  0  stevel 		buff[strlen(buff) - 1] = '\0';
    839  0  stevel 
    840  0  stevel 	return (buff);
    841  0  stevel }
    842  0  stevel 
    843  0  stevel static void
    844  0  stevel detail_access()
    845  0  stevel {
    846  0  stevel 	uint_t bits;
    847  0  stevel 
    848  0  stevel 	bits = showxdr_u_long("Access bits = 0x%08x");
    849  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    850  0  stevel 		getflag(bits, ACCESS3_READ, "Read", "(no read)"));
    851  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    852  0  stevel 		getflag(bits, ACCESS3_LOOKUP, "Lookup", "(no lookup)"));
    853  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    854  0  stevel 		getflag(bits, ACCESS3_MODIFY, "Modify", "(no modify)"));
    855  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    856  0  stevel 		getflag(bits, ACCESS3_EXTEND, "Extend", "(no extend)"));
    857  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    858  0  stevel 		getflag(bits, ACCESS3_DELETE, "Delete", "(no delete)"));
    859  0  stevel 	(void) sprintf(get_line(0, 0), "	%s",
    860  0  stevel 		getflag(bits, ACCESS3_EXECUTE, "Execute", "(no execute)"));
    861  0  stevel }
    862  0  stevel 
    863  0  stevel static void
    864  0  stevel detail_mode(mode)
    865  0  stevel 	int mode;
    866  0  stevel {
    867  0  stevel 
    868  0  stevel 	(void) sprintf(get_line(0, 0), "  Mode = 0%o", mode);
    869  0  stevel 	(void) sprintf(get_line(0, 0),
    870  0  stevel 		"   Setuid = %d, Setgid = %d, Sticky = %d",
    871  0  stevel 		(mode & S_ISUID) != 0,
    872  0  stevel 		(mode & S_ISGID) != 0,
    873  0  stevel 		(mode & S_ISVTX) != 0);
    874  0  stevel 	(void) sprintf(get_line(0, 0), "   Owner's permissions = %s",
    875  0  stevel 		perms(mode >> 6 & 0x7));
    876  0  stevel 	(void) sprintf(get_line(0, 0), "   Group's permissions = %s",
    877  0  stevel 		perms(mode >> 3 & 0x7));
    878  0  stevel 	(void) sprintf(get_line(0, 0), "   Other's permissions = %s",
    879  0  stevel 		perms(mode & 0x7));
    880  0  stevel }
    881  0  stevel 
    882  0  stevel static void
    883  0  stevel detail_fattr3()
    884  0  stevel {
    885  0  stevel 	uint_t fltype, mode, nlinks, uid, gid;
    886  0  stevel 	uint_t major, minor;
    887  0  stevel 	u_longlong_t size, used, fsid, fileid;
    888  0  stevel 
    889  0  stevel 	fltype  = getxdr_u_long();
    890  0  stevel 	mode	= getxdr_u_long();
    891  0  stevel 	nlinks	= getxdr_u_long();
    892  0  stevel 	uid	= getxdr_u_long();
    893  0  stevel 	gid	= getxdr_u_long();
    894  0  stevel 	size	= getxdr_u_longlong();
    895  0  stevel 	used 	= getxdr_u_longlong();
    896  0  stevel 	major	= getxdr_u_long();
    897  0  stevel 	minor	= getxdr_u_long();
    898  0  stevel 	fsid	= getxdr_u_longlong();
    899  0  stevel 	fileid	= getxdr_u_longlong();
    900  0  stevel 
    901  0  stevel 	(void) sprintf(get_line(0, 0),
    902  0  stevel 		"  File type = %d (%s)",
    903  0  stevel 		fltype, filetype(fltype));
    904  0  stevel 	detail_mode(mode);
    905  0  stevel 	(void) sprintf(get_line(0, 0),
    906  0  stevel 		"  Link count = %u, User ID = %u, Group ID = %u",
    907  0  stevel 		nlinks, uid, gid);
    908  0  stevel 	(void) sprintf(get_line(0, 0),
    909  0  stevel 		"  File size = %llu, Used = %llu",
    910  0  stevel 		size, used);
    911  0  stevel 	(void) sprintf(get_line(0, 0),
    912  0  stevel 		"  Special: Major = %u, Minor = %u",
    913  0  stevel 		major, minor);
    914  0  stevel 	(void) sprintf(get_line(0, 0),
    915  0  stevel 		"  File system id = %llu, File id = %llu",
    916  0  stevel 		fsid, fileid);
    917  0  stevel 	(void) showxdr_date_ns("  Last access time      = %s");
    918  0  stevel 	(void) showxdr_date_ns("  Modification time     = %s");
    919  0  stevel 	(void) showxdr_date_ns("  Attribute change time = %s");
    920  0  stevel 	(void) show_line("");
    921  0  stevel }
    922  0  stevel 
    923  0  stevel static void
    924  0  stevel detail_sattr3()
    925  0  stevel {
    926  0  stevel 	int t;
    927  0  stevel 
    928  0  stevel 	if (getxdr_bool())
    929  0  stevel 		detail_mode(getxdr_u_long());
    930  0  stevel 	else
    931  0  stevel 		(void) sprintf(get_line(0, 0), "Mode = (not set)");
    932  0  stevel 	if (getxdr_bool())
    933  0  stevel 		(void) showxdr_long("User ID = %d");
    934  0  stevel 	else
    935  0  stevel 		(void) sprintf(get_line(0, 0), "User ID = (not set)");
    936  0  stevel 	if (getxdr_bool())
    937  0  stevel 		(void) showxdr_long("Group ID = %d");
    938  0  stevel 	else
    939  0  stevel 		(void) sprintf(get_line(0, 0), "Group ID = (not set)");
    940  0  stevel 	if (getxdr_bool())
    941  0  stevel 		(void) showxdr_u_longlong("Size = %llu");
    942  0  stevel 	else
    943  0  stevel 		(void) sprintf(get_line(0, 0), "Size = (not set)");
    944  0  stevel 
    945  0  stevel 	if ((t = getxdr_u_long()) == SET_TO_CLIENT_TIME)
    946  0  stevel 		(void) showxdr_date("Access time = %s (set to client time)");
    947  0  stevel 	else if (t == SET_TO_SERVER_TIME)
    948  0  stevel 		(void) sprintf(get_line(0, 0),
    949  0  stevel 				"Access time = (set to server time)");
    950  0  stevel 	else
    951  0  stevel 		(void) sprintf(get_line(0, 0), "Access time = (do not set)");
    952  0  stevel 
    953  0  stevel 	if ((t = getxdr_u_long()) == SET_TO_CLIENT_TIME) {
    954  0  stevel 		(void) showxdr_date(
    955  0  stevel 				"Modification time = %s (set to client time)");
    956  0  stevel 	} else if (t == SET_TO_SERVER_TIME)
    957  0  stevel 		(void) sprintf(get_line(0, 0),
    958  0  stevel 				"Modification time = (set to server time)");
    959  0  stevel 	else
    960  0  stevel 		(void) sprintf(get_line(0, 0),
    961  0  stevel 				"Modification time = (do not set)");
    962  0  stevel 	(void) show_line("");
    963  0  stevel }
    964  0  stevel 
    965  0  stevel static char *
    966  0  stevel filetype(n)
    967  0  stevel 	int n;
    968  0  stevel {
    969  0  stevel 
    970  0  stevel 	switch (n) {
    971  0  stevel 	case NF3REG:
    972  0  stevel 		return ("Regular File");
    973  0  stevel 	case NF3DIR:
    974  0  stevel 		return ("Directory");
    975  0  stevel 	case NF3BLK:
    976  0  stevel 		return ("Block special");
    977  0  stevel 	case NF3CHR:
    978  0  stevel 		return ("Character special");
    979  0  stevel 	case NF3LNK:
    980  0  stevel 		return ("Symbolic Link");
    981  0  stevel 	case NF3SOCK:
    982  0  stevel 		return ("Unix domain socket");
    983  0  stevel 	case NF3FIFO:
    984  0  stevel 		return ("Named pipe");
    985  0  stevel 	default:
    986  0  stevel 		return ("?");
    987  0  stevel 	}
    988  0  stevel 	/* NOTREACHED */
    989  0  stevel }
    990  0  stevel 
    991  0  stevel static char *
    992  0  stevel perms(n)
    993  0  stevel 	int n;
    994  0  stevel {
    995  0  stevel 	static char buff[4];
    996  0  stevel 
    997  0  stevel 	buff[0] = n & 4 ? 'r' : '-';
    998  0  stevel 	buff[1] = n & 2 ? 'w' : '-';
    999  0  stevel 	buff[2] = n & 1 ? 'x' : '-';
   1000  0  stevel 	buff[3] = '\0';
   1001  0  stevel 	return (buff);
   1002  0  stevel }
   1003  0  stevel 
   1004  0  stevel static void
   1005  0  stevel detail_wcc_attr()
   1006  0  stevel {
   1007  0  stevel 
   1008  0  stevel 	(void) showxdr_u_longlong("  Size = %llu bytes");
   1009  0  stevel 	(void) showxdr_date_ns("  Modification time      = %s");
   1010  0  stevel 	(void) showxdr_date_ns("  Attribute change time  = %s");
   1011  0  stevel 	(void) show_line("");
   1012  0  stevel }
   1013  0  stevel 
   1014  0  stevel static void
   1015  0  stevel detail_pre_op_attr(str)
   1016  0  stevel 	char *str;
   1017  0  stevel {
   1018  0  stevel 
   1019  0  stevel 	if (getxdr_bool()) {
   1020  0  stevel 		(void) sprintf(get_line(0, 0),
   1021  0  stevel 			"Pre-operation attributes: %s", str);
   1022  0  stevel 		detail_wcc_attr();
   1023  0  stevel 	} else
   1024  0  stevel 		(void) sprintf(get_line(0, 0),
   1025  0  stevel 			"Pre-operation attributes: %s (not available)", str);
   1026  0  stevel }
   1027  0  stevel 
   1028  0  stevel void
   1029  0  stevel detail_post_op_attr(str)
   1030  0  stevel 	char *str;
   1031  0  stevel {
   1032  0  stevel 
   1033  0  stevel 	if (getxdr_bool()) {
   1034  0  stevel 		(void) sprintf(get_line(0, 0),
   1035  0  stevel 			"Post-operation attributes: %s", str);
   1036  0  stevel 		detail_fattr3();
   1037  0  stevel 	} else
   1038  0  stevel 		(void) sprintf(get_line(0, 0),
   1039  0  stevel 			"Post-operation attributes: %s (not available)", str);
   1040  0  stevel }
   1041  0  stevel 
   1042  0  stevel static void
   1043  0  stevel detail_wcc_data(str)
   1044  0  stevel 	char *str;
   1045  0  stevel {
   1046  0  stevel 
   1047  0  stevel 	detail_pre_op_attr(str);
   1048  0  stevel 	detail_post_op_attr(str);
   1049  0  stevel }
   1050  0  stevel 
   1051  0  stevel static char *
   1052  0  stevel sum_readdirres()
   1053  0  stevel {
   1054  0  stevel 	static char buff[NFS_MAXNAMLEN + 1]; /* protocol allows longer names */
   1055  0  stevel 	static int entries;
   1056  0  stevel 
   1057  0  stevel 	entries = 0;
   1058  0  stevel 	if (setjmp(xdr_err)) {
   1059  0  stevel 		(void) sprintf(buff, " %d+ entries (incomplete)", entries);
   1060  0  stevel 		return (buff);
   1061  0  stevel 	}
   1062  0  stevel 	skip_postop();
   1063  0  stevel 	xdr_skip(8);	/* cookieverf */
   1064  0  stevel 	while (getxdr_bool()) {
   1065  0  stevel 		entries++;
   1066  0  stevel 		xdr_skip(8);				/* fileid */
   1067  0  stevel 		(void) getxdr_string(buff, NFS_MAXNAMLEN); /* name */
   1068  0  stevel 		xdr_skip(8);				/* cookie */
   1069  0  stevel 	}
   1070  0  stevel 
   1071  0  stevel 	(void) sprintf(buff, " %d entries (%s)",
   1072  0  stevel 		entries, getxdr_bool() ? "No more" : "More");
   1073  0  stevel 	return (buff);
   1074  0  stevel }
   1075  0  stevel 
   1076  0  stevel static char *
   1077  0  stevel sum_readdirplusres()
   1078  0  stevel {
   1079  0  stevel 	static char buff[NFS_MAXNAMLEN + 1]; /* protocol allows longer */
   1080  0  stevel 	static int entries;
   1081  0  stevel 	int skip;
   1082  0  stevel 
   1083  0  stevel 	entries = 0;
   1084  0  stevel 	if (setjmp(xdr_err)) {
   1085  0  stevel 		(void) sprintf(buff, " %d+ entries (incomplete)", entries);
   1086  0  stevel 		return (buff);
   1087  0  stevel 	}
   1088  0  stevel 	skip_postop();
   1089  0  stevel 	xdr_skip(8);	/* cookieverf */
   1090  0  stevel 	while (getxdr_bool()) {
   1091  0  stevel 		entries++;
   1092  0  stevel 		xdr_skip(8);				/* fileid */
   1093  0  stevel 		(void) getxdr_string(buff, NFS_MAXNAMLEN); /* name */
   1094  0  stevel 		xdr_skip(8);				/* cookie */
   1095  0  stevel 		skip_postop();				/* post-op */
   1096  0  stevel 		if (getxdr_bool()) {
   1097  0  stevel 			skip = getxdr_long();
   1098  0  stevel 			xdr_skip(RNDUP(skip));		/* fhandle */
   1099  0  stevel 		}
   1100  0  stevel 	}
   1101  0  stevel 
   1102  0  stevel 	(void) sprintf(buff, " %d entries (%s)",
   1103  0  stevel 		entries, getxdr_bool() ? "No more" : "More");
   1104  0  stevel 	return (buff);
   1105  0  stevel }
   1106  0  stevel 
   1107  0  stevel static void
   1108  0  stevel detail_readdirres()
   1109  0  stevel {
   1110  0  stevel 	static int entries;
   1111  0  stevel 	u_longlong_t fileid, cookie;
   1112  0  stevel 	char *name;
   1113  0  stevel 	char buff[NFS_MAXNAMLEN + 1];	/* protocol allows longer names */
   1114  0  stevel 
   1115  0  stevel 	entries = 0;
   1116  0  stevel 	detail_post_op_attr("");
   1117  0  stevel 	(void) showxdr_hex(8, "Cookie verifier = %s");
   1118  0  stevel 	(void) show_line("");
   1119  0  stevel 	(void) sprintf(get_line(0, 0), "   File id    Cookie   Name");
   1120  0  stevel 
   1121  0  stevel 	if (setjmp(xdr_err)) {
   1122  0  stevel 		(void) sprintf(get_line(0, 0),
   1123  0  stevel 			"  %d+ entries. (Frame is incomplete)",
   1124  0  stevel 			entries);
   1125  0  stevel 		return;
   1126  0  stevel 	}
   1127  0  stevel 	while (getxdr_bool()) {
   1128  0  stevel 		entries++;
   1129  0  stevel 		fileid = getxdr_u_longlong();
   1130  0  stevel 		name = (char *)getxdr_string(buff, NFS_MAXNAMLEN);
   1131  0  stevel 		cookie = getxdr_u_longlong();
   1132  0  stevel 		(void) sprintf(get_line(0, 0),
   1133  0  stevel 			" %10llu %10llu %s",
   1134  0  stevel 			fileid, cookie, name);
   1135  0  stevel 	}
   1136  0  stevel 
   1137  0  stevel 	(void) sprintf(get_line(0, 0), "  %d entries", entries);
   1138  0  stevel 	(void) showxdr_bool("EOF = %s");
   1139  0  stevel }
   1140  0  stevel 
   1141  0  stevel static void
   1142  0  stevel detail_readdirplusres()
   1143  0  stevel {
   1144  0  stevel 	static int entries;
   1145  0  stevel 
   1146  0  stevel 	entries = 0;
   1147  0  stevel 	detail_post_op_attr("");
   1148  0  stevel 	(void) showxdr_hex(8, "Cookie verifier = %s");
   1149  0  stevel 	(void) show_line("");
   1150  0  stevel 
   1151  0  stevel 	if (setjmp(xdr_err)) {
   1152  0  stevel 		(void) sprintf(get_line(0, 0),
   1153  0  stevel 			"  %d+ entries. (Frame is incomplete)",
   1154  0  stevel 			entries);
   1155  0  stevel 		return;
   1156  0  stevel 	}
   1157  0  stevel 	while (getxdr_bool()) {
   1158  0  stevel 		entries++;
   1159  0  stevel 		(void) sprintf(get_line(0, 0),
   1160  0  stevel 			"------------------ entry #%d",
   1161  0  stevel 			entries);
   1162  0  stevel 		(void) showxdr_u_longlong("File ID = %llu");
   1163  0  stevel 		(void) showxdr_string(NFS_MAXNAMLEN, "Name = %s");
   1164  0  stevel 		(void) showxdr_u_longlong("Cookie = %llu");
   1165  0  stevel 		detail_post_op_attr("");
   1166  0  stevel 		if (getxdr_bool())
   1167  0  stevel 			detail_nfsfh3();
   1168  0  stevel 		else
   1169  0  stevel 			(void) sprintf(get_line(0, 0),
   1170  0  stevel 					"(No file handle available)");
   1171  0  stevel 	}
   1172  0  stevel 
   1173  0  stevel 	(void) show_line("");
   1174  0  stevel 	(void) sprintf(get_line(0, 0), "  %d entries", entries);
   1175  0  stevel 	(void) showxdr_bool("EOF = %s");
   1176  0  stevel }
   1177  0  stevel 
   1178  0  stevel static char *
   1179  0  stevel sum_createhow()
   1180  0  stevel {
   1181  0  stevel 	long how;
   1182  0  stevel 
   1183  0  stevel 	how = getxdr_long();
   1184  0  stevel 	switch (how) {
   1185  0  stevel 	case UNCHECKED:
   1186  0  stevel 		return ("UNCHECKED");
   1187  0  stevel 	case GUARDED:
   1188  0  stevel 		return ("GUARDED");
   1189  0  stevel 	case EXCLUSIVE:
   1190  0  stevel 		return ("EXCLUSIVE");
   1191  0  stevel 	default:
   1192  0  stevel 		return ("?");
   1193  0  stevel 	}
   1194  0  stevel 	/* NOTREACHED */
   1195  0  stevel }
   1196  0  stevel 
   1197  0  stevel static char *
   1198  0  stevel sum_stablehow()
   1199  0  stevel {
   1200  0  stevel 	long stable;
   1201  0  stevel 
   1202  0  stevel 	stable = getxdr_long();
   1203  0  stevel 	switch (stable) {
   1204  0  stevel 	case UNSTABLE:
   1205  0  stevel 		return ("ASYNC");
   1206  0  stevel 	case DATA_SYNC:
   1207  0  stevel 		return ("DSYNC");
   1208  0  stevel 	case FILE_SYNC:
   1209  0  stevel 		return ("FSYNC");
   1210  0  stevel 	default:
   1211  0  stevel 		return ("?");
   1212  0  stevel 	}
   1213  0  stevel 	/* NOTREACHED */
   1214  0  stevel }
   1215