Home | History | Annotate | Download | only in snoop
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <ctype.h>
     27 #include <string.h>
     28 #include <strings.h>
     29 #include <stdlib.h>
     30 #include <sys/types.h>
     31 #include <sys/errno.h>
     32 #include <sys/tiuser.h>
     33 #include <setjmp.h>
     34 #include <netdb.h>
     35 #include <sys/socket.h>
     36 #include <errno.h>
     37 
     38 #include <rpc/types.h>
     39 #include <rpc/xdr.h>
     40 #include <rpc/auth.h>
     41 #include <rpc/clnt.h>
     42 #include <rpc/rpc_msg.h>
     43 #include "snoop.h"
     44 
     45 #include <sys/stat.h>
     46 #include <sys/param.h>
     47 #include <rpcsvc/nfs_prot.h>
     48 
     49 /* use the same nfs4_prot.h as the xdr code */
     50 /* #include "rpcsvc/nfs4_prot.h" */
     51 #include "nfs4_prot.h"
     52 
     53 /*
     54  * Things common to nfs4 and ctl.
     55  */
     56 #include "nfs4_cmn.h"
     57 
     58 /*
     59  * XXX With NFS v2 and v3, we only need to xdr the pieces that we care
     60  * about.  Anything else we can ignore and just skip to the next packet.
     61  * So all the stuff that deals directly with XDR lives in snoop_display.c
     62  * With v4, we need to XDR entire structures so that we can skip over
     63  * uninteresting bits in a compound array, so we call XDR directly from
     64  * here.  We need to rethink how we're going to structure XDR access.  Do
     65  * we continue to hide it all in snoop_display.c, or do we expose it to all
     66  * the protocol modules?
     67  */
     68 extern XDR xdrm;
     69 
     70 #ifndef MIN
     71 #define	MIN(a, b)	((a) < (b) ? (a) : (b))
     72 #endif
     73 
     74 /*
     75  * Maximum number of characters to display in compound4 summary line.
     76  */
     77 #define	SUM_COMPND_MAX	100
     78 
     79 /*
     80  * Maximum number of recognized attributes.
     81  */
     82 #define	MAX_ATTRIBUTES	77
     83 
     84 /*
     85  * This data structure provides a more convenient way to access an
     86  * attribute bitmask.  map[N] = value of bit N in a bitmap4.
     87  * It's defined as a struct so as to step around all the weird rules in C
     88  * about arrays, pointers, passing them as arguments, etc.
     89  */
     90 
     91 typedef struct {
     92 	char map[MAX_ATTRIBUTES];
     93 } unpkd_attrmap_t;
     94 
     95 static void sumarg_cb_getattr(char *buf, size_t buflen, void *obj);
     96 static void dtlarg_cb_getattr(void *obj);
     97 static void sumarg_cb_recall(char *buf, size_t buflen, void *obj);
     98 static void dtlarg_cb_recall(void *obj);
     99 
    100 static void sumarg_access(char *buf, size_t buflen, void *obj);
    101 static void dtlarg_access(void *obj);
    102 static void sumarg_close(char *buf, size_t buflen, void *obj);
    103 static void dtlarg_close(void *obj);
    104 static void sumarg_commit(char *buf, size_t buflen, void *obj);
    105 static void dtlarg_commit(void *obj);
    106 static void sumarg_compnt(char *buf, size_t buflen, void *obj);
    107 static void dtlarg_compnt(void *obj);
    108 static void sumarg_create(char *buf, size_t buflen, void *obj);
    109 static void dtlarg_create(void *obj);
    110 static void sumarg_delprge(char *buf, size_t buflen, void *obj);
    111 static void dtlarg_delprge(void *obj);
    112 static void sumarg_delret(char *buf, size_t buflen, void *obj);
    113 static void dtlarg_delret(void *obj);
    114 static void sumarg_getattr(char *buf, size_t buflen, void *obj);
    115 static void dtlarg_getattr(void *obj);
    116 static void sumarg_link(char *buf, size_t buflen, void *obj);
    117 static void dtlarg_link(void *obj);
    118 static void sum_open_to_lock_owner(char *buf, int buflen,
    119 					open_to_lock_owner4 *own);
    120 static void sum_exist_lock_owner(char *buf, int buflen,
    121 					exist_lock_owner4 *own);
    122 static void sum_locker(char *buf, size_t buflen, locker4 *lk);
    123 static void sumarg_lock(char *buf, size_t buflen, void *obj);
    124 static void detail_headerpadsize(count4);
    125 static void detail_open_to_lock_owner(open_to_lock_owner4 *own);
    126 static void detail_exist_lock_owner(exist_lock_owner4 *own);
    127 static void detail_locker(locker4 *lk);
    128 static void dtlarg_lock(void *obj);
    129 static void sumarg_lockt(char *buf, size_t buflen, void *obj);
    130 static void dtlarg_lockt(void *obj);
    131 static void sumarg_locku(char *buf, size_t buflen, void *obj);
    132 static void dtlarg_locku(void *obj);
    133 static void sumarg_lookup(char *buf, size_t buflen, void *obj);
    134 static void dtlarg_lookup(void *obj);
    135 static char *detail_lortype_name(layoutrecall_type4);
    136 static char *sum_lortype_name(layoutrecall_type4);
    137 static void sumarg_open(char *buf, size_t buflen, void *obj);
    138 static void dtlarg_open(void *obj);
    139 static void sumarg_openattr(char *buf, size_t buflen, void *obj);
    140 static void dtlarg_openattr(void *obj);
    141 static void sumarg_open_confirm(char *buf, size_t buflen, void *obj);
    142 static void dtlarg_open_confirm(void *obj);
    143 static void sumarg_open_downgrd(char *buf, size_t buflen, void *obj);
    144 static void dtlarg_open_downgrd(void *obj);
    145 static void sumarg_putfh(char *buf, size_t buflen, void *obj);
    146 static void dtlarg_putfh(void *obj);
    147 static void sumarg_read(char *buf, size_t buflen, void *obj);
    148 static void dtlarg_read(void *obj);
    149 static void sumarg_readdir(char *buf, size_t buflen, void *obj);
    150 static void dtlarg_readdir(void *obj);
    151 static void sumarg_release_lkown(char *buf, size_t buflen, void *obj);
    152 static void dtlarg_release_lkown(void *obj);
    153 static void sumarg_rename(char *buf, size_t buflen, void *obj);
    154 static void dtlarg_rename(void *obj);
    155 static void sumarg_renew(char *buf, size_t buflen, void *obj);
    156 static void dtlarg_renew(void *buf);
    157 static void sumarg_secinfo(char *buf, size_t buflen, void *obj);
    158 static void dtlarg_secinfo(void *obj);
    159 static void sumarg_setattr(char *buf, size_t buflen, void *obj);
    160 static void dtlarg_setattr(void *obj);
    161 static void sumarg_setclid(char *buf, size_t buflen, void *obj);
    162 static void dtlarg_setclid(void *obj);
    163 static void sumarg_setclid_cfm(char *buf, size_t buflen, void *obj);
    164 static void dtlarg_setclid_cfm(void *obj);
    165 static void dtlarg_verify(void *obj);
    166 static void sumarg_write(char *buf, size_t buflen, void *obj);
    167 static void dtlarg_write(void *obj);
    168 
    169 static void sumres_cb_getattr(char *buf, size_t buflen, void *obj);
    170 static void dtlres_cb_getattr(void *obj);
    171 
    172 static void sumres_access(char *buf, size_t buflen, void *obj);
    173 static void dtlres_access(void *obj);
    174 static void sumres_close(char *buf, size_t buflen, void *obj);
    175 static void dtlres_close(void *obj);
    176 static void sumres_commit(char *buf, size_t buflen, void *obj);
    177 static void dtlres_commit(void *obj);
    178 static void dtlres_create(void *obj);
    179 static void sumres_getattr(char *buf, size_t buflen, void *obj);
    180 static void dtlres_getattr(void *obj);
    181 static void sumres_getfh(char *buf, size_t buflen, void *obj);
    182 static void dtlres_getfh(void *obj);
    183 static void dtlres_link(void *obj);
    184 static void sumres_lock(char *buf, size_t buflen, void *obj);
    185 static void dtlres_lock(void *obj);
    186 static void sumres_lockt(char *buf, size_t buflen, void *obj);
    187 static void dtlres_lockt(void *obj);
    188 static void sumres_locku(char *buf, size_t buflen, void *obj);
    189 static void dtlres_locku(void *obj);
    190 static void sumres_open(char *buf, size_t buflen, void *obj);
    191 static void dtlres_open(void *obj);
    192 static void sumres_open_confirm(char *buf, size_t buflen, void *obj);
    193 static void dtlres_open_confirm(void *obj);
    194 static void sumres_open_downgrd(char *buf, size_t buflen, void *obj);
    195 static void dtlres_open_downgrd(void *obj);
    196 static void sumres_read(char *buf, size_t buflen, void *obj);
    197 static void dtlres_read(void *obj);
    198 static void sumres_readdir(char *buf, size_t buflen, void *obj);
    199 static void dtlres_readdir(void *obj);
    200 static void sumres_readlnk(char *buf, size_t buflen, void *obj);
    201 static void dtlres_readlnk(void *obj);
    202 static void dtlres_remove(void *obj);
    203 static void dtlres_rename(void *obj);
    204 static void sumres_secinfo(char *buf, size_t buflen, void *obj);
    205 static void dtlres_secinfo(void *obj);
    206 static void sumres_setattr(char *buf, size_t buflen, void *obj);
    207 static void dtlres_setattr(void *obj);
    208 static void sumres_setclid(char *buf, size_t buflen, void *obj);
    209 static void dtlres_setclid(void *obj);
    210 static void sumres_write(char *buf, size_t buflen, void *obj);
    211 static void dtlres_write(void *obj);
    212 static void sum_nfsstat4(char *buf, size_t buflen, void *obj);
    213 static void dtl_nfsstat4(void *obj);
    214 static void nfs4_xdr_skip(int nbytes);
    215 static char *sum_lock_type_name(enum nfs_lock_type4 type);
    216 
    217 /* nfs4.1 operations */
    218 static void sumarg_cb_layoutrecall(char *buf, size_t buflen, void *obj);
    219 static void dtlarg_cb_layoutrecall(void *obj);
    220 static void sumres_cb_layoutrecall(char *buf, size_t buflen, void *obj);
    221 static void dtlres_cb_layoutrecall(void *obj);
    222 static void sumarg_cb_notify(char *buf, size_t buflen, void *obj);
    223 static void dtlarg_cb_notify(void *obj);
    224 static void sumres_cb_notify(char *buf, size_t buflen, void *obj);
    225 static void dtlres_cb_notify(void *obj);
    226 static void sumarg_cb_push_deleg(char *buf, size_t buflen, void *obj);
    227 static void dtlarg_cb_push_deleg(void *obj);
    228 static void sumres_cb_push_deleg(char *buf, size_t buflen, void *obj);
    229 static void dtlres_cb_push_deleg(void *obj);
    230 static void sumarg_cb_recall_any(char *buf, size_t buflen, void *obj);
    231 static void dtlarg_cb_recall_any(void *obj);
    232 static void sumres_cb_recall_any(char *buf, size_t buflen, void *obj);
    233 static void dtlres_cb_recall_any(void *obj);
    234 static void sumarg_cb_recallable_obj_avail(char *buf, size_t buflen, void *obj);
    235 static void dtlarg_cb_recallable_obj_avail(void *obj);
    236 static void sumres_cb_recallable_obj_avail(char *buf, size_t buflen, void *obj);
    237 static void dtlres_cb_recallable_obj_avail(void *obj);
    238 static void sumarg_cb_recall_slot(char *buf, size_t buflen, void *obj);
    239 static void dtlarg_cb_recall_slot(void *obj);
    240 static void sumres_cb_recall_slot(char *buf, size_t buflen, void *obj);
    241 static void dtlres_cb_recall_slot(void *obj);
    242 static void sumarg_cb_sequence(char *buf, size_t buflen, void *obj);
    243 static void dtlarg_cb_sequence(void *obj);
    244 static void sumres_cb_sequence(char *buf, size_t buflen, void *obj);
    245 static void dtlres_cb_sequence(void *obj);
    246 static void sumarg_cb_wants_cancelled(char *buf, size_t buflen, void *obj);
    247 static void dtlarg_cb_wants_cancelled(void *obj);
    248 static void sumres_cb_wants_cancelled(char *buf, size_t buflen, void *obj);
    249 static void dtlres_cb_wants_cancelled(void *obj);
    250 static void sumarg_cb_notify_lock(char *buf, size_t buflen, void *obj);
    251 static void dtlarg_cb_notify_lock(void *obj);
    252 static void sumres_cb_notify_lock(char *buf, size_t buflen, void *obj);
    253 static void dtlres_cb_notify_lock(void *obj);
    254 static void sumarg_cb_notify_deviceid(char *buf, size_t buflen, void *obj);
    255 static void dtlarg_cb_notify_deviceid(void *obj);
    256 
    257 /* nfs4.1 operations */
    258 static void sumarg_backchannel_ctl(char *buf, size_t buflen, void *obj);
    259 static void dtlarg_backchannel_ctl(void *obj);
    260 static void sumarg_bind_conn_to_session(char *buf, size_t buflen, void *obj);
    261 static void dtlarg_bind_conn_to_session(void *obj);
    262 static void sumres_bind_conn_to_session(char *buf, size_t buflen, void *obj);
    263 static void dtlres_bind_conn_to_session(void *obj);
    264 static void sumarg_exchange_id(char *buf, size_t buflen, void *obj);
    265 static void dtlarg_exchange_id(void *obj);
    266 static void sumres_exchange_id(char *buf, size_t buflen, void *obj);
    267 static void dtlres_exchange_id(void *obj);
    268 static void sumarg_create_session(char *buf, size_t buflen, void *obj);
    269 static void sumres_create_session(char *buf, size_t buflen, void *obj);
    270 static void dtlarg_create_session(void *obj);
    271 static void dtlres_create_session(void *obj);
    272 static void sumarg_destroy_session(char *buf, size_t buflen, void *obj);
    273 static void dtlarg_destroy_session(void *obj);
    274 static void sumarg_free_stateid(char *buf, size_t buflen, void *obj);
    275 static void dtlarg_free_stateid(void *obj);
    276 static void sumarg_get_dir_delegation(char *buf, size_t buflen, void *obj);
    277 static void dtlarg_get_dir_delegation(void *obj);
    278 static void sumres_get_dir_delegation(char *buf, size_t buflen, void *obj);
    279 static void dtlres_get_dir_delegation(void *obj);
    280 static void sumarg_getdeviceinfo(char *buf, size_t buflen, void *obj);
    281 static void dtlarg_getdeviceinfo(void *obj);
    282 static void sumres_getdeviceinfo(char *buf, size_t buflen, void *obj);
    283 static void dtlres_getdeviceinfo(void *obj);
    284 static void sumarg_getdevicelist(char *buf, size_t buflen, void *obj);
    285 static void dtlarg_getdevicelist(void *obj);
    286 static void sumres_getdevicelist(char *buf, size_t buflen, void *obj);
    287 static void dtlres_getdevicelist(void *obj);
    288 static void sumarg_layoutcommit(char *buf, size_t buflen, void *obj);
    289 static void dtlarg_layoutcommit(void *obj);
    290 static void sumres_layoutcommit(char *buf, size_t buflen, void *obj);
    291 static void dtlres_layoutcommit(void *obj);
    292 static void sumarg_layoutget(char *buf, size_t buflen, void *obj);
    293 static void dtlarg_layoutget(void *obj);
    294 static void sumres_layoutget(char *buf, size_t buflen, void *obj);
    295 static void dtlres_layoutget(void *obj);
    296 static void sumarg_layoutreturn(char *buf, size_t buflen, void *obj);
    297 static void dtlarg_layoutreturn(void *obj);
    298 static void sumarg_secinfo_no_name(char *buf, size_t buflen, void *obj);
    299 static void dtlarg_secinfo_no_name(void *obj);
    300 static void sumarg_sequence(char *buf, size_t buflen, void *obj);
    301 static void dtlarg_sequence(void *obj);
    302 static void sumres_sequence(char *buf, size_t buflen, void *obj);
    303 static void dtlres_sequence(void *obj);
    304 static void sumarg_set_ssv(char *buf, size_t buflen, void *obj);
    305 static void dtlarg_set_ssv(void *obj);
    306 static void sumres_set_ssv(char *buf, size_t buflen, void *obj);
    307 static void dtlres_set_ssv(void *obj);
    308 static void sumarg_test_stateid(char *buf, size_t buflen, void *obj);
    309 static void dtlarg_test_stateid(void *obj);
    310 static void sumres_test_stateid(char *buf, size_t buflen, void *obj);
    311 static void dtlres_test_stateid(void *obj);
    312 static void sumarg_want_delegation(char *buf, size_t buflen, void *obj);
    313 static void dtlarg_want_delegation(void *obj);
    314 static void sumres_want_delegation(char *buf, size_t buflen, void *obj);
    315 static void dtlres_want_delegation(void *obj);
    316 static void sumarg_destroy_clientid(char *buf, size_t buflen, void *obj);
    317 static void dtlarg_destroy_clientid(void *obj);
    318 static void sumres_destroy_clientid(char *buf, size_t buflen, void *obj);
    319 static void dtlres_destroy_clientid(void *obj);
    320 static void sumarg_reclaim_complete(char *buf, size_t buflen, void *obj);
    321 static void dtlarg_reclaim_complete(void *obj);
    322 static void sumres_reclaim_complete(char *buf, size_t buflen, void *obj);
    323 static void dtlres_reclaim_complete(void *obj);
    324 
    325 static void detail_threshold_hint_bitmap(uint32_t);
    326 
    327 int nfs4_pkt_start;
    328 int nfs4_pkt_len;
    329 int nfs4_skip_bytes;
    330 int nfs4_fragged_rpc;
    331 char *nfs4err_fragrpc = "<Fragmented RPC>";
    332 char *nfs4err_xdrfrag = "<XDR Error or Fragmented RPC>";
    333 
    334 /*
    335  * need a way to enable this if current testcases are parsing snoop
    336  * error text. -- maybe an env var would do as temp workaround until
    337  * testcases changed to grep for new error text.
    338  */
    339 int nfs4_use_old_error_text = 0;
    340 
    341 /*
    342  * Information about each operation that can appear in a compound call.
    343  * The function pointers are to formatting functions for summary arguments
    344  * and results, and detail arguments & results.
    345  */
    346 
    347 typedef struct {
    348 	char	*name;
    349 	void	(*sumarg)(char *, size_t, void *);
    350 	void	(*sumres)(char *, size_t, void *);
    351 	void	(*dtlarg)(void *);
    352 	void	(*dtlres)(void *);
    353 } op_info_t;
    354 
    355 static op_info_t cb_opcode_info[] = {
    356 	{"OP_ZERO",	NULL,	NULL,	NULL,	NULL},	/* 0 */
    357 	{"OP_ONE",	NULL,	NULL,	NULL,	NULL},
    358 	{"OP_TWO",	NULL,	NULL,	NULL,	NULL},  /* minor vers */
    359 	{"CB_GETATTR",
    360 	    sumarg_cb_getattr,	sumres_cb_getattr,
    361 	    dtlarg_cb_getattr,	dtlres_cb_getattr},
    362 	{"CB_RECALL",
    363 	    sumarg_cb_recall,	sum_nfsstat4,
    364 	    dtlarg_cb_recall,	dtl_nfsstat4},
    365 	{"CB_LAYOUTRECALL",				/* 5 */
    366 	    sumarg_cb_layoutrecall,	sumres_cb_layoutrecall,
    367 	    dtlarg_cb_layoutrecall,	dtlres_cb_layoutrecall},
    368 	{"CB_NOTIFY",
    369 	    sumarg_cb_notify,	sumres_cb_notify,
    370 	    dtlarg_cb_notify,	dtlres_cb_notify},
    371 	{"CB_PUSH_DELEG",
    372 	    sumarg_cb_push_deleg,	sumres_cb_push_deleg,
    373 	    dtlarg_cb_push_deleg,	dtlres_cb_push_deleg},
    374 	{"CB_RECALL_ANY",
    375 	    sumarg_cb_recall_any,	sumres_cb_recall_any,
    376 	    dtlarg_cb_recall_any,	dtlres_cb_recall_any},
    377 	{"CB_RECALLABLE_OBJ_AVAIL",
    378 	    sumarg_cb_recallable_obj_avail,
    379 	    sumres_cb_recallable_obj_avail,
    380 	    dtlarg_cb_recallable_obj_avail,
    381 	    dtlres_cb_recallable_obj_avail},
    382 	{"CB_RECALL_SLOT",				/* 10 */
    383 	    sumarg_cb_recall_slot,	sumres_cb_recall_slot,
    384 	    dtlarg_cb_recall_slot,	dtlres_cb_recall_slot},
    385 	{"CB_SEQUENCE",
    386 	    sumarg_cb_sequence,	sumres_cb_sequence,
    387 	    dtlarg_cb_sequence,	dtlres_cb_sequence},
    388 	{"CB_WANTS_CANCELLED",
    389 	    sumarg_cb_wants_cancelled,
    390 	    sumres_cb_wants_cancelled,
    391 	    dtlarg_cb_wants_cancelled,
    392 	    dtlres_cb_wants_cancelled},
    393 	{"CB_NOTIFY_LOCK",
    394 	    sumarg_cb_notify_lock,	sumres_cb_notify_lock,
    395 	    dtlarg_cb_notify_lock,	dtlres_cb_notify_lock},
    396 	{"CB_NOTIFY_DEVICEID",
    397 	    sumarg_cb_notify_deviceid,	sum_nfsstat4,
    398 	    dtlarg_cb_notify_deviceid,	dtl_nfsstat4},
    399 };
    400 static uint_t cb_num_opcodes = sizeof (cb_opcode_info) / sizeof (op_info_t *);
    401 
    402 static op_info_t opcode_info[] = {
    403 	{"OP_ZERO",	NULL,	NULL,	NULL,	NULL},	/* 0 */
    404 	{"OP_ONE",	NULL,	NULL,	NULL,	NULL},
    405 	{"OP_TWO",	NULL,	NULL,	NULL,	NULL},  /* minor vers */
    406 	{"ACCESS",
    407 	sumarg_access,	sumres_access,	dtlarg_access,	dtlres_access},
    408 	{"CLOSE",
    409 	sumarg_close,	sumres_close,	dtlarg_close,	dtlres_close},
    410 	{"COMMIT",
    411 	sumarg_commit,	sumres_commit,	dtlarg_commit,	dtlres_commit},
    412 	{"CREATE",					/* 5 */
    413 	sumarg_create,	sum_nfsstat4,	dtlarg_create,	dtlres_create},
    414 	{"DELEGPURGE",
    415 	sumarg_delprge,	sum_nfsstat4,	dtlarg_delprge,	dtl_nfsstat4},
    416 	{"DELEGRETURN",
    417 	sumarg_delret,	sum_nfsstat4,	dtlarg_delret,	dtl_nfsstat4},
    418 	{"GETATTR",
    419 	sumarg_getattr,	sumres_getattr,	dtlarg_getattr,	dtlres_getattr},
    420 	{"GETFH",
    421 	NULL,		sumres_getfh,	NULL,	dtlres_getfh},
    422 	{"LINK",					/* 10 */
    423 	sumarg_link,	sum_nfsstat4,	dtlarg_link,	dtlres_link},
    424 	{"LOCK",
    425 	sumarg_lock,	sumres_lock,	dtlarg_lock,	dtlres_lock},
    426 	{"LOCKT",
    427 	sumarg_lockt,	sumres_lockt,	dtlarg_lockt,	dtlres_lockt},
    428 	{"LOCKU",
    429 	sumarg_locku,	sumres_locku,	dtlarg_locku,	dtlres_locku},
    430 	{"LOOKUP",
    431 	sumarg_lookup,	sum_nfsstat4,	dtlarg_lookup,	dtl_nfsstat4},
    432 	{"LOOKUPP",					/* 15 */
    433 	NULL,		sum_nfsstat4,	NULL,		dtl_nfsstat4},
    434 	{"NVERIFY",
    435 	NULL,		sum_nfsstat4,	dtlarg_verify,	dtl_nfsstat4},
    436 	{"OPEN",
    437 	sumarg_open,	sumres_open,	dtlarg_open,	dtlres_open},
    438 	{"OPENATTR",
    439 	sumarg_openattr, sum_nfsstat4, dtlarg_openattr, dtl_nfsstat4},
    440 	{"OPEN_CONFIRM",
    441 	sumarg_open_confirm,
    442 	sumres_open_confirm,
    443 	dtlarg_open_confirm,
    444 	dtlres_open_confirm},
    445 	{"OPEN_DOWNGRADE",
    446 	sumarg_open_downgrd,
    447 	sumres_open_downgrd,
    448 	dtlarg_open_downgrd,
    449 	dtlres_open_downgrd},
    450 	{"PUTFH",
    451 	sumarg_putfh,	sum_nfsstat4,	dtlarg_putfh,	dtl_nfsstat4},
    452 	{"PUTPUBFH",					/* 20 */
    453 	NULL,		sum_nfsstat4,	NULL,		dtl_nfsstat4},
    454 	{"PUTROOTFH",
    455 	NULL,		sum_nfsstat4,	NULL,		dtl_nfsstat4},
    456 	{"READ",
    457 	sumarg_read,	sumres_read,	dtlarg_read,	dtlres_read},
    458 	{"READDIR",
    459 	sumarg_readdir,	sumres_readdir,	dtlarg_readdir,	dtlres_readdir},
    460 	{"READLINK",
    461 	NULL,		sumres_readlnk,	NULL,		dtlres_readlnk},
    462 	{"REMOVE",					/* 25 */
    463 	sumarg_compnt,	sum_nfsstat4,	dtlarg_compnt,	dtlres_remove},
    464 	{"RENAME",
    465 	sumarg_rename,	sum_nfsstat4,	dtlarg_rename,	dtlres_rename},
    466 	{"RENEW",
    467 	sumarg_renew,	sum_nfsstat4,	dtlarg_renew,	dtl_nfsstat4},
    468 	{"RESTOREFH",
    469 	NULL,		sum_nfsstat4,	NULL,		dtl_nfsstat4},
    470 	{"SAVEFH",
    471 	NULL,		sum_nfsstat4,	NULL,		dtl_nfsstat4},
    472 	{"SECINFO",					/* 30 */
    473 	sumarg_secinfo,	sumres_secinfo,	dtlarg_secinfo,	dtlres_secinfo},
    474 	{"SETATTR",
    475 	sumarg_setattr,	sumres_setattr,	dtlarg_setattr,	dtlres_setattr},
    476 	{"SETCLIENTID",
    477 	sumarg_setclid,	sumres_setclid,	dtlarg_setclid,	dtlres_setclid},
    478 	{"SETCLIENTID_CONFIRM",
    479 	sumarg_setclid_cfm,
    480 	sum_nfsstat4,
    481 	dtlarg_setclid_cfm,
    482 	dtl_nfsstat4},
    483 	{"VERIFY",
    484 	NULL,		sum_nfsstat4,	dtlarg_verify,	dtl_nfsstat4},
    485 	{"WRITE",
    486 	sumarg_write,	sumres_write,	dtlarg_write,	dtlres_write},
    487 	{"RELEASE_LOCKOWNER",
    488 	sumarg_release_lkown, sum_nfsstat4,
    489 	dtlarg_release_lkown, dtl_nfsstat4},
    490 	/* nfs4.1 operations */
    491 	{"BACKCHANNEL_CTL",				/* 40 */
    492 	sumarg_backchannel_ctl,		sum_nfsstat4,
    493 	dtlarg_backchannel_ctl,		dtl_nfsstat4},
    494 	{"BIND_CONN_TO_SESSION",
    495 	sumarg_bind_conn_to_session,	sumres_bind_conn_to_session,
    496 	dtlarg_bind_conn_to_session,	dtlres_bind_conn_to_session},
    497 	{"EXCHANGE_ID",
    498 	sumarg_exchange_id,		sumres_exchange_id,
    499 	dtlarg_exchange_id,		dtlres_exchange_id},
    500 	{"CREATE_SESSION",
    501 	sumarg_create_session,		sumres_create_session,
    502 	dtlarg_create_session,		dtlres_create_session},
    503 	{"DESTROY_SESSION",
    504 	sumarg_destroy_session,		sum_nfsstat4,
    505 	dtlarg_destroy_session,		dtl_nfsstat4},
    506 	{"FREE_STATEID",				/* 45 */
    507 	sumarg_free_stateid,		sum_nfsstat4,
    508 	dtlarg_free_stateid,		dtl_nfsstat4},
    509 	{"GET_DIR_DELEGATION",
    510 	sumarg_get_dir_delegation,	sumres_get_dir_delegation,
    511 	dtlarg_get_dir_delegation,	dtlres_get_dir_delegation},
    512 	{"GETDEVICEINFO",
    513 	sumarg_getdeviceinfo,		sumres_getdeviceinfo,
    514 	dtlarg_getdeviceinfo,		dtlres_getdeviceinfo},
    515 	{"GETDEVICELIST",
    516 	sumarg_getdevicelist,		sumres_getdevicelist,
    517 	dtlarg_getdevicelist,		dtlres_getdevicelist},
    518 	{"LAYOUTCOMMIT",
    519 	sumarg_layoutcommit,		sumres_layoutcommit,
    520 	dtlarg_layoutcommit,		dtlres_layoutcommit},
    521 	{"LAYOUTGET",					/* 50 */
    522 	sumarg_layoutget,		sumres_layoutget,
    523 	dtlarg_layoutget,		dtlres_layoutget},
    524 	{"LAYOUTRETURN",
    525 	sumarg_layoutreturn,		sum_nfsstat4,
    526 	dtlarg_layoutreturn,		dtl_nfsstat4},
    527 	{"SECINFO_NO_NAME",
    528 	sumarg_secinfo_no_name,		sumres_secinfo,
    529 	dtlarg_secinfo_no_name,		dtlres_secinfo},
    530 	{"SEQUENCE",
    531 	sumarg_sequence,		sumres_sequence,
    532 	dtlarg_sequence,		dtlres_sequence},
    533 	{"SET_SSV",
    534 	sumarg_set_ssv,			sumres_set_ssv,
    535 	dtlarg_set_ssv,			dtlres_set_ssv},
    536 	{"TEST_STATEID",				/* 55 */
    537 	sumarg_test_stateid,		sumres_test_stateid,
    538 	dtlarg_test_stateid,		dtlres_test_stateid},
    539 	{"WANT_DELEGATION",
    540 	sumarg_want_delegation,		sumres_want_delegation,
    541 	dtlarg_want_delegation,		dtlres_want_delegation},
    542 	{"DESTROY_CLIENTID",
    543 	sumarg_destroy_clientid,		sumres_destroy_clientid,
    544 	dtlarg_destroy_clientid,		dtlres_destroy_clientid},
    545 	{"RECLAIM_COMPLETE",
    546 	sumarg_reclaim_complete,		sumres_reclaim_complete,
    547 	dtlarg_reclaim_complete,		dtlres_reclaim_complete},
    548 };
    549 static uint_t num_opcodes = sizeof (opcode_info) / sizeof (op_info_t *);
    550 
    551 
    552 typedef struct {
    553 	char *short_name;		/* for summary output */
    554 	char *long_name;		/* for detail output */
    555 } type_names_t;
    556 
    557 
    558 /*
    559  * Layout Recall types
    560  */
    561 static type_names_t lortype_names[] = {
    562 	{"Type 0",	"Type 0"},
    563 	{"FILE",	"Layout for File handle"},
    564 	{"FSID",	"All layouts for objects in FSID"},
    565 	{"ALL",		"All layouts"},
    566 };
    567 static uint_t num_lortypes = sizeof (lortype_names) / sizeof (type_names_t);
    568 
    569 
    570 /*
    571  * Layout types
    572  */
    573 static type_names_t lotype_names[] = {
    574 	{"Type 0",	"Type 0"},
    575 	{"FILE",	"LAYOUT4_NFSV4_1_FILES"},
    576 	{"OBJ",		"LAYOUT4_OSD2_OBJECTS"},
    577 	{"VOL",		"LAYOUT4_BLOCK_VOLUME"},
    578 };
    579 static uint_t num_lotypes = sizeof (lotype_names) / sizeof (type_names_t);
    580 
    581 /*
    582  * Layout iomodes
    583  */
    584 
    585 static type_names_t iomode_names[] = {
    586 	{"?",		"UNKNOWN"},
    587 	{"READ",	"LAYOUTIOMODE4_READ"},
    588 	{"RW",		"LAYOUTIOMODE4_RW"},
    589 	{"ANY",		"LAYOUTIOMODE4_ANY"},
    590 };
    591 static uint_t num_iomodes = sizeof (iomode_names) / sizeof (type_names_t);
    592 
    593 /*
    594  * Layoutreturn types
    595  */
    596 
    597 static type_names_t lrtype_names[] = {
    598 	{"?",		"UNKNOWN"},
    599 	{"FILE",	"LAYOUTRETURN4_FILE"},
    600 	{"FSID",	"LAYOUTRETURN4_FSID"},
    601 	{"ALL",		"LAYOUTRETURN4_ALL"},
    602 };
    603 static uint_t num_lrtypes = sizeof (lrtype_names) / sizeof (type_names_t);
    604 
    605 /* stripe type */
    606 static type_names_t stripe_names[] = {
    607 	{"?",		"UNKNOWN"},
    608 	{"SPARSE",      "STRIPE4_SPARSE"},
    609 	{"DENSE",       "STRIPE4_DENSE"},
    610 };
    611 static uint_t num_stripes = sizeof (stripe_names) / sizeof (type_names_t);
    612 
    613 /* how the client wants to protect its client */
    614 static type_names_t ps_names[] = {
    615 	{"NONE",	"SP4_NONE"},
    616 	{"MACH_CRED",	"SP4_MACH_CRED"},
    617 	{"SSV",		"SP4_SSV"},
    618 };
    619 static uint_t num_ps = sizeof (ps_names) / sizeof (type_names_t);
    620 
    621 /*
    622  * File types.
    623  */
    624 
    625 typedef type_names_t ftype_names_t;
    626 
    627 static ftype_names_t ftype_names[] = {
    628 	{"Type 0",	"Type 0"},
    629 	{"REG",		"Regular File"},
    630 	{"DIR",		"Directory"},
    631 	{"BLK",		"Block Device"},
    632 	{"CHR",		"Character Device"},
    633 	{"LNK",		"Symbolic Link"},	/* 5 */
    634 	{"SOCK",	"Socket"},
    635 	{"FIFO",	"FIFO"},
    636 	{"ATTRDIR",	"Attribute Directory"},
    637 	{"NAMEDATTR",	"Named Attribute"},
    638 };
    639 static uint_t num_ftypes = sizeof (ftype_names) / sizeof (ftype_names_t);
    640 
    641 typedef type_names_t flag_t;
    642 
    643 static flag_t	open_rflags[] = {
    644 	{"?",	"UNKNOWN"},	/* 0 */
    645 	{"CF",	"CONFIRM"},	/* 1 */
    646 	{"PL",	"POSIX LOCK"},	/* 2 */
    647 	{"?",	"UNKNOWN"},
    648 };
    649 static uint_t num_open_rflags =
    650 	sizeof (open_rflags) / sizeof (ftype_names_t) - 1;
    651 
    652 static char *get_flags(uint_t, ftype_names_t *, uint_t, int, char *);
    653 
    654 #define	sum_open_rflags(flag) \
    655 	get_flags((flag), open_rflags, num_open_rflags, 1, " RF=")
    656 
    657 #define	detail_open_rflags(flag) \
    658 	get_flags((flag), open_rflags, num_open_rflags, 0, NULL)
    659 
    660 static void prt_supported_attrs(XDR *);
    661 static void prt_type(XDR *);
    662 static void prt_fh_expire_type(XDR *);
    663 static void prt_change(XDR *);
    664 static void prt_size(XDR *);
    665 static void prt_link_support(XDR *);
    666 static void prt_symlink_support(XDR *);
    667 static void prt_named_attr(XDR *);
    668 static void prt_fsid(XDR *);
    669 static void prt_unique_handles(XDR *);
    670 static void prt_lease_time(XDR *);
    671 static void prt_rdattr_error(XDR *);
    672 static void prt_acl(XDR *);
    673 static void prt_aclsupport(XDR *);
    674 static void prt_archive(XDR *);
    675 static void prt_cansettime(XDR *);
    676 static void prt_case_insensitive(XDR *);
    677 static void prt_case_preserving(XDR *);
    678 static void prt_chown_restricted(XDR *);
    679 static void prt_filehandle(XDR *);
    680 static void prt_fileid(XDR *);
    681 static void prt_mounted_on_fileid(XDR *);
    682 static void prt_files_avail(XDR *);
    683 static void prt_files_free(XDR *);
    684 static void prt_files_total(XDR *);
    685 static void prt_fs_locations(XDR *);
    686 static void prt_hidden(XDR *);
    687 static void prt_homogeneous(XDR *);
    688 static void prt_maxfilesize(XDR *);
    689 static void prt_maxlink(XDR *);
    690 static void prt_maxname(XDR *);
    691 static void prt_maxread(XDR *);
    692 static void prt_maxwrite(XDR *);
    693 static void prt_mimetype(XDR *);
    694 static void prt_mode(XDR *);
    695 static void prt_no_trunc(XDR *);
    696 static void prt_numlinks(XDR *);
    697 static void prt_owner(XDR *);
    698 static void prt_owner_group(XDR *);
    699 static void prt_quota_avail_hard(XDR *);
    700 static void prt_quota_avail_soft(XDR *);
    701 static void prt_quota_used(XDR *);
    702 static void prt_rawdev(XDR *);
    703 static void prt_space_avail(XDR *);
    704 static void prt_space_free(XDR *);
    705 static void prt_space_total(XDR *);
    706 static void prt_space_used(XDR *);
    707 static void prt_system(XDR *);
    708 static void prt_time_access(XDR *);
    709 static void prt_time_access_set(XDR *);
    710 static void prt_time_backup(XDR *);
    711 static void prt_time_create(XDR *);
    712 static void prt_time_delta(XDR *);
    713 static void prt_time_metadata(XDR *);
    714 static void prt_time_modify(XDR *);
    715 static void prt_time_modify_set(XDR *);
    716 /* nfs4.1 attributes */
    717 static void prt_dir_notif_delay(XDR *);
    718 static void prt_dirent_notif_delay(XDR *);
    719 static void prt_dacl(XDR *);
    720 static void prt_sacl(XDR *);
    721 static void prt_change_policy(XDR *);
    722 static void prt_fs_status(XDR *);
    723 static void prt_fs_layout_type(XDR *);
    724 static void prt_layout_hint(XDR *);
    725 static void prt_layout_type(XDR *);
    726 static void prt_layout_blksize(XDR *);
    727 static void prt_layout_alignment(XDR *);
    728 static void prt_fs_locations_info(XDR *);
    729 static void prt_mdsthreshold(XDR *);
    730 static void prt_retention_get(XDR *);
    731 static void prt_retention_set(XDR *);
    732 static void prt_retentevt_get(XDR *);
    733 static void prt_retentevt_set(XDR *);
    734 static void prt_retention_hold(XDR *);
    735 static void prt_mode_set_masked(XDR *);
    736 static void prt_suppattr_exclcreat(XDR *);
    737 static void prt_fs_charset_cap(XDR *);
    738 
    739 
    740 /*
    741  * Information for attributes.
    742  * name		name of the attribute.
    743  * prt_details	function to XDR decode the attribute and print it.
    744  *
    745  * XXX If this table ever gets extensively changed (including
    746  * reorganization to track changes to the spec), it would probably be a
    747  * good idea to change to a scheme where the table is mechanically
    748  * generated.  Look at $SRC/uts/common/rpcsvc for how this is done in the
    749  * kernel.
    750  */
    751 
    752 typedef struct {
    753 	char	*name;
    754 	void	(*prt_details)(XDR *);
    755 } attr_info_t;
    756 
    757 
    758 #define	TH4_READ_SIZE_MASK	(1 << TH4_READ_SIZE)
    759 #define	TH4_WRITE_SIZE_MASK	(1 << TH4_WRITE_SIZE)
    760 #define	TH4_READ_IOSIZE_MASK	(1 << TH4_READ_IOSIZE)
    761 #define	TH4_WRITE_IOSIZE_MASK	(1 << TH4_WRITE_IOSIZE)
    762 
    763 static attr_info_t attr_info[MAX_ATTRIBUTES] = {
    764 	{"SUPPORTED_ATTRS",	prt_supported_attrs},
    765 	{"TYPE",		prt_type},
    766 	{"FH_EXPIRE_TYPE",	prt_fh_expire_type},
    767 	{"CHANGE",		prt_change},
    768 	{"SIZE",		prt_size},
    769 	{"LINK_SUPPORT",	prt_link_support},	/* 5 */
    770 	{"SYMLINK_SUPPORT",	prt_symlink_support},
    771 	{"NAMED_ATTR",		prt_named_attr},
    772 	{"FSID",		prt_fsid},
    773 	{"UNIQUE_HANDLES",	prt_unique_handles},
    774 	{"LEASE_TIME",		prt_lease_time},	/* 10 */
    775 	{"RDATTR_ERROR",	prt_rdattr_error},
    776 	{"ACL",			prt_acl},
    777 	{"ACLSUPPORT",		prt_aclsupport},
    778 	{"ARCHIVE",		prt_archive},
    779 	{"CANSETTIME",		prt_cansettime},	/* 15 */
    780 	{"CASE_INSENSITIVE",	prt_case_insensitive},
    781 	{"CASE_PRESERVING",	prt_case_preserving},
    782 	{"CHOWN_RESTRICTED",	prt_chown_restricted},
    783 	{"FILEHANDLE",		prt_filehandle},
    784 	{"FILEID",		prt_fileid},		/* 20 */
    785 	{"FILES_AVAIL",		prt_files_avail},
    786 	{"FILES_FREE",		prt_files_free},
    787 	{"FILES_TOTAL",		prt_files_total},
    788 	{"FS_LOCATIONS",	prt_fs_locations},
    789 	{"HIDDEN",		prt_hidden},		/* 25 */
    790 	{"HOMOGENEOUS",		prt_homogeneous},
    791 	{"MAXFILESIZE",		prt_maxfilesize},
    792 	{"MAXLINK",		prt_maxlink},
    793 	{"MAXNAME",		prt_maxname},
    794 	{"MAXREAD",		prt_maxread},		/* 30 */
    795 	{"MAXWRITE",		prt_maxwrite},
    796 	{"MIMETYPE",		prt_mimetype},
    797 	{"MODE",		prt_mode},
    798 	{"NO_TRUNC",		prt_no_trunc},
    799 	{"NUMLINKS",		prt_numlinks},		/* 35 */
    800 	{"OWNER",		prt_owner},
    801 	{"OWNER_GROUP",		prt_owner_group},
    802 	{"QUOTA_AVAIL_HARD",	prt_quota_avail_hard},
    803 	{"QUOTA_AVAIL_SOFT",	prt_quota_avail_soft},
    804 	{"QUOTA_USED",		prt_quota_used},	/* 40 */
    805 	{"RAWDEV",		prt_rawdev},
    806 	{"SPACE_AVAIL",		prt_space_avail},
    807 	{"SPACE_FREE",		prt_space_free},
    808 	{"SPACE_TOTAL",		prt_space_total},
    809 	{"SPACE_USED",		prt_space_used},	/* 45 */
    810 	{"SYSTEM",		prt_system},
    811 	{"TIME_ACCESS",		prt_time_access},
    812 	{"TIME_ACCESS_SET",	prt_time_access_set},
    813 	{"TIME_BACKUP",		prt_time_backup},
    814 	{"TIME_CREATE",		prt_time_create},	/* 50 */
    815 	{"TIME_DELTA",		prt_time_delta},
    816 	{"TIME_METADATA",	prt_time_metadata},
    817 	{"TIME_MODIFY",		prt_time_modify},
    818 	{"TIME_MODIFY_SET",	prt_time_modify_set},
    819 	{"MOUNTED_ON_FILEID",	prt_mounted_on_fileid},	/* 55 */
    820 	/* Attributes supported in nfs4.1 */
    821 	{"DIR_NOTIF_DELAY",	prt_dir_notif_delay},
    822 	{"DIRENT_NOTIF_DELAY",	prt_dirent_notif_delay},
    823 	{"DACL",		prt_dacl},
    824 	{"SACL",		prt_sacl},
    825 	{"CHANGE_POLICY",	prt_change_policy},	/* 60 */
    826 	{"FS_STATUS",		prt_fs_status},
    827 	{"FS_LAYOUT_TYPE",	prt_fs_layout_type},
    828 	{"LAYOUT_HINT",		prt_layout_hint},
    829 	{"LAYOUT_TYPE",		prt_layout_type},
    830 	{"LAYOUT_BLKSIZE",	prt_layout_blksize},	/* 65 */
    831 	{"LAYOUT_ALIGNMENT",	prt_layout_alignment},
    832 	{"FS_LOCATIONS_INFO",	prt_fs_locations_info},
    833 	{"MDSTHRESHOLD",	prt_mdsthreshold},
    834 	{"RETENTION_GET",	prt_retention_get},
    835 	{"RETENTION_SET",	prt_retention_set},	/* 70 */
    836 	{"RETENTEVT_GET",	prt_retentevt_get},
    837 	{"RETENTEVT_SET",	prt_retentevt_set},
    838 	{"RETENTION_HOLD",	prt_retention_hold},
    839 	{"MODE_SET_MASKED",	prt_mode_set_masked},
    840 	{"SUPPATTR_EXCLCREAT",	prt_suppattr_exclcreat}, /* 75 */
    841 	{"FS_CHARSET_CAP",	prt_fs_charset_cap},
    842 };
    843 
    844 extern char *get_sum_line();
    845 
    846 extern jmp_buf xdr_err;
    847 
    848 static void sum_comp4res(char *, char *(*)(void));
    849 static char *sum_compound4args(void);
    850 static char *sum_compound4res(void);
    851 static char *sum_operand(nfs_argop4 *opp);
    852 static char *sum_result(nfs_resop4 *resp);
    853 
    854 static char *sum_cb_compound4args(void);
    855 static char *sum_cb_compound4res(void);
    856 static char *sum_cb_operand(nfs_cb_argop4 *opp);
    857 static char *sum_cb_result(nfs_cb_resop4 *resp);
    858 
    859 static void detail_acetype4(acetype4);
    860 static void detail_uint32_bitmap(uint32_t, char *[], int);
    861 static void detail_aceflag4(aceflag4);
    862 static void detail_acemask4(acemask4);
    863 static void detail_nfs_argop4(void);
    864 static void detail_nfs_resop4(void);
    865 static void detail_cb_argop4(void);
    866 static void detail_cb_resop4(void);
    867 
    868 static char *attr_name(uint_t);
    869 static char *claim_name(enum open_claim_type4 claim_type);
    870 static char *delegation_type_name(enum open_delegation_type4 type);
    871 static char *flavor_name(uint_t flavor);
    872 static char *gss_svc_name(rpc_gss_svc_t svc);
    873 static char *limitby_name(enum limit_by4 limitby);
    874 static char *lock_type_name(enum nfs_lock_type4);
    875 static char *opcode_name(uint_t);
    876 static char *cb_opcode_name(uint_t opnum);
    877 static char *status_name(int);
    878 static char *status_name_compat(int);
    879 static char *status_name_pcol(int);
    880 static char *sum_type_name(nfs_ftype4);
    881 static void sum_access4(char *buf, size_t buflen, uint32_t bits);
    882 static void detail_access4(char *, uint32_t);
    883 static void sum_claim(char *buf, size_t buflen, open_claim4 *claim);
    884 static void detail_claim(open_claim4 *claim);
    885 static void sum_delegation(char *buf, size_t buflen, open_delegation4 *delp);
    886 static void detail_delegation(open_delegation4 *delp);
    887 static void detail_lock_owner(lock_owner4 *owner);
    888 static void detail_open_owner(open_owner4 *owner);
    889 static void sum_openflag(char *bufp, int buflen, openflag4 *flagp);
    890 static char *get_deleg_typestr(open_delegation_type4 dt);
    891 static void detail_openflag(openflag4 *flagp);
    892 static void sum_name(char *buf, size_t buflen, open_claim4 *claim);
    893 static void detail_rpcsec_gss(rpcsec_gss_info *);
    894 static char *sum_space_limit(nfs_space_limit4 *limitp);
    895 static void detail_space_limit(nfs_space_limit4 *limitp);
    896 static char *detail_type_name(nfs_ftype4);
    897 static char *createhow4_name(createhow4 *crtp);
    898 
    899 
    900 static void showxdr_utf8string(char *);
    901 static void sum_pathname4(char *, size_t, pathname4 *);
    902 static void detail_pathname4(pathname4 *pathp);
    903 static void sum_compname4(char *buf, size_t buflen, component4 *comp);
    904 static void detail_compname4(component4 *comp);
    905 
    906 static void detail_fattr4(fattr4 *attrp);
    907 static void detail_attr_bitmap(char *, bitmap4 *, unpkd_attrmap_t *);
    908 static void sum_attr_bitmap(char *buf, size_t buflen, bitmap4 *mapp);
    909 static void detail_fattr4_change(char *msg, fattr4_change chg);
    910 
    911 #define	DONT_CHANGE		0
    912 #define	SET_TO_SERVER_TIME	1
    913 #define	SET_TO_CLIENT_TIME	2
    914 
    915 static stateid4 spec_stateid_0 =
    916 	{0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    917 static stateid4 spec_stateid_1 =
    918 	{0xFFFFFFFF, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
    919 
    920 static char *procnames_short[] = {
    921 	"NULL4",	/*  0 */
    922 	"COMPOUND4"	/*  1 */
    923 };
    924 
    925 static char *procnames_long[] = {
    926 	"Null procedure",		/*  0 */
    927 	"Compound",			/*  1 */
    928 };
    929 
    930 static char *cb_procnames_short[] = {
    931 	"CB_NULL",	/*  0 */
    932 	"CB_COMPOUND"	/*  1 */
    933 };
    934 
    935 static char *cb_procnames_long[] = {
    936 	"Null CallBack procedure",	/*  0 */
    937 	"CallBack compound",		/*  1 */
    938 };
    939 
    940 static char *acetype4_names[] = {
    941 	"ACE4_ACCESS_ALLOWED_ACE_TYPE",
    942 	"ACE4_ACCESS_DENIED_ACE_TYPE",
    943 	"ACE4_SYSTEM_AUDIT_ACE_TYPE",
    944 	"ACE4_SYSTEM_ALARM_ACE_TYPE"
    945 };
    946 #define	ACETYPE4_NAMES_MAX (sizeof (acetype4_names) / sizeof (char *))
    947 
    948 static char *aceflag4_names[] = {
    949 	"ACE4_FILE_INHERIT_ACE",
    950 	"ACE4_DIRECTORY_INHERIT_ACE",
    951 	"ACE4_NO_PROPAGATE_INHERIT_ACE",
    952 	"ACE4_INHERIT_ONLY_ACE",
    953 	"ACE4_SUCCESSFUL_ACCESS_ACE_FLAG",
    954 	"ACE4_FAILED_ACCESS_ACE_FLAG",
    955 	"ACE4_IDENTIFIER_GROUP"
    956 };
    957 #define	ACEFLAG4_NAMES_MAX (sizeof (aceflag4_names) / sizeof (char *))
    958 
    959 static char *acemask4_names[] = {
    960 	"ACE4_READ_DATA/ACE4_LIST_DIRECTORY",
    961 	"ACE4_WRITE_DATA/ACE4_ADD_FILE",
    962 	"ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY",
    963 	"ACE4_READ_NAMED_ATTRS",
    964 	"ACE4_WRITE_NAMED_ATTRS",
    965 	"ACE4_EXECUTE",
    966 	"ACE4_DELETE_CHILD",
    967 	"ACE4_READ_ATTRIBUTES",
    968 	"ACE4_WRITE_ATTRIBUTES",
    969 	"UNDEFINED",	/* 0x00000200 */
    970 	"UNDEFINED",	/* 0x00000400 */
    971 	"UNDEFINED",	/* 0x00000800 */
    972 	"UNDEFINED",	/* 0x00001000 */
    973 	"UNDEFINED",	/* 0x00002000 */
    974 	"UNDEFINED",	/* 0x00004000 */
    975 	"UNDEFINED",	/* 0x00008000 */
    976 	"ACE4_DELETE",
    977 	"ACE4_READ_ACL",
    978 	"ACE4_WRITE_ACL",
    979 	"ACE4_WRITE_OWNER",
    980 	"ACE4_SYNCHRONIZE"
    981 };
    982 #define	ACEMASK4_NAMES_MAX (sizeof (acemask4_names) / sizeof (char *))
    983 
    984 static char *seq_status[] = {
    985 	"SEQ4_STATUS_CB_PATH_DOWN",
    986 	"SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING",
    987 	"SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED",
    988 	"SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED",
    989 	"SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED",
    990 	"SEQ4_STATUS_ADMIN_STATE_REVOKED",
    991 	"SEQ4_STATUS_RECALLABLE_STATE_REVOKED",
    992 	"SEQ4_STATUS_LEASE_MOVED",
    993 	"SEQ4_STATUS_RESTART_RECLAIM_NEEDED"
    994 };
    995 #define	SEQ_STATUS_MAX	(sizeof (seq_status) / sizeof (char *))
    996 
    997 static flag_t   session_flags[] = {
    998 	{"RS",	"PERSIST"},	/* 1: Reliable semantics */
    999 	{"BC",	"BACKCHAN"},	/* 2: conn used for back channel, too */
   1000 	{"DP",	"RDMA"},	/* 3: conn is non-streamed; Begin RDMA */
   1001 	{"?",	"UNKNOWN"}	/* 4: Unknown Flag */
   1002 };
   1003 static uint_t num_session_flags = sizeof (session_flags) / sizeof (flag_t) - 1;
   1004 
   1005 #define	sum_sn_flags(flag) \
   1006 	get_flags((flag), session_flags, num_session_flags, 1, " SF=")
   1007 #define	detail_sn_flags(flag) \
   1008 	get_flags((flag), session_flags, num_session_flags, 0, NULL)
   1009 
   1010 #define	MAXPROC	1
   1011 
   1012 /*ARGSUSED*/
   1013 void
   1014 interpret_nfs4_cb(int flags, int type, int xid, int vers, int proc,
   1015 		char *data, int len)
   1016 {
   1017 	char *line = NULL;
   1018 
   1019 	if (proc < 0 || proc > MAXPROC)
   1020 		return;
   1021 
   1022 	if (flags & F_SUM) {
   1023 		line = get_sum_line();
   1024 
   1025 		if (type == CALL) {
   1026 			(void) sprintf(line, "NFS C %s",
   1027 			    proc == CB_COMPOUND ? "CB4" :
   1028 			    cb_procnames_short[proc]);
   1029 			line += strlen(line);
   1030 
   1031 			if (proc == CB_COMPOUND) {
   1032 				static utf8string tag;
   1033 
   1034 				if (!xdr_utf8string(&xdrm, &tag))
   1035 					longjmp(xdr_err, 1);
   1036 				sprintf(line, " (%.20s) %s",
   1037 				    utf8localize(&tag),
   1038 				    sum_cb_compound4args());
   1039 				xdr_free(xdr_utf8string, (char *)&tag);
   1040 			}
   1041 			check_retransmit(line, xid);
   1042 		} else {
   1043 			(void) sprintf(line, "NFS R %s ",
   1044 			    proc == CB_COMPOUND ? "CB4" :
   1045 			    cb_procnames_short[proc]);
   1046 			line += strlen(line);
   1047 			if (proc == CB_COMPOUND)
   1048 				sum_comp4res(line, sum_cb_compound4res);
   1049 		}
   1050 	}
   1051 
   1052 	if (flags & F_DTAIL) {
   1053 		show_header("NFS:  ", "Sun NFS4 CallBack", len);
   1054 		show_space();
   1055 		(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
   1056 		    proc, cb_procnames_long[proc]);
   1057 		if (proc == CB_COMPOUND) {
   1058 			if (type == CALL) {
   1059 				showxdr_utf8string("Tag = %s");
   1060 				detail_cb_argop4();
   1061 			} else {
   1062 				nfsstat4 status;
   1063 
   1064 				status = getxdr_long();
   1065 				showxdr_utf8string("Tag = %s");
   1066 				sprintf(get_line(0, 0), "Status = %d (%s)",
   1067 				    status, status_name(status));
   1068 				detail_cb_resop4();
   1069 			}
   1070 		}
   1071 		show_trailer();
   1072 	}
   1073 
   1074 	utf8free();			/* cf. utf8localize() */
   1075 }
   1076 
   1077 
   1078 /*ARGSUSED*/
   1079 void
   1080 interpret_nfs4(int flags, int type, int xid, int vers, int proc,
   1081 		char *data, int len)
   1082 {
   1083 	char *line = NULL;
   1084 
   1085 	if (proc < 0 || proc > MAXPROC)
   1086 		return;
   1087 
   1088 	nfs4_fragged_rpc = 0;
   1089 	nfs4_pkt_len = len;
   1090 	nfs4_pkt_start = xdr_getpos(&xdrm);
   1091 
   1092 	if (flags & F_SUM) {
   1093 		line = get_sum_line();
   1094 
   1095 		if (type == CALL) {
   1096 			(void) sprintf(line, "NFS C %s",
   1097 			    proc == NFSPROC4_COMPOUND ? "4" :
   1098 			    procnames_short[proc]);
   1099 			line += strlen(line);
   1100 
   1101 			if (proc == NFSPROC4_COMPOUND) {
   1102 				static utf8string tag;
   1103 
   1104 				if (!xdr_utf8string(&xdrm, &tag))
   1105 					longjmp(xdr_err, 1);
   1106 				sprintf(line, " (%.20s) %s",
   1107 				    utf8localize(&tag),
   1108 				    sum_compound4args());
   1109 				xdr_free(xdr_utf8string, (char *)&tag);
   1110 			}
   1111 			check_retransmit(line, xid);
   1112 		} else {
   1113 			(void) sprintf(line, "NFS R %s ",
   1114 			    proc == NFSPROC4_COMPOUND ? "4" :
   1115 			    procnames_short[proc]);
   1116 			line += strlen(line);
   1117 
   1118 			if (proc == NFSPROC4_COMPOUND)
   1119 				sum_comp4res(line, sum_compound4res);
   1120 		}
   1121 	}
   1122 
   1123 	if (flags & F_DTAIL) {
   1124 		show_header("NFS:  ", "Sun NFS", len);
   1125 		show_space();
   1126 		(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
   1127 		    proc, procnames_long[proc]);
   1128 		if (proc == NFSPROC4_COMPOUND) {
   1129 			if (type == CALL) {
   1130 				showxdr_utf8string("Tag = %s");
   1131 				detail_nfs_argop4();
   1132 			} else {
   1133 				nfsstat4 status;
   1134 
   1135 				status = getxdr_long();
   1136 				showxdr_utf8string("Tag = %s");
   1137 				sprintf(get_line(0, 0), "Status = %d (%s)",
   1138 				    status, status_name(status));
   1139 				detail_nfs_resop4();
   1140 			}
   1141 		}
   1142 		show_trailer();
   1143 	}
   1144 
   1145 	utf8free();			/* cf. utf8localize() */
   1146 }
   1147 
   1148 
   1149 
   1150 /*
   1151  * Return the names and arguments of the oplist elements, up to
   1152  * SUM_COMPND_MAX characters.  If the elements don't fit, include a "..."
   1153  * at the end of the string.
   1154  */
   1155 
   1156 static char *
   1157 sum_compound4args(void)
   1158 {
   1159 	static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
   1160 	int numops;
   1161 	const size_t buflen = sizeof (buf);
   1162 	char *bp;
   1163 	nfs_argop4 one_op;
   1164 	uint32_t minor_version;
   1165 
   1166 	buf[0] = '\0';
   1167 
   1168 	if (setjmp(xdr_err)) {
   1169 		bp = buf + strlen(buf);
   1170 		snprintf(bp, buflen - (bp - buf),
   1171 		    nfs4_fragged_rpc ? nfs4err_fragrpc : nfs4err_xdrfrag);
   1172 		return (buf);
   1173 	}
   1174 
   1175 	/*
   1176 	 * might be nice to print minor version, but doesn't
   1177 	 * seem like very useful info for summary mode
   1178 	 */
   1179 	if (!xdr_uint32_t(&xdrm, &minor_version))
   1180 		longjmp(xdr_err, 1);
   1181 
   1182 	numops = getxdr_long();
   1183 	bp = buf;
   1184 	while (numops-- > 0) {
   1185 		char *operand;
   1186 
   1187 		bzero(&one_op, sizeof (one_op));
   1188 
   1189 		if (!xdr_nfs_argop4(&xdrm, &one_op)) {
   1190 			xdr_free(xdr_nfs_argop4, (char *)&one_op);
   1191 			longjmp(xdr_err, 1);
   1192 		}
   1193 		snprintf(bp, buflen - (bp - buf), "%s ",
   1194 		    opcode_name(one_op.argop));
   1195 		bp += strlen(bp);
   1196 
   1197 		operand = sum_operand(&one_op);
   1198 		if (strlen(operand) > 0) {
   1199 			snprintf(bp, buflen - (bp - buf), "%s ", operand);
   1200 			bp += strlen(bp);
   1201 		}
   1202 
   1203 		/* nfs4_skip_bytes set by xdr_nfs4_argop4 */
   1204 		if (nfs4_skip_bytes != 0)
   1205 			nfs4_xdr_skip(nfs4_skip_bytes);
   1206 
   1207 		xdr_free(xdr_nfs_argop4, (char *)&one_op);
   1208 
   1209 		/* add "..." if past the "end" of the buffer */
   1210 		if (bp - buf > SUM_COMPND_MAX) {
   1211 			strcpy(buf + SUM_COMPND_MAX - strlen("..."),
   1212 			    "...");
   1213 			break;
   1214 		}
   1215 	}
   1216 
   1217 	return (buf);
   1218 }
   1219 
   1220 static void
   1221 nfs4_xdr_skip(int nbytes)
   1222 {
   1223 	int resid, off, len, cur_pos, new_pos;
   1224 
   1225 	len = RNDUP(nbytes);
   1226 	cur_pos = xdr_getpos(&xdrm);
   1227 
   1228 	/*
   1229 	 * Time to skip over the rd/wr data.  If the
   1230 	 * rd/wr data is completely contained in the first
   1231 	 * frag, we must skip over it to process the rest of
   1232 	 * the packet.
   1233 	 *
   1234 	 * nfs4_pkt_start: XDR position of start of NFS4 compound
   1235 	 * nfs4_pkt_len: number of bytes in pkt relative to
   1236 	 *		 nfs4_pkt_start
   1237 	 *
   1238 	 * cur_pos: current XDR position
   1239 	 * off: current XDR position relative to nfs4_pkt_start
   1240 	 * resid: number of unprocessed bytes in current pkt
   1241 	 *	  (relative to cur_pos/off)
   1242 	 *
   1243 	 * If nbytes <= resid, then we must skip over the rd/wr
   1244 	 * bytes so we can read the next op/compound in this
   1245 	 * packet.  Otherwise, set the fragged flag so we can
   1246 	 * display the fragged_rpc message.
   1247 	 */
   1248 	off = cur_pos - nfs4_pkt_start;
   1249 	resid = nfs4_pkt_len - off;
   1250 
   1251 	/*
   1252 	 * set nfs4_fragged_rpc if the requested number of "skip"
   1253 	 * bytes is larger than the bytes remaining in the XDR
   1254 	 * stream/current packet.  The global is reset to 0 at
   1255 	 * start of interpret_nfs4.
   1256 	 */
   1257 	new_pos = cur_pos + ((nfs4_fragged_rpc = len > resid) ? resid : len);
   1258 
   1259 	/* there's nothing to do for error case (if it fails pkt is doomed) */
   1260 	xdr_setpos(&xdrm, new_pos);
   1261 }
   1262 
   1263 
   1264 /*
   1265  * Return the names and arguments of the oplist elements, up to
   1266  * SUM_COMPND_MAX characters.  If the elements don't fit, include a "..."
   1267  * at the end of the string.
   1268  */
   1269 static char *
   1270 sum_cb_compound4args(void)
   1271 {
   1272 	static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
   1273 	int numops;
   1274 	const size_t buflen = sizeof (buf);
   1275 	char *bp;
   1276 	nfs_cb_argop4 one_op;
   1277 	uint32_t minor_version, callback_ident;
   1278 
   1279 	buf[0] = '\0';
   1280 	if (setjmp(xdr_err)) {
   1281 		bp = buf + strlen(buf);
   1282 		snprintf(bp, buflen - (bp - buf), "<XDR Error or Fragmented"
   1283 		    " RPC>");
   1284 		return (buf);
   1285 	}
   1286 
   1287 	/*
   1288 	 * might be nice to print minor version, but doesn't
   1289 	 * seem like very useful info for summary mode
   1290 	 */
   1291 	if (!xdr_uint32_t(&xdrm, &minor_version))
   1292 		longjmp(xdr_err, 1);
   1293 
   1294 	/* print callback_ident */
   1295 	if (!xdr_uint32_t(&xdrm, &callback_ident))
   1296 		longjmp(xdr_err, 1);
   1297 	snprintf(buf, buflen, "CBID=%u ", callback_ident);
   1298 
   1299 	bp = buf + strlen(buf);
   1300 	numops = getxdr_long();
   1301 
   1302 	while (numops-- > 0) {
   1303 		char *operand;
   1304 
   1305 		bzero(&one_op, sizeof (one_op));
   1306 		if (!xdr_nfs_cb_argop4(&xdrm, &one_op)) {
   1307 			xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
   1308 			longjmp(xdr_err, 1);
   1309 		}
   1310 
   1311 		snprintf(bp, buflen - (bp - buf), "%s ",
   1312 		    cb_opcode_name(one_op.argop));
   1313 		bp += strlen(bp);
   1314 		operand = sum_cb_operand(&one_op);
   1315 		if (strlen(operand) > 0) {
   1316 			snprintf(bp, buflen - (bp - buf), "%s ", operand);
   1317 			bp += strlen(bp);
   1318 		}
   1319 
   1320 		xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
   1321 
   1322 		/* add "..." if past the "end" of the buffer */
   1323 		if (bp - buf > SUM_COMPND_MAX) {
   1324 			strcpy(buf + SUM_COMPND_MAX - strlen("..."),
   1325 			    "...");
   1326 			break;
   1327 		}
   1328 	}
   1329 
   1330 	return (buf);
   1331 }
   1332 
   1333 /*
   1334  * Return the summarized argument list for the given nfs_argop4.
   1335  */
   1336 
   1337 static char *
   1338 sum_operand(nfs_argop4 *opp)
   1339 {
   1340 	static char buf[1024];
   1341 	void (*fmtproc)(char *, size_t, void *);
   1342 
   1343 	buf[0] = '\0';
   1344 	if (opp->argop < num_opcodes) {
   1345 		fmtproc = opcode_info[opp->argop].sumarg;
   1346 		if (fmtproc != NULL)
   1347 			fmtproc(buf, sizeof (buf), &opp->nfs_argop4_u);
   1348 	}
   1349 
   1350 	return (buf);
   1351 }
   1352 
   1353 /*
   1354  * Return the summarized argument list for the given nfs_argop4.
   1355  */
   1356 
   1357 static char *
   1358 sum_cb_operand(nfs_cb_argop4 *opp)
   1359 {
   1360 	static char buf[1024];
   1361 	void (*fmtproc)(char *, size_t, void *);
   1362 
   1363 	buf[0] = '\0';
   1364 	if (opp->argop < cb_num_opcodes) {
   1365 		fmtproc = cb_opcode_info[opp->argop].sumarg;
   1366 		if (fmtproc != NULL)
   1367 			fmtproc(buf, sizeof (buf), &opp->nfs_cb_argop4_u);
   1368 	}
   1369 
   1370 	return (buf);
   1371 }
   1372 
   1373 /*
   1374  * Print details about the nfs_argop4 that is next in the XDR stream.
   1375  */
   1376 
   1377 static void
   1378 detail_nfs_argop4(void)
   1379 {
   1380 	int numops;
   1381 	nfs_argop4 one_op;
   1382 	void (*fmtproc)(void *);
   1383 	uint32_t minor_version;
   1384 
   1385 	if (!xdr_uint32_t(&xdrm, &minor_version))
   1386 		longjmp(xdr_err, 1);
   1387 
   1388 	(void) sprintf(get_line(0, 0), "Minor version = %u",
   1389 	    minor_version);
   1390 
   1391 	numops = getxdr_long();
   1392 	(void) sprintf(get_line(0, 0), "Number of operations = %d",
   1393 	    numops);
   1394 
   1395 	while (numops-- > 0) {
   1396 		bzero(&one_op, sizeof (one_op));
   1397 
   1398 		if (!xdr_nfs_argop4(&xdrm, &one_op)) {
   1399 			xdr_free(xdr_nfs_argop4, (char *)&one_op);
   1400 			longjmp(xdr_err, 1);
   1401 		}
   1402 
   1403 		get_line(0, 0);		/* blank line to separate ops */
   1404 		sprintf(get_line(0, 0), "Op = %d (%s)",
   1405 		    one_op.argop, opcode_name(one_op.argop));
   1406 		if (one_op.argop < num_opcodes) {
   1407 			fmtproc = opcode_info[one_op.argop].dtlarg;
   1408 			if (fmtproc != NULL)
   1409 				fmtproc(&one_op.nfs_argop4_u);
   1410 		}
   1411 
   1412 		/* nfs4_skip_bytes set by xdr_nfs_argop4() */
   1413 		if (nfs4_skip_bytes)
   1414 			nfs4_xdr_skip(nfs4_skip_bytes);
   1415 
   1416 		xdr_free(xdr_nfs_argop4, (char *)&one_op);
   1417 	}
   1418 }
   1419 
   1420 
   1421 /*
   1422  * Print details about the nfs_argop4 that is next in the XDR stream.
   1423  */
   1424 static void
   1425 detail_cb_argop4(void)
   1426 {
   1427 	int numops;
   1428 	nfs_cb_argop4 one_op;
   1429 	void (*fmtproc)(void *);
   1430 	uint32_t minor_version, callback_ident;
   1431 
   1432 	if (!xdr_uint32_t(&xdrm, &minor_version))
   1433 		longjmp(xdr_err, 1);
   1434 	(void) sprintf(get_line(0, 0), "Minor version = %u",
   1435 	    minor_version);
   1436 
   1437 	if (!xdr_uint32_t(&xdrm, &callback_ident))
   1438 		longjmp(xdr_err, 1);
   1439 	(void) sprintf(get_line(0, 0), "Callback Ident = %u",
   1440 	    callback_ident);
   1441 
   1442 	numops = getxdr_long();
   1443 	(void) sprintf(get_line(0, 0), "Number of operations = %d",
   1444 	    numops);
   1445 
   1446 	while (numops-- > 0) {
   1447 		bzero(&one_op, sizeof (one_op));
   1448 		if (!xdr_nfs_cb_argop4(&xdrm, &one_op)) {
   1449 			xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
   1450 			longjmp(xdr_err, 1);
   1451 		}
   1452 
   1453 		get_line(0, 0);		/* blank line to separate ops */
   1454 		sprintf(get_line(0, 0), "Op = %d (%s)",
   1455 		    one_op.argop, cb_opcode_name(one_op.argop));
   1456 		if (one_op.argop < cb_num_opcodes) {
   1457 			fmtproc = cb_opcode_info[one_op.argop].dtlarg;
   1458 			if (fmtproc != NULL)
   1459 				fmtproc(&one_op.nfs_cb_argop4_u);
   1460 		}
   1461 
   1462 		xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
   1463 	}
   1464 }
   1465 
   1466 /*
   1467  * component_name: return a printable string for the given component4.  I'm
   1468  * leaving this as a separate function (as opposed to having the callers
   1469  * call utf8localize() directly) in case the definition of component4
   1470  * changes.
   1471  */
   1472 
   1473 static char *
   1474 component_name(component4 *cp)
   1475 {
   1476 	return (utf8localize(cp));
   1477 }
   1478 
   1479 /*
   1480  * linktext_name.  cf. component_name().
   1481  */
   1482 
   1483 static char *
   1484 linktext_name(linktext4 *lp)
   1485 {
   1486 	return (utf8localize(lp));
   1487 }
   1488 
   1489 /*
   1490  * stable_how4_name: return a string for "how".
   1491  */
   1492 
   1493 static char *
   1494 stable_how4_name(stable_how4 how)
   1495 {
   1496 	char *result;
   1497 
   1498 	switch (how) {
   1499 	case UNSTABLE4:
   1500 		result = "ASYNC";
   1501 		break;
   1502 	case DATA_SYNC4:
   1503 		result = "DSYNC";
   1504 		break;
   1505 	case FILE_SYNC4:
   1506 		result = "FSYNC";
   1507 		break;
   1508 	default:
   1509 		result = "?";
   1510 		break;
   1511 	}
   1512 
   1513 	return (result);
   1514 }
   1515 
   1516 /*
   1517  * sum_open_share_access: return a string corresponding to the
   1518  * given OPEN share access bitmask.
   1519  */
   1520 
   1521 static char *
   1522 sum_open_share_access(int32_t mask)
   1523 {
   1524 	char *result;
   1525 
   1526 	switch (mask) {
   1527 	case 0:
   1528 		result = "N";
   1529 		break;
   1530 	case OPEN4_SHARE_ACCESS_READ:
   1531 		result = "R";
   1532 		break;
   1533 	case OPEN4_SHARE_ACCESS_WRITE:
   1534 		result = "W";
   1535 		break;
   1536 	case OPEN4_SHARE_ACCESS_BOTH:
   1537 		result = "RW";
   1538 		break;
   1539 	default:
   1540 		result = "?";
   1541 		break;
   1542 	}
   1543 
   1544 	return (result);
   1545 }
   1546 
   1547 /*
   1548  * sum_open_share_deny: return a string corresponding to the
   1549  * given OPEN share deny bitmask.
   1550  */
   1551 
   1552 static char *
   1553 sum_open_share_deny(int32_t mask)
   1554 {
   1555 	char *result;
   1556 
   1557 	switch (mask) {
   1558 	case OPEN4_SHARE_DENY_NONE:
   1559 		result = "N";
   1560 		break;
   1561 	case OPEN4_SHARE_DENY_READ:
   1562 		result = "R";
   1563 		break;
   1564 	case OPEN4_SHARE_DENY_WRITE:
   1565 		result = "W";
   1566 		break;
   1567 	case OPEN4_SHARE_DENY_BOTH:
   1568 		result = "RW";
   1569 		break;
   1570 	default:
   1571 		result = "?";
   1572 		break;
   1573 	}
   1574 
   1575 	return (result);
   1576 }
   1577 
   1578 static int
   1579 special_stateid(stateid4 *stateid)
   1580 {
   1581 
   1582 	if (! memcmp(stateid, &spec_stateid_0, sizeof (*stateid)))
   1583 		return (0);
   1584 
   1585 	if (! memcmp(stateid, &spec_stateid_1, sizeof (*stateid)))
   1586 		return (1);
   1587 
   1588 	return (-1);
   1589 }
   1590 
   1591 char *
   1592 cmn_sum_stateid(stateid4 *stateid, char *prefix)
   1593 {
   1594 	static char buf[32];
   1595 	int spec;
   1596 
   1597 	if ((spec = special_stateid(stateid)) < 0)
   1598 		snprintf(buf, sizeof (buf), "%s%04X:%u", prefix,
   1599 		    stateid_hash(stateid), stateid->seqid);
   1600 	else
   1601 		snprintf(buf, sizeof (buf), "%s%s", prefix,
   1602 		    spec == 0 ? "SPC0" : (spec == 1 ? "SPC1" : "SPC?"));
   1603 	return (buf);
   1604 }
   1605 
   1606 void
   1607 cmn_detail_stateid(stateid4 *stateid, char *prefix)
   1608 {
   1609 	int spec;
   1610 	char seqstr[32] = {0};
   1611 
   1612 	spec = special_stateid(stateid);
   1613 
   1614 	if (spec < 0)
   1615 		sprintf(get_line(0, 0), "%sState ID hash = %04X",
   1616 		    prefix, stateid_hash(stateid));
   1617 	else
   1618 		sprintf(get_line(0, 0), "%sState ID hash = %s",	prefix,
   1619 		    spec == 0 ? "SPECIAL_0" :
   1620 		    (spec == 1 ? "SPECIAL_1" : "SPECIAL_?"));
   1621 
   1622 	sprintf(get_line(0, 0), "    len = %u    val = %s",
   1623 	    sizeof (stateid->other),
   1624 	    tohex(stateid->other, sizeof (stateid->other)));
   1625 
   1626 	/*
   1627 	 * If spec 0/1 stateid, print seqid in hex; otherwise,
   1628 	 * use decimal.  This makes it more clear how spec stateids
   1629 	 * are constructed [obvious that either all bits are 0, or all
   1630 	 * bits are 1].
   1631 	 */
   1632 	if (spec == -1)
   1633 		sprintf(seqstr, "%d", stateid->seqid);
   1634 	else
   1635 		sprintf(seqstr, "%08X", stateid->seqid);
   1636 
   1637 	sprintf(get_line(0, 0), "    %sState ID Sequence ID = %s",
   1638 	    prefix, seqstr);
   1639 }
   1640 
   1641 static char *
   1642 sum_lock_denied(LOCK4denied *denied)
   1643 {
   1644 	static char buf[64];
   1645 
   1646 	sprintf(buf, "%s %llu %llu LO=%04X",
   1647 	    sum_lock_type_name(denied->locktype),
   1648 	    denied->offset, denied->length,
   1649 	    owner_hash(&denied->owner.owner));
   1650 
   1651 	return (buf);
   1652 }
   1653 
   1654 static void
   1655 detail_lock_denied(LOCK4denied *denied)
   1656 {
   1657 	sprintf(get_line(0, 0), "Type = %s", lock_type_name(denied->locktype));
   1658 	detail_lock_owner(&denied->owner);
   1659 	sprintf(get_line(0, 0), "Offset = %llu", denied->offset);
   1660 	sprintf(get_line(0, 0), "Length = %llu", denied->length);
   1661 }
   1662 
   1663 /*
   1664  * sum_createhow4: return the string name of "how".
   1665  */
   1666 
   1667 static char *
   1668 createhow4_name(createhow4 *crtp)
   1669 {
   1670 	char *result;
   1671 
   1672 	switch (crtp->mode) {
   1673 	case UNCHECKED4:
   1674 		result = "UNCHECKED";
   1675 		break;
   1676 	case GUARDED4:
   1677 		result = "GUARDED";
   1678 		break;
   1679 	case EXCLUSIVE4:
   1680 		result = "EXCLUSIVE";
   1681 		break;
   1682 	default:
   1683 		result = "?";
   1684 		break;
   1685 	}
   1686 
   1687 	return (result);
   1688 }
   1689 
   1690 /*
   1691  * detail_createhow4: print detail information about "how".
   1692  */
   1693 
   1694 static void
   1695 detail_createhow4(createhow4 *crtp)
   1696 {
   1697 	sprintf(get_line(0, 0), "Method = %s",
   1698 	    createhow4_name(crtp));
   1699 
   1700 	switch (crtp->mode) {
   1701 	case UNCHECKED4:
   1702 	case GUARDED4:
   1703 		detail_fattr4(&crtp->createhow4_u.createattrs);
   1704 		break;
   1705 	case EXCLUSIVE4:
   1706 		sprintf(get_line(0, 0), "  Verifier = %s",
   1707 		    tohex(crtp->createhow4_u.createverf,
   1708 		    NFS4_VERIFIER_SIZE));
   1709 		break;
   1710 	}
   1711 }
   1712 
   1713 static void
   1714 detail_createtype4(createtype4 *crtp)
   1715 {
   1716 	sprintf(get_line(0, 0), "Type = %s",
   1717 	    detail_type_name(crtp->type));
   1718 	switch (crtp->type) {
   1719 	case NF4LNK:
   1720 		sprintf(get_line(0, 0), "Linkdata = %s",
   1721 		    utf8localize(&crtp->createtype4_u.linkdata));
   1722 		break;
   1723 	case NF4BLK:
   1724 	case NF4CHR:
   1725 		sprintf(get_line(0, 0), "Specdata1 = %04x Specdata2 = %04x",
   1726 		    crtp->createtype4_u.devdata.specdata1,
   1727 		    crtp->createtype4_u.devdata.specdata2);
   1728 		break;
   1729 	default:
   1730 		break;
   1731 	}
   1732 }
   1733 
   1734 static void
   1735 sumarg_access(char *buf, size_t buflen, void *obj)
   1736 {
   1737 	ACCESS4args *args = (ACCESS4args *)obj;
   1738 
   1739 	sum_access4(buf, buflen, args->access);
   1740 }
   1741 
   1742 static void
   1743 dtlarg_access(void *obj)
   1744 {
   1745 	ACCESS4args *args = (ACCESS4args *)obj;
   1746 
   1747 	detail_access4("Access bits", args->access);
   1748 }
   1749 
   1750 static void
   1751 sumarg_close(char *buf, size_t buflen, void *obj)
   1752 {
   1753 	CLOSE4args *args = (CLOSE4args *)obj;
   1754 
   1755 	snprintf(buf, buflen, "SQ=%u %s",
   1756 	    args->seqid, sum_open_stateid(&args->open_stateid));
   1757 }
   1758 
   1759 static void
   1760 dtlarg_close(void *obj)
   1761 {
   1762 	CLOSE4args *args = (CLOSE4args *)obj;
   1763 
   1764 	detail_open_stateid(&args->open_stateid);
   1765 	sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
   1766 }
   1767 
   1768 static void
   1769 sumarg_commit(char *buf, size_t buflen, void *obj)
   1770 {
   1771 	COMMIT4args *args = (COMMIT4args *)obj;
   1772 
   1773 	snprintf(buf, buflen, "at %llu for %u ", args->offset,
   1774 	    args->count);
   1775 }
   1776 
   1777 static void
   1778 dtlarg_commit(void *obj)
   1779 {
   1780 	COMMIT4args *args = (COMMIT4args *)obj;
   1781 
   1782 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   1783 	sprintf(get_line(0, 0), "Count = %u", args->count);
   1784 }
   1785 
   1786 static void
   1787 sumarg_compnt(char *buf, size_t buflen, void *obj)
   1788 {
   1789 	component4 *comp = (component4 *)obj;
   1790 
   1791 	snprintf(buf, buflen, "%s", component_name(comp));
   1792 }
   1793 
   1794 static void
   1795 dtlarg_compnt(void *obj)
   1796 {
   1797 	component4 *comp = (component4 *)obj;
   1798 
   1799 	sprintf(get_line(0, 0), "Name = %s", component_name(comp));
   1800 }
   1801 
   1802 static void
   1803 sumarg_create(char *buf, size_t buflen, void *obj)
   1804 {
   1805 	CREATE4args *args = (CREATE4args *)obj;
   1806 
   1807 	snprintf(buf, buflen, "%s %s ", component_name(&args->objname),
   1808 	    sum_type_name(args->objtype.type));
   1809 }
   1810 
   1811 static void
   1812 dtlarg_create(void *obj)
   1813 {
   1814 	CREATE4args *args = (CREATE4args *)obj;
   1815 
   1816 	sprintf(get_line(0, 0), "Name = %s", component_name(&args->objname));
   1817 	detail_createtype4(&args->objtype);
   1818 	detail_fattr4(&args->createattrs);
   1819 }
   1820 
   1821 static void
   1822 sumarg_delprge(char *buf, size_t buflen, void *obj)
   1823 {
   1824 	DELEGPURGE4args *args = (DELEGPURGE4args *)obj;
   1825 
   1826 	snprintf(buf, buflen, "%s", sum_clientid(args->clientid));
   1827 }
   1828 
   1829 static void
   1830 dtlarg_delprge(void *obj)
   1831 {
   1832 	DELEGPURGE4args *args = (DELEGPURGE4args *)obj;
   1833 
   1834 	detail_clientid(args->clientid);
   1835 }
   1836 
   1837 static void
   1838 sumarg_delret(char *buf, size_t buflen, void *obj)
   1839 {
   1840 	DELEGRETURN4args *args = (DELEGRETURN4args *)obj;
   1841 
   1842 	snprintf(buf, buflen, "%s", sum_deleg_stateid(&args->deleg_stateid));
   1843 }
   1844 
   1845 static void
   1846 dtlarg_delret(void *obj)
   1847 {
   1848 	DELEGRETURN4args *args = (DELEGRETURN4args *)obj;
   1849 
   1850 	detail_deleg_stateid(&args->deleg_stateid);
   1851 }
   1852 
   1853 static void
   1854 sumarg_getattr(char *buf, size_t buflen, void *obj)
   1855 {
   1856 	GETATTR4args *args = (GETATTR4args *)obj;
   1857 
   1858 	sum_attr_bitmap(buf, buflen, &args->attr_request);
   1859 }
   1860 
   1861 static void
   1862 dtlarg_getattr(void *obj)
   1863 {
   1864 	GETATTR4args *args = (GETATTR4args *)obj;
   1865 
   1866 	detail_attr_bitmap("", &args->attr_request, NULL);
   1867 }
   1868 
   1869 static void
   1870 sumarg_cb_getattr(char *buf, size_t buflen, void *obj)
   1871 {
   1872 	CB_GETATTR4args *args = (CB_GETATTR4args *)obj;
   1873 	char *bp = buf;
   1874 
   1875 	snprintf(bp, buflen, "%s ", sum_fh4(&args->fh));
   1876 	bp += strlen(bp);
   1877 	sum_attr_bitmap(bp, buflen - (bp - buf), &args->attr_request);
   1878 }
   1879 
   1880 static void
   1881 dtlarg_cb_getattr(void *obj)
   1882 {
   1883 	CB_GETATTR4args *args = (CB_GETATTR4args *)obj;
   1884 
   1885 	detail_fh4(&args->fh, "");
   1886 	detail_attr_bitmap("", &args->attr_request, NULL);
   1887 }
   1888 
   1889 static void
   1890 sumarg_cb_recall(char *buf, size_t buflen, void *obj)
   1891 {
   1892 	CB_RECALL4args *args = (CB_RECALL4args *)obj;
   1893 	char *bp = buf;
   1894 
   1895 	snprintf(bp, buflen, "%s %s TR=%s", sum_fh4(&args->fh),
   1896 	    sum_stateid(&args->stateid), args->truncate ? "T" : "F");
   1897 }
   1898 
   1899 static void
   1900 dtlarg_cb_recall(void *obj)
   1901 {
   1902 	CB_RECALL4args *args = (CB_RECALL4args *)obj;
   1903 
   1904 	detail_fh4(&args->fh, "");
   1905 	detail_stateid(&args->stateid);
   1906 	sprintf(get_line(0, 0), "Truncate = %s",
   1907 	    args->truncate ? "True" : "False");
   1908 }
   1909 
   1910 
   1911 /*
   1912  * name openhow seqid claim access deny owner
   1913  */
   1914 static void
   1915 sumarg_open(char *buf, size_t buflen, void *obj)
   1916 {
   1917 	OPEN4args *args = (OPEN4args *)obj;
   1918 	char *bp = buf;
   1919 	int blen = buflen, len;
   1920 
   1921 	sum_name(bp, buflen, &args->claim);
   1922 	bp += (len = strlen(bp));
   1923 	blen -= len;
   1924 
   1925 	sum_openflag(bp, blen, &args->openhow);
   1926 	bp += (len = strlen(bp));
   1927 	blen -= len;
   1928 
   1929 	snprintf(bp, blen, " SQ=%u", args->seqid);
   1930 	bp += (len = strlen(bp));
   1931 	blen -= len;
   1932 
   1933 	sum_claim(bp, blen, &args->claim);
   1934 	bp += (len = strlen(bp));
   1935 	blen -= len;
   1936 
   1937 	snprintf(bp, blen, " AC=%s DN=%s OO=%04X",
   1938 	    sum_open_share_access(args->share_access),
   1939 	    sum_open_share_deny(args->share_deny),
   1940 	    owner_hash(&args->owner.owner));
   1941 }
   1942 
   1943 static void
   1944 dtlarg_open(void *obj)
   1945 {
   1946 	OPEN4args *args = (OPEN4args *)obj;
   1947 
   1948 	detail_claim(&args->claim);
   1949 	detail_openflag(&args->openhow);
   1950 	detail_open_owner(&args->owner);
   1951 	sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
   1952 	sprintf(get_line(0, 0), "Access = 0x%x (%s)",
   1953 	    args->share_access, sum_open_share_access(args->share_access));
   1954 	sprintf(get_line(0, 0), "Deny   = 0x%x (%s)",
   1955 	    args->share_deny, sum_open_share_access(args->share_deny));
   1956 }
   1957 
   1958 static void
   1959 sumarg_openattr(char *buf, size_t buflen, void *obj)
   1960 {
   1961 	OPENATTR4args *args = (OPENATTR4args *)obj;
   1962 
   1963 	snprintf(buf, buflen, "CD=%s",
   1964 	    args->createdir ? "T" : "F");
   1965 }
   1966 
   1967 static void
   1968 dtlarg_openattr(void *obj)
   1969 {
   1970 	OPENATTR4args *args = (OPENATTR4args *)obj;
   1971 
   1972 	sprintf(get_line(0, 0), "CreateDir = %s",
   1973 	    args->createdir ? "True" : "False");
   1974 }
   1975 
   1976 static void
   1977 sumarg_open_confirm(char *buf, size_t buflen, void *obj)
   1978 {
   1979 	char *bp = buf;
   1980 	OPEN_CONFIRM4args *args = (OPEN_CONFIRM4args *)obj;
   1981 
   1982 	snprintf(bp, buflen, "SQ=%u %s", args->seqid,
   1983 	    sum_open_stateid(&args->open_stateid));
   1984 }
   1985 
   1986 static void
   1987 dtlarg_open_confirm(void *obj)
   1988 {
   1989 	OPEN_CONFIRM4args *args = (OPEN_CONFIRM4args *)obj;
   1990 
   1991 	sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
   1992 	detail_open_stateid(&args->open_stateid);
   1993 }
   1994 
   1995 static void
   1996 sumarg_open_downgrd(char *buf, size_t buflen, void *obj)
   1997 {
   1998 	OPEN_DOWNGRADE4args *args = (OPEN_DOWNGRADE4args *)obj;
   1999 
   2000 	snprintf(buf, buflen, "SQ=%u %s AC=%s DN=%s",
   2001 	    args->seqid, sum_open_stateid(&args->open_stateid),
   2002 	    sum_open_share_access(args->share_access),
   2003 	    sum_open_share_deny(args->share_deny));
   2004 }
   2005 
   2006 static void
   2007 dtlarg_open_downgrd(void *obj)
   2008 {
   2009 	OPEN_DOWNGRADE4args *args = (OPEN_DOWNGRADE4args *)obj;
   2010 
   2011 	sprintf(get_line(0, 0), "Open Sequence ID = %u", args->seqid);
   2012 	detail_open_stateid(&args->open_stateid);
   2013 	sprintf(get_line(0, 0), "Access = 0x%x (%s)",
   2014 	    args->share_access, sum_open_share_access(args->share_access));
   2015 	sprintf(get_line(0, 0), "Deny   = 0x%x (%s)",
   2016 	    args->share_deny, sum_open_share_access(args->share_deny));
   2017 }
   2018 
   2019 static void
   2020 sumarg_putfh(char *buf, size_t buflen, void *obj)
   2021 {
   2022 	PUTFH4args *args = (PUTFH4args *)obj;
   2023 
   2024 	snprintf(buf, buflen, "%s", sum_fh4(&args->object));
   2025 }
   2026 
   2027 static void
   2028 dtlarg_putfh(void *obj)
   2029 {
   2030 	PUTFH4args *args = (PUTFH4args *)obj;
   2031 
   2032 	detail_fh4(&args->object, "");
   2033 }
   2034 
   2035 static void
   2036 sumarg_link(char *buf, size_t buflen, void *obj)
   2037 {
   2038 	LINK4args *args = (LINK4args *)obj;
   2039 
   2040 	snprintf(buf, buflen, "%s", component_name(&args->newname));
   2041 }
   2042 
   2043 static void
   2044 dtlarg_link(void *obj)
   2045 {
   2046 	LINK4args *args = (LINK4args *)obj;
   2047 
   2048 	sprintf(get_line(0, 0), "New name = %s",
   2049 	    component_name(&args->newname));
   2050 }
   2051 
   2052 static void
   2053 sum_open_to_lock_owner(char *buf, int buflen, open_to_lock_owner4 *own)
   2054 {
   2055 	snprintf(buf, buflen, " OSQ=%u %s LSQ=%u LO=%04X", own->open_seqid,
   2056 	    sum_open_stateid(&own->open_stateid), own->lock_seqid,
   2057 	    owner_hash(&own->lock_owner.owner));
   2058 }
   2059 
   2060 static void
   2061 sum_exist_lock_owner(char *buf, int buflen, exist_lock_owner4 *own)
   2062 {
   2063 	snprintf(buf, buflen, " LSQ=%u %s", own->lock_seqid,
   2064 	    sum_lock_stateid(&own->lock_stateid));
   2065 }
   2066 
   2067 static void
   2068 sum_locker(char *buf, size_t len, locker4 *lk)
   2069 {
   2070 	if (lk->new_lock_owner == TRUE)
   2071 		sum_open_to_lock_owner(buf, len, &lk->locker4_u.open_owner);
   2072 	else
   2073 		sum_exist_lock_owner(buf, len, &lk->locker4_u.lock_owner);
   2074 }
   2075 
   2076 static char *
   2077 sum_lock_type_name(enum nfs_lock_type4 type)
   2078 {
   2079 	char *result;
   2080 
   2081 	switch (type) {
   2082 	case READ_LT:
   2083 		result = "RD";
   2084 		break;
   2085 	case WRITE_LT:
   2086 		result = "WR";
   2087 		break;
   2088 	case READW_LT:
   2089 		result = "RDW";
   2090 		break;
   2091 	case WRITEW_LT:
   2092 		result = "WRW";
   2093 		break;
   2094 	default:
   2095 		result = "?";
   2096 		break;
   2097 	}
   2098 
   2099 	return (result);
   2100 }
   2101 
   2102 static void
   2103 sumarg_lock(char *buf, size_t buflen, void *obj)
   2104 {
   2105 	LOCK4args *args = (LOCK4args *)obj;
   2106 	char *bp = buf;
   2107 
   2108 	snprintf(buf, buflen, "%s%s%llu:%llu",
   2109 	    sum_lock_type_name(args->locktype),
   2110 	    args->reclaim ? " reclaim " : " ",
   2111 	    args->offset, args->length);
   2112 
   2113 	bp += strlen(buf);
   2114 	sum_locker(bp, buflen - (bp - buf), &args->locker);
   2115 }
   2116 
   2117 static void
   2118 detail_open_to_lock_owner(open_to_lock_owner4 *own)
   2119 {
   2120 	sprintf(get_line(0, 0), "Open Sequence ID = %u", own->open_seqid);
   2121 	detail_open_stateid(&own->open_stateid);
   2122 	sprintf(get_line(0, 0), "Lock Sequence ID = %u", own->lock_seqid);
   2123 	detail_lock_owner(&own->lock_owner);
   2124 }
   2125 
   2126 static void
   2127 detail_exist_lock_owner(exist_lock_owner4 *own)
   2128 {
   2129 	detail_lock_stateid(&own->lock_stateid);
   2130 	sprintf(get_line(0, 0), "Lock Sequence ID = %u", own->lock_seqid);
   2131 }
   2132 
   2133 static void
   2134 detail_locker(locker4 *lk)
   2135 {
   2136 	if (lk->new_lock_owner == TRUE)
   2137 		detail_open_to_lock_owner(&lk->locker4_u.open_owner);
   2138 	else
   2139 		detail_exist_lock_owner(&lk->locker4_u.lock_owner);
   2140 }
   2141 
   2142 static void
   2143 dtlarg_lock(void *obj)
   2144 {
   2145 	LOCK4args *args = (LOCK4args *)obj;
   2146 
   2147 	sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
   2148 	sprintf(get_line(0, 0), "Reclaim = %s",
   2149 	    args->reclaim ? "TRUE" : "FALSE");
   2150 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   2151 	sprintf(get_line(0, 0), "Length = %llu", args->length);
   2152 	detail_locker(&args->locker);
   2153 }
   2154 
   2155 static void
   2156 sumarg_lockt(char *buf, size_t buflen, void *obj)
   2157 {
   2158 	LOCKT4args *args = (LOCKT4args *)obj;
   2159 
   2160 	snprintf(buf, buflen, "R=%llu:%llu",
   2161 	    args->offset, args->length);
   2162 }
   2163 
   2164 static void
   2165 dtlarg_lockt(void *obj)
   2166 {
   2167 	LOCKT4args *args = (LOCKT4args *)obj;
   2168 
   2169 	sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
   2170 	detail_lock_owner(&args->owner);
   2171 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   2172 	sprintf(get_line(0, 0), "Length = %llu", args->length);
   2173 }
   2174 
   2175 static void
   2176 sumarg_locku(char *buf, size_t buflen, void *obj)
   2177 {
   2178 	LOCKU4args *args = (LOCKU4args *)obj;
   2179 
   2180 	snprintf(buf, buflen, "R=%llu:%llu LSQ=%u %s",
   2181 	    args->offset, args->length, args->seqid,
   2182 	    sum_lock_stateid(&args->lock_stateid));
   2183 }
   2184 
   2185 
   2186 static void
   2187 dtlarg_locku(void *obj)
   2188 {
   2189 	LOCKU4args *args = (LOCKU4args *)obj;
   2190 
   2191 	sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
   2192 	sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
   2193 	detail_lock_stateid(&args->lock_stateid);
   2194 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   2195 	sprintf(get_line(0, 0), "Length = %llu", args->length);
   2196 }
   2197 
   2198 static void
   2199 sumarg_lookup(char *buf, size_t buflen, void *obj)
   2200 {
   2201 	LOOKUP4args *args = (LOOKUP4args *)obj;
   2202 
   2203 	sum_compname4(buf, buflen, &args->objname);
   2204 }
   2205 
   2206 static void
   2207 dtlarg_lookup(void *obj)
   2208 {
   2209 	LOOKUP4args *args = (LOOKUP4args *)obj;
   2210 
   2211 	detail_compname4(&args->objname);
   2212 }
   2213 
   2214 static void
   2215 sumarg_read(char *buf, size_t buflen, void *obj)
   2216 {
   2217 	READ4args *args = (READ4args *)obj;
   2218 
   2219 	snprintf(buf, buflen, "%s at %llu for %u",
   2220 	    sum_stateid(&args->stateid), args->offset, args->count);
   2221 }
   2222 
   2223 static void
   2224 dtlarg_read(void *obj)
   2225 {
   2226 	READ4args *args = (READ4args *)obj;
   2227 
   2228 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   2229 	sprintf(get_line(0, 0), "Count = %u", args->count);
   2230 	detail_stateid(&args->stateid);
   2231 }
   2232 
   2233 static void
   2234 sumarg_readdir(char *buf, size_t buflen, void *obj)
   2235 {
   2236 	READDIR4args *args = (READDIR4args *)obj;
   2237 
   2238 	snprintf(buf, buflen, "Cookie=%llu (%s) for %u/%u",
   2239 	    args->cookie, tohex(args->cookieverf, NFS4_VERIFIER_SIZE),
   2240 	    args->dircount, args->maxcount);
   2241 }
   2242 
   2243 static void
   2244 dtlarg_readdir(void *obj)
   2245 {
   2246 	READDIR4args *args = (READDIR4args *)obj;
   2247 
   2248 	sprintf(get_line(0, 0), "Cookie = %llu", args->cookie);
   2249 	sprintf(get_line(0, 0), "Verifier = %s",
   2250 	    tohex(args->cookieverf, NFS4_VERIFIER_SIZE));
   2251 	sprintf(get_line(0, 0), "Dircount = %u", args->dircount);
   2252 	sprintf(get_line(0, 0), "Maxcount = %u", args->maxcount);
   2253 	detail_attr_bitmap("", &args->attr_request, NULL);
   2254 }
   2255 
   2256 static void
   2257 dtlarg_release_lkown(void *obj)
   2258 {
   2259 	RELEASE_LOCKOWNER4args *args = (RELEASE_LOCKOWNER4args *)obj;
   2260 
   2261 	detail_lock_owner(&args->lock_owner);
   2262 }
   2263 
   2264 static void
   2265 sumarg_release_lkown(char *buf, size_t buflen, void *obj)
   2266 
   2267 {
   2268 	RELEASE_LOCKOWNER4args *args = (RELEASE_LOCKOWNER4args *)obj;
   2269 
   2270 	snprintf(buf, buflen, "LO=%04X", owner_hash(&args->lock_owner.owner));
   2271 }
   2272 
   2273 static void
   2274 sumarg_rename(char *buf, size_t buflen, void *obj)
   2275 {
   2276 	RENAME4args *args = (RENAME4args *)obj;
   2277 
   2278 	snprintf(buf, buflen, "%s to %s",
   2279 	    component_name(&args->oldname),
   2280 	    component_name(&args->newname));
   2281 }
   2282 
   2283 static void
   2284 dtlarg_rename(void *obj)
   2285 {
   2286 	RENAME4args *args = (RENAME4args *)obj;
   2287 
   2288 	sprintf(get_line(0, 0), "Old name = %s",
   2289 	    component_name(&args->oldname));
   2290 	sprintf(get_line(0, 0), "New name = %s",
   2291 	    component_name(&args->newname));
   2292 }
   2293 
   2294 static void
   2295 sumarg_renew(char *buf, size_t buflen, void *obj)
   2296 {
   2297 	RENEW4args *args = (RENEW4args *)obj;
   2298 
   2299 	snprintf(buf, buflen, "%s", sum_clientid(args->clientid));
   2300 }
   2301 static void
   2302 dtlarg_renew(void *obj)
   2303 {
   2304 	RENEW4args *args = (RENEW4args *)obj;
   2305 
   2306 	detail_clientid(args->clientid);
   2307 }
   2308 
   2309 static void
   2310 sumarg_secinfo(char *buf, size_t buflen, void *obj)
   2311 {
   2312 	SECINFO4args *args = (SECINFO4args *)obj;
   2313 
   2314 	snprintf(buf, buflen, "%s",
   2315 	    component_name(&args->name));
   2316 }
   2317 
   2318 static void
   2319 dtlarg_secinfo(void *obj)
   2320 {
   2321 	SECINFO4args *args = (SECINFO4args *)obj;
   2322 
   2323 	sprintf(get_line(0, 0), "Name = %s",
   2324 	    component_name(&args->name));
   2325 }
   2326 
   2327 static void
   2328 sumarg_setattr(char *buf, size_t buflen, void *obj)
   2329 {
   2330 	SETATTR4args *args = (SETATTR4args *)obj;
   2331 
   2332 	snprintf(buf, buflen, "%s", sum_stateid(&args->stateid));
   2333 }
   2334 
   2335 static void
   2336 dtlarg_setattr(void *obj)
   2337 {
   2338 	SETATTR4args *args = (SETATTR4args *)obj;
   2339 
   2340 	detail_stateid(&args->stateid);
   2341 	detail_fattr4(&args->obj_attributes);
   2342 }
   2343 
   2344 static void
   2345 sumarg_setclid(char *buf, size_t buflen, void *obj)
   2346 {
   2347 	SETCLIENTID4args *args = (SETCLIENTID4args *)obj;
   2348 
   2349 	snprintf(buf, buflen, "Prog=%u ID=%s Addr=%s CBID=%u",
   2350 	    args->callback.cb_program,
   2351 	    args->callback.cb_location.na_r_netid,
   2352 	    args->callback.cb_location.na_r_addr, args->callback_ident);
   2353 }
   2354 
   2355 static void
   2356 dtlarg_setclid(void *obj)
   2357 {
   2358 	SETCLIENTID4args *args = (SETCLIENTID4args *)obj;
   2359 
   2360 	sprintf(get_line(0, 0), "Verifier=%s",
   2361 	    tohex(args->client.verifier, NFS4_VERIFIER_SIZE));
   2362 	sprintf(get_line(0, 0), "ID = (%d) %s",
   2363 	    args->client.id.id_len,
   2364 	    tohex(args->client.id.id_val, args->client.id.id_len));
   2365 
   2366 	sprintf(get_line(0, 0), "Callback Program = %u",
   2367 	    args->callback.cb_program);
   2368 	sprintf(get_line(0, 0), "Callback Net ID = %s",
   2369 	    args->callback.cb_location.na_r_netid);
   2370 	sprintf(get_line(0, 0), "Callback Addr = %s",
   2371 	    args->callback.cb_location.na_r_addr);
   2372 	sprintf(get_line(0, 0), "Callback Ident = %u", args->callback_ident);
   2373 }
   2374 
   2375 static void
   2376 sumarg_setclid_cfm(char *buf, size_t buflen, void *obj)
   2377 {
   2378 	SETCLIENTID_CONFIRM4args *args = (SETCLIENTID_CONFIRM4args *)obj;
   2379 
   2380 	snprintf(buf, buflen, "%s CFV=%s", sum_clientid(args->clientid),
   2381 	    tohex(args->setclientid_confirm, NFS4_VERIFIER_SIZE));
   2382 }
   2383 
   2384 static void
   2385 dtlarg_setclid_cfm(void *obj)
   2386 {
   2387 	SETCLIENTID_CONFIRM4args *args = (SETCLIENTID_CONFIRM4args *)obj;
   2388 
   2389 	detail_clientid(args->clientid);
   2390 	sprintf(get_line(0, 0), "Set Client ID Confirm Verifier = %s",
   2391 	    tohex(args->setclientid_confirm, NFS4_VERIFIER_SIZE));
   2392 }
   2393 
   2394 
   2395 static void
   2396 dtlarg_verify(void *obj)
   2397 {
   2398 	NVERIFY4args *args = (NVERIFY4args *)obj;
   2399 
   2400 	detail_fattr4(&args->obj_attributes);
   2401 }
   2402 
   2403 static void
   2404 sumarg_write(char *buf, size_t buflen, void *obj)
   2405 {
   2406 	WRITE4args *args = (WRITE4args *)obj;
   2407 
   2408 	snprintf(buf, buflen, "%s at %llu for %u",
   2409 	    sum_stateid(&args->stateid), args->offset, args->data.data_len);
   2410 }
   2411 
   2412 static void
   2413 dtlarg_write(void *obj)
   2414 {
   2415 	WRITE4args *args = (WRITE4args *)obj;
   2416 
   2417 	sprintf(get_line(0, 0), "Offset = %llu", args->offset);
   2418 	sprintf(get_line(0, 0), "Count = %u", args->data.data_len);
   2419 	sprintf(get_line(0, 0), "Stable = %s", stable_how4_name(args->stable));
   2420 	detail_stateid(&args->stateid);
   2421 }
   2422 
   2423 char *
   2424 sum_fh4(nfs_fh4 *fh)
   2425 {
   2426 	static char buf[20];
   2427 
   2428 	sprintf(buf, "FH=%04X", fh4_hash(fh));
   2429 
   2430 	return (buf);
   2431 }
   2432 
   2433 void
   2434 detail_fh4(nfs_fh4 *fh, char *label)
   2435 {
   2436 	int i;
   2437 	uchar_t *cp;
   2438 	char *bufp;
   2439 
   2440 	sprintf(get_line(0, 0), "%sFile handle = [%04X]", label, fh4_hash(fh));
   2441 	bufp = get_line(0, 0);
   2442 	sprintf(bufp, "(%d) ", fh->nfs_fh4_len);
   2443 	bufp += strlen(bufp);
   2444 	/* XXX use tohex()? */
   2445 	for (i = 0, cp = (uchar_t *)fh->nfs_fh4_val;
   2446 	    i < fh->nfs_fh4_len;
   2447 	    i++, cp++) {
   2448 		if (i != 0 && i % 32 == 0)
   2449 			bufp = get_line(0, 0);
   2450 		sprintf(bufp, "%02x", *cp);
   2451 		bufp += strlen(bufp);
   2452 	}
   2453 }
   2454 
   2455 static void
   2456 detail_fattr4(fattr4 *attrp)
   2457 {
   2458 	unpkd_attrmap_t provided;
   2459 	uint_t attrnum;
   2460 	XDR attrxdr;
   2461 	jmp_buf old_errbuf;
   2462 
   2463 	xdrmem_create(&attrxdr, attrp->attr_vals.attrlist4_val,
   2464 	    attrp->attr_vals.attrlist4_len, XDR_DECODE);
   2465 
   2466 	bcopy(xdr_err, old_errbuf, sizeof (old_errbuf));
   2467 	if (setjmp(xdr_err)) {
   2468 		sprintf(get_line(0, 0), "<attr_vals too short>");
   2469 		goto done;
   2470 	}
   2471 
   2472 	detail_attr_bitmap("", &attrp->attrmask, &provided);
   2473 	for (attrnum = 0; attrnum < MAX_ATTRIBUTES; attrnum++) {
   2474 		if (provided.map[attrnum]) {
   2475 			attr_info[attrnum].prt_details(&attrxdr);
   2476 		}
   2477 	}
   2478 
   2479 done:
   2480 	bcopy(old_errbuf, xdr_err, sizeof (old_errbuf));
   2481 }
   2482 
   2483 static void
   2484 detail_threshold_item4(threshold_item4 *thi)
   2485 {
   2486 	XDR txdr;
   2487 	jmp_buf old_errbuf;
   2488 	uint32_t b, val;
   2489 
   2490 	sprintf(get_line(0, 0), "    %s",
   2491 	    detail_lotype_name(thi->thi_layout_type));
   2492 
   2493 	if (thi->thi_hintset.bitmap4_len == 0)
   2494 		return;
   2495 
   2496 	b = ((uint32_t *)(thi->thi_hintset.bitmap4_val))[0];
   2497 	sprintf(get_line(0, 0), "      Threshold hint bitmap = 0x%08x", b);
   2498 
   2499 	xdrmem_create(&txdr, thi->thi_hintlist.thi_hintlist_val,
   2500 	    thi->thi_hintlist.thi_hintlist_len, XDR_DECODE);
   2501 
   2502 	bcopy(xdr_err, old_errbuf, sizeof (old_errbuf));
   2503 	if (setjmp(xdr_err)) {
   2504 		sprintf(get_line(0, 0), "<attr_vals too short>");
   2505 		goto done;
   2506 	}
   2507 
   2508 	if (b & TH4_READ_SIZE_MASK) {
   2509 		if (!xdr_uint32_t(&txdr, &val))
   2510 			longjmp(xdr_err, 1);
   2511 		sprintf(get_line(0, 0), "        Read size = %u", val);
   2512 	}
   2513 	if (b & TH4_READ_IOSIZE_MASK) {
   2514 		if (!xdr_uint32_t(&txdr, &val))
   2515 			longjmp(xdr_err, 1);
   2516 		sprintf(get_line(0, 0), "        Read IO size = %u", val);
   2517 	}
   2518 	if (b & TH4_WRITE_SIZE_MASK) {
   2519 		if (!xdr_uint32_t(&txdr, &val))
   2520 			longjmp(xdr_err, 1);
   2521 		sprintf(get_line(0, 0), "        Write size = %u", val);
   2522 	}
   2523 	if (b & TH4_WRITE_IOSIZE_MASK) {
   2524 		if (!xdr_uint32_t(&txdr, &val))
   2525 			longjmp(xdr_err, 1);
   2526 		sprintf(get_line(0, 0), "        Write IO size = %u", val);
   2527 	}
   2528 done:
   2529 	bcopy(old_errbuf, xdr_err, sizeof (old_errbuf));
   2530 }
   2531 
   2532 static void
   2533 sum_attr_bitmap(char *buf, size_t buflen, bitmap4 *mapp)
   2534 {
   2535 	uint_t num_words;
   2536 	char *bp;
   2537 	size_t curlen, remaining;
   2538 
   2539 	buf[0] = '\0';
   2540 	for (num_words = 0; num_words < mapp->bitmap4_len; num_words++) {
   2541 		curlen = strlen(buf);
   2542 		if (curlen + sizeof ("<Too Long>") >= buflen) {
   2543 			strcpy(buf + buflen - sizeof ("<Too Long>"),
   2544 			    "<Too Long>");
   2545 			return;
   2546 		}
   2547 		bp = buf + curlen;
   2548 		remaining = buflen - curlen;
   2549 		snprintf(bp, remaining,
   2550 		    num_words == 0 ? "%x" : " %x",
   2551 		    mapp->bitmap4_val[num_words]);
   2552 	}
   2553 }
   2554 
   2555 /*
   2556  * Print detail information for the given attribute bitmap, and fill in the
   2557  * unpacked version of the map if "unpacked" is non-null.  Returns the
   2558  * number of bytes in the bitmap.  "prefix" is an initial string that is
   2559  * printed at the front of each line.
   2560  */
   2561 
   2562 static void
   2563 detail_attr_bitmap(char *prefix, bitmap4 *bitp, unpkd_attrmap_t *unpacked)
   2564 {
   2565 	uint_t num_words;
   2566 	uint32_t *wp;
   2567 	uint_t byte_num;
   2568 
   2569 	if (unpacked != NULL)
   2570 		memset(unpacked, 0, sizeof (unpkd_attrmap_t));
   2571 
   2572 	/*
   2573 	 * Break the bitmap into octets, then print in hex and
   2574 	 * symbolically.
   2575 	 */
   2576 
   2577 	for (num_words = 0, wp = bitp->bitmap4_val;
   2578 	    num_words < bitp->bitmap4_len;
   2579 	    num_words++, wp++) {
   2580 		for (byte_num = 0; byte_num < 4; byte_num++) {
   2581 			uchar_t val = (*wp) >> (byte_num * 8);
   2582 			char *buf = get_line(0, 0);
   2583 			uint_t attrnum;
   2584 			int bit;
   2585 
   2586 			sprintf(buf, "%s  0x%02x  ", prefix, val);
   2587 			attrnum = num_words * 32 + byte_num * 8;
   2588 			for (bit = 7; bit >= 0; bit--) {
   2589 				if (val & (1 << bit)) {
   2590 					strcat(buf, " ");
   2591 					strcat(buf,
   2592 					    attr_name(attrnum + bit));
   2593 					if (unpacked != NULL)
   2594 						unpacked->map[attrnum + bit] =
   2595 						    1;
   2596 				}
   2597 			}
   2598 		}
   2599 	}
   2600 }
   2601 
   2602 /*
   2603  * Format the summary line results from a COMPOUND4 call.
   2604  */
   2605 
   2606 static void
   2607 sum_comp4res(char *line, char *(*sumres_fn)(void))
   2608 {
   2609 	nfsstat4 status;
   2610 	static utf8string tag;
   2611 
   2612 	status = getxdr_long();
   2613 	if (!xdr_utf8string(&xdrm, &tag))
   2614 		longjmp(xdr_err, 1);
   2615 
   2616 	sprintf(line, "(%.20s) %s %s", utf8localize(&tag),
   2617 	    status_name(status), sumres_fn());
   2618 
   2619 	xdr_free(xdr_utf8string, (char *)&tag);
   2620 }
   2621 
   2622 
   2623 /*
   2624  * Return a set of summary strings for the result data that's next in the
   2625  * XDR stream, up to SUM_COMPND_MAX characters.  If the strings don't fit,
   2626  * include a "..." at the end of the string.
   2627  */
   2628 
   2629 static char *
   2630 sum_compound4res(void)
   2631 {
   2632 	static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
   2633 	int numres;
   2634 	const size_t buflen = sizeof (buf);
   2635 	char *bp;
   2636 	nfs_resop4 one_res;
   2637 
   2638 	buf[0] = '\0';
   2639 	if (setjmp(xdr_err)) {
   2640 		bp = buf + strlen(buf);
   2641 		snprintf(bp, buflen - (bp - buf),
   2642 		    nfs4_fragged_rpc ? nfs4err_fragrpc : nfs4err_xdrfrag);
   2643 		return (buf);
   2644 	}
   2645 
   2646 	numres = getxdr_long();
   2647 	bp = buf;
   2648 	while (numres-- > 0) {
   2649 		char *result;
   2650 
   2651 		bzero(&one_res, sizeof (one_res));
   2652 
   2653 		if (!xdr_nfs_resop4(&xdrm, &one_res)) {
   2654 			xdr_free(xdr_nfs_resop4, (char *)&one_res);
   2655 			longjmp(xdr_err, 1);
   2656 		}
   2657 
   2658 		snprintf(bp, buflen - (bp - buf), "%s ",
   2659 		    opcode_name(one_res.resop));
   2660 		bp += strlen(bp);
   2661 
   2662 		result = sum_result(&one_res);
   2663 		if (strlen(result) > 0) {
   2664 			snprintf(bp, buflen - (bp - buf), "%s ", result);
   2665 			bp += strlen(bp);
   2666 		}
   2667 
   2668 		/* nfs4_skip_bytes set by xdr_nfs4_argop4() */
   2669 		if (nfs4_skip_bytes != 0)
   2670 			nfs4_xdr_skip(nfs4_skip_bytes);
   2671 
   2672 		xdr_free(xdr_nfs_resop4, (char *)&one_res);
   2673 		/* add "..." if past the "end" of the buffer */
   2674 		if (bp - buf > SUM_COMPND_MAX) {
   2675 			strcpy(buf + SUM_COMPND_MAX - strlen("..."),
   2676 			    "...");
   2677 			break;
   2678 		}
   2679 	}
   2680 
   2681 	return (buf);
   2682 }
   2683 
   2684 
   2685 /*
   2686  * Return a set of summary strings for the result data that's next in the
   2687  * XDR stream, up to SUM_COMPND_MAX characters.  If the strings don't fit,
   2688  * include a "..." at the end of the string.
   2689  */
   2690 
   2691 static char *
   2692 sum_cb_compound4res(void)
   2693 {
   2694 	static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
   2695 	int numres;
   2696 	const size_t buflen = sizeof (buf);
   2697 	char *bp;
   2698 	nfs_cb_resop4 one_res;
   2699 
   2700 	buf[0] = '\0';
   2701 	if (setjmp(xdr_err)) {
   2702 		bp = buf + strlen(buf);
   2703 		snprintf(bp, buflen - (bp - buf), "<XDR Error or Fragmented"
   2704 		    " RPC>");
   2705 		return (buf);
   2706 	}
   2707 
   2708 	numres = getxdr_long();
   2709 	bp = buf;
   2710 	while (numres-- > 0) {
   2711 		bzero(&one_res, sizeof (one_res));
   2712 		if (!xdr_nfs_cb_resop4(&xdrm, &one_res)) {
   2713 			xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
   2714 			longjmp(xdr_err, 1);
   2715 		}
   2716 		snprintf(bp, buflen - (bp - buf), "%s %s ",
   2717 		    cb_opcode_name(one_res.resop),
   2718 		    sum_cb_result(&one_res));
   2719 		bp += strlen(bp);
   2720 
   2721 		xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
   2722 
   2723 		/* add "..." if past the "end" of the buffer */
   2724 		if (bp - buf > SUM_COMPND_MAX) {
   2725 			strcpy(buf + SUM_COMPND_MAX - strlen("..."),
   2726 			    "...");
   2727 			break;
   2728 		}
   2729 	}
   2730 
   2731 	return (buf);
   2732 }
   2733 
   2734 
   2735 /*
   2736  * Return the summarized results for the given resultdata.
   2737  */
   2738 
   2739 static char *
   2740 sum_result(nfs_resop4 *resp)
   2741 {
   2742 	static char buf[1024];
   2743 	void (*fmtproc)(char *, size_t, void *);
   2744 
   2745 	buf[0] = '\0';
   2746 	if (resp->resop < num_opcodes)
   2747 		fmtproc = opcode_info[resp->resop].sumres;
   2748 	else if (resp->resop == OP_ILLEGAL)
   2749 		fmtproc = sum_nfsstat4;
   2750 	else
   2751 		fmtproc = NULL;
   2752 
   2753 	if (fmtproc != NULL)
   2754 		fmtproc(buf, sizeof (buf), &resp->nfs_resop4_u);
   2755 
   2756 	return (buf);
   2757 }
   2758 
   2759 /*
   2760  * Return the summarized results for the given resultdata.
   2761  */
   2762 
   2763 static char *
   2764 sum_cb_result(nfs_cb_resop4 *resp)
   2765 {
   2766 	static char buf[1024];
   2767 	void (*fmtproc)(char *, size_t, void *);
   2768 
   2769 	buf[0] = '\0';
   2770 	if (resp->resop < cb_num_opcodes)
   2771 		fmtproc = cb_opcode_info[resp->resop].sumres;
   2772 	else if (resp->resop == OP_CB_ILLEGAL)
   2773 		fmtproc = sum_nfsstat4;
   2774 	else
   2775 		fmtproc = NULL;
   2776 
   2777 	if (fmtproc != NULL)
   2778 		fmtproc(buf, sizeof (buf), &resp->nfs_cb_resop4_u);
   2779 
   2780 	return (buf);
   2781 }
   2782 
   2783 
   2784 static void
   2785 dtl_change_info(char *msg, change_info4 *infop)
   2786 {
   2787 	sprintf(get_line(0, 0), "%s:", msg);
   2788 	sprintf(get_line(0, 0), "  Atomic = %s",
   2789 	    infop->atomic ? "TRUE" : "FALSE");
   2790 	detail_fattr4_change("  Before", infop->before);
   2791 	detail_fattr4_change("  After", infop->after);
   2792 }
   2793 
   2794 static void
   2795 detail_fattr4_change(char *msg, fattr4_change chg)
   2796 {
   2797 	sprintf(get_line(0, 0), "%s: 0x%llx", msg, chg);
   2798 	/* XXX print as time_t, too? */
   2799 }
   2800 
   2801 static void
   2802 sum_nfsstat4(char *buf, size_t buflen, void *obj)
   2803 {
   2804 	nfsstat4 status = *(nfsstat4 *)obj;
   2805 
   2806 	strncpy(buf, status_name(status), buflen);
   2807 }
   2808 
   2809 static void
   2810 dtl_nfsstat4(void *obj)
   2811 {
   2812 	nfsstat4 status = *(nfsstat4 *)obj;
   2813 
   2814 	sprintf(get_line(0, 0), "Status = %d (%s)", status,
   2815 	    status_name(status));
   2816 }
   2817 
   2818 static void
   2819 sumres_access(char *buf, size_t buflen, void *obj)
   2820 {
   2821 	ACCESS4res *res = (ACCESS4res *)obj;
   2822 	char *bp = buf;
   2823 	int len, blen = buflen;
   2824 
   2825 	strcpy(bp, status_name(res->status));
   2826 	if (res->status == NFS4_OK) {
   2827 		bp += (len = strlen(bp));
   2828 		blen -= len;
   2829 
   2830 		snprintf(bp, blen, " Supp=");
   2831 		bp += (len = strlen(bp));
   2832 		blen -= len;
   2833 
   2834 		sum_access4(bp, blen, res->ACCESS4res_u.resok4.supported);
   2835 		bp += (len = strlen(bp));
   2836 		blen -= len;
   2837 
   2838 		snprintf(bp, blen, " Allow=");
   2839 		bp += (len = strlen(bp));
   2840 		blen -= len;
   2841 
   2842 		sum_access4(bp, blen, res->ACCESS4res_u.resok4.access);
   2843 	}
   2844 }
   2845 
   2846 static void
   2847 dtlres_access(void *obj)
   2848 {
   2849 	ACCESS4res *res = (ACCESS4res *)obj;
   2850 
   2851 	dtl_nfsstat4(obj);
   2852 	if (res->status == NFS4_OK) {
   2853 		detail_access4("Supported Attributes",
   2854 		    res->ACCESS4res_u.resok4.supported);
   2855 		detail_access4("Allowed Attributes",
   2856 		    res->ACCESS4res_u.resok4.access);
   2857 	}
   2858 }
   2859 
   2860 static void
   2861 sumres_close(char *buf, size_t buflen, void *obj)
   2862 {
   2863 	CLOSE4res *res = (CLOSE4res *)obj;
   2864 
   2865 	if (res->status == NFS4_OK)
   2866 		snprintf(buf, buflen, "%s",
   2867 		    sum_open_stateid(&res->CLOSE4res_u.open_stateid));
   2868 }
   2869 
   2870 static void
   2871 dtlres_close(void *obj)
   2872 {
   2873 	CLOSE4res *res = (CLOSE4res *)obj;
   2874 
   2875 	dtl_nfsstat4(obj);
   2876 	if (res->status == NFS4_OK) {
   2877 		detail_open_stateid(&res->CLOSE4res_u.open_stateid);
   2878 	}
   2879 }
   2880 
   2881 static void
   2882 sumres_commit(char *buf, size_t buflen, void *obj)
   2883 {
   2884 	COMMIT4res *res = (COMMIT4res *)obj;
   2885 
   2886 	if (res->status == NFS4_OK)
   2887 		snprintf(buf, buflen, "Verf=%s",
   2888 		    tohex(res->COMMIT4res_u.resok4.writeverf,
   2889 		    NFS4_VERIFIER_SIZE));
   2890 }
   2891 
   2892 static void
   2893 dtlres_commit(void *obj)
   2894 {
   2895 	COMMIT4res *res = (COMMIT4res *)obj;
   2896 
   2897 	dtl_nfsstat4(obj);
   2898 	if (res->status == NFS4_OK) {
   2899 		sprintf(get_line(0, 0), "Verifier = %s",
   2900 		    tohex(res->COMMIT4res_u.resok4.writeverf,
   2901 		    NFS4_VERIFIER_SIZE));
   2902 	}
   2903 }
   2904 
   2905 static void
   2906 dtlres_create(void *obj)
   2907 {
   2908 	CREATE4res *res = (CREATE4res *)obj;
   2909 
   2910 	dtl_nfsstat4(obj);
   2911 	if (res->status == NFS4_OK) {
   2912 		dtl_change_info("Change Information",
   2913 		    &res->CREATE4res_u.resok4.cinfo);
   2914 		detail_attr_bitmap("", &res->CREATE4res_u.resok4.attrset,
   2915 		    NULL);
   2916 	}
   2917 }
   2918 
   2919 static void
   2920 sumres_getattr(char *buf, size_t buflen, void *obj)
   2921 {
   2922 	GETATTR4res *res = (GETATTR4res *)obj;
   2923 
   2924 	strncpy(buf, status_name(res->status), buflen);
   2925 }
   2926 
   2927 static void
   2928 dtlres_getattr(void *obj)
   2929 {
   2930 	GETATTR4res *res = (GETATTR4res *)obj;
   2931 
   2932 	dtl_nfsstat4(obj);
   2933 	if (res->status == NFS4_OK) {
   2934 		detail_fattr4(&res->GETATTR4res_u.resok4.obj_attributes);
   2935 	}
   2936 }
   2937 
   2938 static void
   2939 sumres_cb_getattr(char *buf, size_t buflen, void *obj)
   2940 {
   2941 	CB_GETATTR4res *res = (CB_GETATTR4res *)obj;
   2942 
   2943 	strncpy(buf, status_name(res->status), buflen);
   2944 }
   2945 
   2946 static void
   2947 dtlres_cb_getattr(void *obj)
   2948 {
   2949 	CB_GETATTR4res *res = (CB_GETATTR4res *)obj;
   2950 
   2951 	dtl_nfsstat4(obj);
   2952 	if (res->status == NFS4_OK) {
   2953 		detail_fattr4(&res->CB_GETATTR4res_u.resok4.obj_attributes);
   2954 	}
   2955 }
   2956 
   2957 
   2958 static void
   2959 sumres_getfh(char *buf, size_t buflen, void *obj)
   2960 {
   2961 	char *bp;
   2962 	GETFH4res *res = (GETFH4res *)obj;
   2963 
   2964 	strncpy(buf, status_name(res->status), buflen);
   2965 	if (res->status == NFS4_OK) {
   2966 		bp = buf + strlen(buf);
   2967 		snprintf(bp, buflen - (bp - buf), " %s",
   2968 		    sum_fh4(&res->GETFH4res_u.resok4.object));
   2969 	}
   2970 }
   2971 
   2972 static void
   2973 dtlres_getfh(void *obj)
   2974 {
   2975 	GETFH4res *res = (GETFH4res *)obj;
   2976 
   2977 	dtl_nfsstat4(obj);
   2978 	if (res->status == NFS4_OK) {
   2979 		detail_fh4(&res->GETFH4res_u.resok4.object, "");
   2980 	}
   2981 }
   2982 
   2983 static void
   2984 dtlres_link(void *obj)
   2985 {
   2986 	LINK4res *res = (LINK4res *)obj;
   2987 
   2988 	dtl_nfsstat4(obj);
   2989 	if (res->status == NFS4_OK) {
   2990 		dtl_change_info("Change Information",
   2991 		    &res->LINK4res_u.resok4.cinfo);
   2992 	}
   2993 }
   2994 
   2995 static void
   2996 sumres_lock(char *buf, size_t buflen, void *obj)
   2997 {
   2998 	char *bp;
   2999 	LOCK4res *res = (LOCK4res *)obj;
   3000 
   3001 	strncpy(buf, status_name(res->status), buflen);
   3002 	if (res->status == NFS4_OK) {
   3003 		bp = buf + strlen(buf);
   3004 		snprintf(bp, buflen - (bp - buf), " %s",
   3005 		    sum_lock_stateid(&res->LOCK4res_u.resok4.lock_stateid));
   3006 	}
   3007 	if (res->status == NFS4ERR_DENIED) {
   3008 		bp = buf + strlen(buf);
   3009 		snprintf(bp, buflen - (bp - buf), " %s",
   3010 		    sum_lock_denied(&res->LOCK4res_u.denied));
   3011 	}
   3012 }
   3013 
   3014 static void
   3015 dtlres_lock(void *obj)
   3016 {
   3017 	LOCK4res *res = (LOCK4res *)obj;
   3018 
   3019 	dtl_nfsstat4(obj);
   3020 	if (res->status == NFS4_OK) {
   3021 		detail_lock_stateid(&res->LOCK4res_u.resok4.lock_stateid);
   3022 	}
   3023 	if (res->status == NFS4ERR_DENIED) {
   3024 		detail_lock_denied(&res->LOCK4res_u.denied);
   3025 	}
   3026 }
   3027 
   3028 static void
   3029 sumres_lockt(char *buf, size_t buflen, void *obj)
   3030 {
   3031 	char *bp;
   3032 	LOCKT4res *res = (LOCKT4res *)obj;
   3033 
   3034 	strcpy(buf, status_name(res->status));
   3035 	if (res->status == NFS4ERR_DENIED) {
   3036 		bp = buf + strlen(buf);
   3037 		snprintf(bp, buflen - (bp - buf), " %s",
   3038 		    sum_lock_denied(&res->LOCKT4res_u.denied));
   3039 	}
   3040 }
   3041 
   3042 static void
   3043 dtlres_lockt(void *obj)
   3044 {
   3045 	LOCKT4res *res = (LOCKT4res *)obj;
   3046 
   3047 	dtl_nfsstat4(obj);
   3048 	if (res->status == NFS4ERR_DENIED) {
   3049 		detail_lock_denied(&res->LOCKT4res_u.denied);
   3050 	}
   3051 }
   3052 
   3053 static void
   3054 sumres_locku(char *buf, size_t buflen, void *obj)
   3055 {
   3056 	char *bp;
   3057 	LOCKU4res *res = (LOCKU4res *)obj;
   3058 
   3059 	strncpy(buf, status_name(res->status), buflen);
   3060 	bp = buf + strlen(buf);
   3061 	if (res->status == NFS4_OK)
   3062 		snprintf(bp, buflen - (bp - buf), " %s",
   3063 		    sum_lock_stateid(&res->LOCKU4res_u.lock_stateid));
   3064 }
   3065 
   3066 static void
   3067 dtlres_locku(void *obj)
   3068 {
   3069 	LOCKU4res *res = (LOCKU4res *)obj;
   3070 
   3071 	dtl_nfsstat4(obj);
   3072 	if (res->status == NFS4_OK)
   3073 		detail_lock_stateid(&res->LOCKU4res_u.lock_stateid);
   3074 }
   3075 
   3076 static void
   3077 sumres_open(char *buf, size_t buflen, void *obj)
   3078 {
   3079 	char *bp = buf;
   3080 	OPEN4res *res = (OPEN4res *)obj;
   3081 	uint_t rflags;
   3082 	int len, blen = buflen;
   3083 
   3084 	strncpy(bp, status_name(res->status), blen);
   3085 
   3086 	if (res->status == NFS4_OK) {
   3087 		bp += (len = strlen(bp));
   3088 		blen -= len;
   3089 
   3090 		snprintf(bp, blen, " %s",
   3091 		    sum_stateid(&res->OPEN4res_u.resok4.stateid));
   3092 		bp += (len = strlen(bp));
   3093 		blen -= len;
   3094 
   3095 		if ((rflags = res->OPEN4res_u.resok4.rflags) != 0) {
   3096 			snprintf(bp, blen, "%s", sum_open_rflags(rflags));
   3097 			bp += (len = strlen(bp));
   3098 			blen -= len;
   3099 		}
   3100 
   3101 		sum_delegation(bp, blen, &res->OPEN4res_u.resok4.delegation);
   3102 	}
   3103 }
   3104 
   3105 static void
   3106 dtlres_open(void *obj)
   3107 {
   3108 	OPEN4res *res = (OPEN4res *)obj;
   3109 
   3110 	dtl_nfsstat4(obj);
   3111 	if (res->status == NFS4_OK) {
   3112 		detail_stateid(&res->OPEN4res_u.resok4.stateid);
   3113 		dtl_change_info("Change Information",
   3114 		    &res->OPEN4res_u.resok4.cinfo);
   3115 		sprintf(get_line(0, 0), "Flags = 0x%x (%s)",
   3116 		    res->OPEN4res_u.resok4.rflags,
   3117 		    detail_open_rflags(res->OPEN4res_u.resok4.rflags));
   3118 		detail_attr_bitmap("", &res->OPEN4res_u.resok4.attrset,
   3119 		    NULL);
   3120 		detail_delegation(&res->OPEN4res_u.resok4.delegation);
   3121 	}
   3122 }
   3123 
   3124 static void
   3125 sumres_open_confirm(char *buf, size_t buflen, void *obj)
   3126 {
   3127 	char *bp;
   3128 	OPEN_CONFIRM4res *res = (OPEN_CONFIRM4res *)obj;
   3129 
   3130 	strncpy(buf, status_name(res->status), buflen);
   3131 	if (res->status == NFS4_OK) {
   3132 		bp = buf + strlen(buf);
   3133 		snprintf(bp, buflen - (bp - buf), " %s",
   3134 		    sum_open_stateid(&res->OPEN_CONFIRM4res_u.resok4.
   3135 		    open_stateid));
   3136 	}
   3137 }
   3138 
   3139 static void
   3140 dtlres_open_confirm(void *obj)
   3141 {
   3142 	OPEN_CONFIRM4res *res = (OPEN_CONFIRM4res *)obj;
   3143 
   3144 	dtl_nfsstat4(obj);
   3145 	if (res->status == NFS4_OK) {
   3146 		detail_open_stateid(&res->OPEN_CONFIRM4res_u.resok4.
   3147 		    open_stateid);
   3148 	}
   3149 }
   3150 
   3151 static void
   3152 sumres_open_downgrd(char *buf, size_t buflen, void *obj)
   3153 {
   3154 	char *bp;
   3155 	OPEN_DOWNGRADE4res *res = (OPEN_DOWNGRADE4res *)obj;
   3156 
   3157 	strncpy(buf, status_name(res->status), buflen);
   3158 	if (res->status == NFS4_OK) {
   3159 		bp = buf + strlen(buf);
   3160 		snprintf(bp, buflen - (bp - buf), " %s",
   3161 		    sum_open_stateid(&res->OPEN_DOWNGRADE4res_u.resok4.
   3162 		    open_stateid));
   3163 	}
   3164 }
   3165 
   3166 static void
   3167 dtlres_open_downgrd(void *obj)
   3168 {
   3169 	OPEN_DOWNGRADE4res *res = (OPEN_DOWNGRADE4res *)obj;
   3170 
   3171 	dtl_nfsstat4(obj);
   3172 	if (res->status == NFS4_OK) {
   3173 		detail_open_stateid(&res->OPEN_DOWNGRADE4res_u.resok4.
   3174 		    open_stateid);
   3175 	}
   3176 }
   3177 
   3178 static void
   3179 sumres_read(char *buf, size_t buflen, void *obj)
   3180 {
   3181 	char *bp;
   3182 	READ4res *res = (READ4res *)obj;
   3183 
   3184 	strncpy(buf, status_name(res->status), buflen);
   3185 	if (res->status == NFS4_OK) {
   3186 		bp = buf + strlen(buf);
   3187 		snprintf(bp, buflen - (bp - buf), " (%u bytes) %s",
   3188 		    res->READ4res_u.resok4.data.data_len,
   3189 		    res->READ4res_u.resok4.eof ? "EOF" : "");
   3190 	}
   3191 }
   3192 
   3193 static void
   3194 dtlres_read(void *obj)
   3195 {
   3196 	READ4res *res = (READ4res *)obj;
   3197 
   3198 	dtl_nfsstat4(obj);
   3199 	if (res->status == NFS4_OK) {
   3200 		sprintf(get_line(0, 0), "Count = %u bytes read",
   3201 		    res->READ4res_u.resok4.data.data_len);
   3202 		sprintf(get_line(0, 0), "End of file = %s",
   3203 		    res->READ4res_u.resok4.eof ? "TRUE" : "FALSE");
   3204 	}
   3205 }
   3206 
   3207 static void
   3208 sumres_readdir(char *buf, size_t buflen, void *obj)
   3209 {
   3210 	char *bp;
   3211 	READDIR4res *res = (READDIR4res *)obj;
   3212 	int num_entries = 0;
   3213 	entry4 *ep;
   3214 
   3215 	strncpy(buf, status_name(res->status), buflen);
   3216 	if (res->status == NFS4_OK) {
   3217 		for (ep = res->READDIR4res_u.resok4.reply.entries;
   3218 		    ep != NULL;
   3219 		    ep = ep->nextentry)
   3220 			num_entries++;
   3221 		bp = buf + strlen(buf);
   3222 		snprintf(bp, buflen - (bp - buf), " %d entries (%s)",
   3223 		    num_entries,
   3224 		    res->READDIR4res_u.resok4.reply.eof
   3225 		    ? "No more" : "More");
   3226 	}
   3227 }
   3228 
   3229 static void
   3230 dtlres_readdir(void *obj)
   3231 {
   3232 	READDIR4res *res = (READDIR4res *)obj;
   3233 	int num_entries = 0;
   3234 	entry4 *ep;
   3235 
   3236 	dtl_nfsstat4(obj);
   3237 	if (res->status == NFS4_OK) {
   3238 		for (ep = res->READDIR4res_u.resok4.reply.entries;
   3239 		    ep != NULL;
   3240 		    ep = ep->nextentry) {
   3241 			num_entries++;
   3242 			sprintf(get_line(0, 0),
   3243 			    "------------------ entry #%d",
   3244 			    num_entries);
   3245 			sprintf(get_line(0, 0), "Cookie = %llu",
   3246 			    ep->cookie);
   3247 			sprintf(get_line(0, 0), "Name = %s",
   3248 			    component_name(&ep->name));
   3249 			detail_fattr4(&ep->attrs);
   3250 		}
   3251 		if (num_entries == 0)
   3252 			sprintf(get_line(0, 0), "(No entries)");
   3253 		sprintf(get_line(0, 0), "EOF = %s",
   3254 		    res->READDIR4res_u.resok4.reply.eof ? "TRUE" : "FALSE");
   3255 		sprintf(get_line(0, 0), "Verifer = %s",
   3256 		    tohex(res->READDIR4res_u.resok4.cookieverf,
   3257 		    NFS4_VERIFIER_SIZE));
   3258 	}
   3259 }
   3260 
   3261 static void
   3262 sumres_readlnk(char *buf, size_t buflen, void *obj)
   3263 {
   3264 	char *bp;
   3265 	READLINK4res *res = (READLINK4res *)obj;
   3266 
   3267 	strncpy(buf, status_name(res->status), buflen);
   3268 	if (res->status == NFS4_OK) {
   3269 		bp = buf + strlen(buf);
   3270 		snprintf(bp, buflen - (bp - buf), " %s",
   3271 		    linktext_name(&res->READLINK4res_u.resok4.link));
   3272 	}
   3273 }
   3274 
   3275 static void
   3276 dtlres_readlnk(void *obj)
   3277 {
   3278 	READLINK4res *res = (READLINK4res *)obj;
   3279 
   3280 	dtl_nfsstat4(obj);
   3281 	if (res->status == NFS4_OK) {
   3282 		sprintf(get_line(0, 0), "Link = %s",
   3283 		    linktext_name(&res->READLINK4res_u.resok4.link));
   3284 	}
   3285 }
   3286 
   3287 static void
   3288 dtlres_remove(void *obj)
   3289 {
   3290 	REMOVE4res *res = (REMOVE4res *)obj;
   3291 
   3292 	dtl_nfsstat4(obj);
   3293 	if (res->status == NFS4_OK) {
   3294 		dtl_change_info("Change Information",
   3295 		    &res->REMOVE4res_u.resok4.cinfo);
   3296 	}
   3297 }
   3298 
   3299 static void
   3300 dtlres_rename(void *obj)
   3301 {
   3302 	RENAME4res *res = (RENAME4res *)obj;
   3303 
   3304 	dtl_nfsstat4(obj);
   3305 	if (res->status == NFS4_OK) {
   3306 		dtl_change_info("Source Change Information",
   3307 		    &res->RENAME4res_u.resok4.source_cinfo);
   3308 		dtl_change_info("Target Change Information",
   3309 		    &res->RENAME4res_u.resok4.target_cinfo);
   3310 	}
   3311 }
   3312 
   3313 static void
   3314 sumres_secinfo(char *buf, size_t buflen, void *obj)
   3315 {
   3316 	char *bp;
   3317 	SECINFO4res *res = (SECINFO4res *)obj;
   3318 
   3319 	strncpy(buf, status_name(res->status), buflen);
   3320 	bp = buf + strlen(buf);
   3321 	if (res->status == NFS4_OK) {
   3322 		uint_t numinfo = res->SECINFO4res_u.resok4.SECINFO4resok_len;
   3323 		secinfo4 *infop;
   3324 
   3325 		for (infop = res->SECINFO4res_u.resok4.SECINFO4resok_val;
   3326 		    numinfo != 0;
   3327 		    infop++, numinfo--) {
   3328 			snprintf(bp, buflen - (bp - buf), " %s",
   3329 			    flavor_name(infop->flavor));
   3330 			bp += strlen(bp);
   3331 		}
   3332 	}
   3333 }
   3334 
   3335 static void
   3336 dtlres_secinfo(void *obj)
   3337 {
   3338 	SECINFO4res *res = (SECINFO4res *)obj;
   3339 
   3340 	dtl_nfsstat4(obj);
   3341 	if (res->status == NFS4_OK) {
   3342 		uint_t numinfo =
   3343 		    res->SECINFO4res_u.resok4.SECINFO4resok_len;
   3344 		secinfo4 *infop;
   3345 
   3346 		for (infop = res->SECINFO4res_u.resok4.SECINFO4resok_val;
   3347 		    numinfo != 0;
   3348 		    infop++, numinfo--) {
   3349 			detail_secinfo4(infop);
   3350 		}
   3351 	}
   3352 }
   3353 
   3354 static void
   3355 sumres_setattr(char *buf, size_t buflen, void *obj)
   3356 {
   3357 	SETATTR4res *res = (SETATTR4res *)obj;
   3358 
   3359 	strncpy(buf, status_name(res->status), buflen);
   3360 	sum_attr_bitmap(buf, buflen, &res->attrsset);
   3361 }
   3362 
   3363 static void
   3364 dtlres_setattr(void *obj)
   3365 {
   3366 	SETATTR4res *res = (SETATTR4res *)obj;
   3367 
   3368 	dtl_nfsstat4(obj);
   3369 	detail_attr_bitmap("", &res->attrsset, NULL);
   3370 }
   3371 
   3372 static void
   3373 sumres_setclid(char *buf, size_t buflen, void *obj)
   3374 {
   3375 	char *bp;
   3376 	SETCLIENTID4res *res = (SETCLIENTID4res *)obj;
   3377 
   3378 	strncpy(buf, status_name(res->status), buflen);
   3379 	switch (res->status) {
   3380 	case NFS_OK:
   3381 		bp = buf + strlen(buf);
   3382 		snprintf(bp, buflen - (bp - buf), " %s CFV=%s",
   3383 		    sum_clientid(res->SETCLIENTID4res_u.resok4.clientid),
   3384 		    tohex(res->SETCLIENTID4res_u.resok4.setclientid_confirm,
   3385 		    NFS4_VERIFIER_SIZE));
   3386 		break;
   3387 	case NFS4ERR_CLID_INUSE:
   3388 		bp = buf + strlen(buf);
   3389 		snprintf(bp, buflen - (bp - buf), " ID=%s Addr=%s",
   3390 		    res->SETCLIENTID4res_u.client_using.na_r_netid,
   3391 		    res->SETCLIENTID4res_u.client_using.na_r_addr);
   3392 		break;
   3393 	}
   3394 }
   3395 
   3396 static void
   3397 dtlres_setclid(void *obj)
   3398 {
   3399 	SETCLIENTID4res *res = (SETCLIENTID4res *)obj;
   3400 
   3401 	dtl_nfsstat4(obj);
   3402 	switch (res->status) {
   3403 	case NFS_OK:
   3404 		detail_clientid(res->SETCLIENTID4res_u.resok4.clientid);
   3405 		sprintf(get_line(0, 0), "Set Client ID Confirm Verifier = %s",
   3406 		    tohex(res->SETCLIENTID4res_u.resok4.setclientid_confirm,
   3407 		    NFS4_VERIFIER_SIZE));
   3408 		break;
   3409 	case NFS4ERR_CLID_INUSE:
   3410 		sprintf(get_line(0, 0), "Used by Net ID = %s",
   3411 		    res->SETCLIENTID4res_u.client_using.na_r_netid);
   3412 		sprintf(get_line(0, 0), "Used by Addr = %s",
   3413 		    res->SETCLIENTID4res_u.client_using.na_r_addr);
   3414 		break;
   3415 	}
   3416 }
   3417 
   3418 static void
   3419 sumres_write(char *buf, size_t buflen, void *obj)
   3420 {
   3421 	char *bp;
   3422 	WRITE4res *res = (WRITE4res *)obj;
   3423 
   3424 	strncpy(buf, status_name(res->status), buflen);
   3425 	if (res->status == NFS4_OK) {
   3426 		bp = buf + strlen(buf);
   3427 		snprintf(bp, buflen - (bp - buf), " %u (%s)",
   3428 		    res->WRITE4res_u.resok4.count,
   3429 		    stable_how4_name(res->WRITE4res_u.resok4.committed));
   3430 	}
   3431 }
   3432 
   3433 static void
   3434 dtlres_write(void *obj)
   3435 {
   3436 	WRITE4res *res = (WRITE4res *)obj;
   3437 
   3438 	dtl_nfsstat4(obj);
   3439 	if (res->status == NFS4_OK) {
   3440 		sprintf(get_line(0, 0), "Count = %u bytes written",
   3441 		    res->WRITE4res_u.resok4.count);
   3442 		sprintf(get_line(0, 0), "Stable = %s",
   3443 		    stable_how4_name(res->WRITE4res_u.resok4.committed));
   3444 		sprintf(get_line(0, 0), "Verifier = %s",
   3445 		    tohex(res->WRITE4res_u.resok4.writeverf,
   3446 		    NFS4_VERIFIER_SIZE));
   3447 	}
   3448 }
   3449 
   3450 /*
   3451  * Print details about the nfs_resop4 that is next in the XDR stream.
   3452  */
   3453 
   3454 static void
   3455 detail_nfs_resop4(void)
   3456 {
   3457 	int numres;
   3458 	nfs_resop4 one_res;
   3459 	void (*fmtproc)(void *);
   3460 
   3461 	numres = getxdr_long();
   3462 	(void) sprintf(get_line(0, 0), "Number of results = %d",
   3463 	    numres);
   3464 
   3465 	while (numres-- > 0) {
   3466 		bzero(&one_res, sizeof (one_res));
   3467 
   3468 		if (!xdr_nfs_resop4(&xdrm, &one_res)) {
   3469 			xdr_free(xdr_nfs_resop4, (char *)&one_res);
   3470 			longjmp(xdr_err, 1);
   3471 		}
   3472 
   3473 		get_line(0, 0);		/* blank line to separate ops */
   3474 		sprintf(get_line(0, 0), "Op = %d (%s)",
   3475 		    one_res.resop, opcode_name(one_res.resop));
   3476 		if (one_res.resop < num_opcodes)
   3477 			fmtproc = opcode_info[one_res.resop].dtlres;
   3478 		else if (one_res.resop == OP_ILLEGAL)
   3479 			fmtproc = dtl_nfsstat4;
   3480 		else
   3481 			fmtproc = NULL;
   3482 
   3483 		if (fmtproc != NULL)
   3484 			fmtproc(&one_res.nfs_resop4_u);
   3485 
   3486 		/* nfs4_skip_bytes set by xdr_nfs_resop4()() */
   3487 		if (nfs4_skip_bytes)
   3488 			nfs4_xdr_skip(nfs4_skip_bytes);
   3489 
   3490 		xdr_free(xdr_nfs_resop4, (char *)&one_res);
   3491 	}
   3492 }
   3493 
   3494 
   3495 /*
   3496  * Print details about the nfs_cb_resop4 that is next in the XDR stream.
   3497  */
   3498 
   3499 static void
   3500 detail_cb_resop4(void)
   3501 {
   3502 	int numres;
   3503 	nfs_cb_resop4 one_res;
   3504 	void (*fmtproc)(void *);
   3505 
   3506 	numres = getxdr_long();
   3507 	(void) sprintf(get_line(0, 0), "Number of results = %d",
   3508 	    numres);
   3509 
   3510 	while (numres-- > 0) {
   3511 		bzero(&one_res, sizeof (one_res));
   3512 		if (!xdr_nfs_cb_resop4(&xdrm, &one_res))
   3513 			longjmp(xdr_err, 1);
   3514 
   3515 		get_line(0, 0);		/* blank line to separate ops */
   3516 		sprintf(get_line(0, 0), "Op = %d (%s)",
   3517 		    one_res.resop, cb_opcode_name(one_res.resop));
   3518 		if (one_res.resop < cb_num_opcodes)
   3519 			fmtproc = cb_opcode_info[one_res.resop].dtlres;
   3520 		else if (one_res.resop == OP_CB_ILLEGAL)
   3521 			fmtproc = dtl_nfsstat4;
   3522 		else
   3523 			fmtproc = NULL;
   3524 
   3525 		if (fmtproc != NULL)
   3526 			fmtproc(&one_res.nfs_cb_resop4_u);
   3527 
   3528 		xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
   3529 	}
   3530 }
   3531 
   3532 
   3533 /*
   3534  * Return the name of a lock type.
   3535  */
   3536 static char *
   3537 lock_type_name(enum nfs_lock_type4 type)
   3538 {
   3539 	char *result;
   3540 
   3541 	switch (type) {
   3542 	case READ_LT:
   3543 		result = "READ";
   3544 		break;
   3545 	case WRITE_LT:
   3546 		result = "WRITE";
   3547 		break;
   3548 	case READW_LT:
   3549 		result = "READW";
   3550 		break;
   3551 	case WRITEW_LT:
   3552 		result = "WRITEW";
   3553 		break;
   3554 	default:
   3555 		result = "?";
   3556 		break;
   3557 	}
   3558 
   3559 	return (result);
   3560 }
   3561 
   3562 /*
   3563  * Return the name of an opcode.
   3564  */
   3565 
   3566 static char *
   3567 opcode_name(uint_t opnum)
   3568 {
   3569 	static char buf[20];
   3570 
   3571 	if (opnum < num_opcodes)
   3572 		return (opcode_info[opnum].name);
   3573 
   3574 	if (opnum == OP_ILLEGAL)
   3575 		return ("ILLEGAL");
   3576 
   3577 	sprintf(buf, "op %d", opnum);
   3578 	return (buf);
   3579 }
   3580 
   3581 /*
   3582  * Return the name of an opcode.
   3583  */
   3584 static char *
   3585 cb_opcode_name(uint_t opnum)
   3586 {
   3587 	static char buf[20];
   3588 
   3589 	if (opnum < cb_num_opcodes)
   3590 		return (cb_opcode_info[opnum].name);
   3591 
   3592 	if (opnum == OP_CB_ILLEGAL)
   3593 		return ("CB_ILLEGAL");
   3594 
   3595 	sprintf(buf, "op %d", opnum);
   3596 	return (buf);
   3597 }
   3598 
   3599 
   3600 /*
   3601  * Fill in a summary string for the given access bitmask.
   3602  */
   3603 
   3604 static void
   3605 sum_access4(char *buf, size_t buflen, uint32_t bits)
   3606 {
   3607 	buf[0] = '\0';
   3608 
   3609 	if (bits & ACCESS4_READ)
   3610 		(void) strncat(buf, "rd,", buflen);
   3611 	if (bits & ACCESS4_LOOKUP)
   3612 		(void) strncat(buf, "lk,", buflen);
   3613 	if (bits & ACCESS4_MODIFY)
   3614 		(void) strncat(buf, "mo,", buflen);
   3615 	if (bits & ACCESS4_EXTEND)
   3616 		(void) strncat(buf, "ext,", buflen);
   3617 	if (bits & ACCESS4_DELETE)
   3618 		(void) strncat(buf, "dl,", buflen);
   3619 	if (bits & ACCESS4_EXECUTE)
   3620 		(void) strncat(buf, "exc,", buflen);
   3621 	if (buf[0] != '\0')
   3622 		buf[strlen(buf) - 1] = '\0';
   3623 }
   3624 
   3625 /*
   3626  * Print detail information about the given access bitmask.
   3627  */
   3628 
   3629 static void
   3630 detail_access4(char *descrip, uint32_t bits)
   3631 {
   3632 	sprintf(get_line(0, 0), "%s = 0x%08x", descrip, bits);
   3633 
   3634 	(void) sprintf(get_line(0, 0), "	%s",
   3635 	    getflag(bits, ACCESS4_READ, "Read", "(no read)"));
   3636 	(void) sprintf(get_line(0, 0), "	%s",
   3637 	    getflag(bits, ACCESS4_LOOKUP, "Lookup", "(no lookup)"));
   3638 	(void) sprintf(get_line(0, 0), "	%s",
   3639 	    getflag(bits, ACCESS4_MODIFY, "Modify", "(no modify)"));
   3640 	(void) sprintf(get_line(0, 0), "	%s",
   3641 	    getflag(bits, ACCESS4_EXTEND, "Extend", "(no extend)"));
   3642 	(void) sprintf(get_line(0, 0), "	%s",
   3643 	    getflag(bits, ACCESS4_DELETE, "Delete", "(no delete)"));
   3644 	(void) sprintf(get_line(0, 0), "	%s",
   3645 	    getflag(bits, ACCESS4_EXECUTE, "Execute", "(no execute)"));
   3646 }
   3647 
   3648 
   3649 /*
   3650  * Fill in a summary string for the given open_claim4.
   3651  */
   3652 static void
   3653 sum_name(char *buf, size_t buflen, open_claim4 *claim)
   3654 {
   3655 	char *bp = buf;
   3656 
   3657 	switch (claim->claim) {
   3658 	case CLAIM_NULL:
   3659 		snprintf(bp, buflen, "%s ",
   3660 		    component_name(&claim->open_claim4_u.file));
   3661 		break;
   3662 	case CLAIM_PREVIOUS:
   3663 		break;
   3664 	case CLAIM_DELEGATE_CUR:
   3665 		snprintf(bp, buflen, "%s ",
   3666 		    component_name(&claim->open_claim4_u.
   3667 		    delegate_cur_info.file));
   3668 		break;
   3669 	case CLAIM_DELEGATE_PREV:
   3670 		snprintf(bp, buflen, "%s ",
   3671 		    component_name(&claim->open_claim4_u.
   3672 		    file_delegate_prev));
   3673 		break;
   3674 	case CLAIM_FH:
   3675 		break;
   3676 	case CLAIM_DELEG_CUR_FH:
   3677 		break;
   3678 	case CLAIM_DELEG_PREV_FH:
   3679 		break;
   3680 	}
   3681 }
   3682 
   3683 /*
   3684  * Fill in a summary string for the given open_claim4.
   3685  */
   3686 static void
   3687 sum_claim(char *buf, size_t buflen, open_claim4 *claim)
   3688 {
   3689 	char *bp = buf;
   3690 
   3691 	switch (claim->claim) {
   3692 	case CLAIM_NULL:
   3693 		snprintf(bp, buflen, " CT=N");
   3694 		break;
   3695 	case CLAIM_PREVIOUS:
   3696 		snprintf(bp, buflen, " CT=P DT=%s",
   3697 		    get_deleg_typestr(claim->open_claim4_u.delegate_type));
   3698 		break;
   3699 	case CLAIM_DELEGATE_CUR:
   3700 		snprintf(bp, buflen, " CT=DC %s",
   3701 		    sum_deleg_stateid(&claim->open_claim4_u.
   3702 		    delegate_cur_info.delegate_stateid));
   3703 		break;
   3704 	case CLAIM_DELEGATE_PREV:
   3705 		snprintf(bp, buflen, " CT=DP");
   3706 		break;
   3707 	case CLAIM_FH:
   3708 		snprintf(bp, buflen, " CT=FH");
   3709 		break;
   3710 	case CLAIM_DELEG_CUR_FH:
   3711 		snprintf(bp, buflen, " CT=CUR_FH");
   3712 		break;
   3713 	case CLAIM_DELEG_PREV_FH:
   3714 		snprintf(bp, buflen, " CT=PREV_FH");
   3715 		break;
   3716 	default:
   3717 		snprintf(bp, buflen, " CT=? (%d)", claim->claim);
   3718 		break;
   3719 	}
   3720 }
   3721 
   3722 static char *
   3723 get_deleg_typestr(open_delegation_type4 dt)
   3724 {
   3725 	char *str = "";
   3726 
   3727 	switch (dt) {
   3728 	case OPEN_DELEGATE_NONE:
   3729 		str = "N";
   3730 		break;
   3731 	case OPEN_DELEGATE_READ:
   3732 		str = "R";
   3733 		break;
   3734 	case OPEN_DELEGATE_WRITE:
   3735 		str = "W";
   3736 		break;
   3737 	default:
   3738 		str = "?";
   3739 	}
   3740 
   3741 	return (str);
   3742 }
   3743 
   3744 /*
   3745  * Print detail information for the given open_claim4.
   3746  */
   3747 
   3748 static void
   3749 detail_claim(open_claim4 *claim)
   3750 {
   3751 	sprintf(get_line(0, 0), "Claim Type = %d (%s)",
   3752 	    claim->claim, claim_name(claim->claim));
   3753 
   3754 	switch (claim->claim) {
   3755 	case CLAIM_NULL:
   3756 		detail_compname4(&claim->open_claim4_u.file);
   3757 		break;
   3758 	case CLAIM_PREVIOUS:
   3759 		sprintf(get_line(0, 0), "Delegate Type = %s (val = %d)",
   3760 		    get_deleg_typestr(claim->open_claim4_u.delegate_type),
   3761 		    claim->open_claim4_u.delegate_type);
   3762 		break;
   3763 	case CLAIM_DELEGATE_CUR:
   3764 		detail_compname4(&claim->open_claim4_u.delegate_cur_info.file);
   3765 		detail_deleg_stateid(&claim->open_claim4_u.delegate_cur_info.
   3766 		    delegate_stateid);
   3767 		break;
   3768 	case CLAIM_DELEGATE_PREV:
   3769 		detail_compname4(&claim->open_claim4_u.file_delegate_prev);
   3770 		break;
   3771 	}
   3772 }
   3773 
   3774 /*
   3775  * Return a summary string for the given clientid4.
   3776  */
   3777 char *
   3778 sum_clientid(clientid4 client)
   3779 {
   3780 	static char buf[50];
   3781 
   3782 	snprintf(buf, sizeof (buf), "CL=%llx", client);
   3783 
   3784 	return (buf);
   3785 }
   3786 
   3787 /*
   3788  * Print a detail string for the given clientid4.
   3789  */
   3790 void
   3791 detail_clientid(clientid4 client)
   3792 {
   3793 	sprintf(get_line(0, 0), "Client ID = %llx", client);
   3794 }
   3795 
   3796 /*
   3797  * Write a summary string for the given delegation into buf.
   3798  */
   3799 
   3800 static void
   3801 sum_delegation(char *buf, size_t buflen, open_delegation4 *delp)
   3802 {
   3803 	switch (delp->delegation_type) {
   3804 	case OPEN_DELEGATE_NONE:
   3805 		snprintf(buf, buflen, " DT=N");
   3806 		break;
   3807 	case OPEN_DELEGATE_READ:
   3808 		snprintf(buf, buflen, " DT=R %s",
   3809 		    sum_deleg_stateid(&delp->open_delegation4_u.write.
   3810 		    stateid));
   3811 		break;
   3812 	case OPEN_DELEGATE_WRITE:
   3813 		snprintf(buf, buflen, " DT=W %s %s",
   3814 		    sum_deleg_stateid(&delp->open_delegation4_u.write.
   3815 		    stateid),
   3816 		    sum_space_limit(&delp->open_delegation4_u.write.
   3817 		    space_limit));
   3818 		break;
   3819 	default:
   3820 		snprintf(buf, buflen, " DT=?");
   3821 		break;
   3822 	}
   3823 }
   3824 
   3825 static void
   3826 detail_delegation(open_delegation4 *delp)
   3827 {
   3828 	sprintf(get_line(0, 0), "Delegation Type = %d (%s)",
   3829 	    delp->delegation_type,
   3830 	    delegation_type_name(delp->delegation_type));
   3831 
   3832 	switch (delp->delegation_type) {
   3833 	case OPEN_DELEGATE_NONE:
   3834 		/* no-op */
   3835 		break;
   3836 	case OPEN_DELEGATE_READ:
   3837 		detail_deleg_stateid(&delp->open_delegation4_u.read.stateid);
   3838 		sprintf(get_line(0, 0), "Recall = %s",
   3839 		    delp->open_delegation4_u.read.recall ?
   3840 		    "TRUE" : "FALSE");
   3841 		sprintf(get_line(0, 0), "[nfsacl4]");
   3842 		break;
   3843 	case OPEN_DELEGATE_WRITE:
   3844 		detail_deleg_stateid(&delp->open_delegation4_u.write.stateid);
   3845 		sprintf(get_line(0, 0), "Recall = %s",
   3846 		    delp->open_delegation4_u.write.recall ?
   3847 		    "TRUE" : "FALSE");
   3848 		detail_space_limit(&delp->open_delegation4_u.write.
   3849 		    space_limit);
   3850 		sprintf(get_line(0, 0), "[nfsacl4]");
   3851 		break;
   3852 	}
   3853 }
   3854 
   3855 
   3856 static void
   3857 detail_open_owner(open_owner4 *owner)
   3858 {
   3859 	sprintf(get_line(0, 0), "Open Owner hash = [%04X] ",
   3860 	    owner_hash(&owner->owner));
   3861 	sprintf(get_line(0, 0), "    len = %u   val = %s ",
   3862 	    owner->owner.owner_len,
   3863 	    tohex(owner->owner.owner_val, owner->owner.owner_len));
   3864 	detail_clientid(owner->clientid);
   3865 }
   3866 
   3867 static void
   3868 detail_lock_owner(lock_owner4 *owner)
   3869 {
   3870 	sprintf(get_line(0, 0), "Lock Owner hash = [%04X] ",
   3871 	    owner_hash(&owner->owner));
   3872 	sprintf(get_line(0, 0), "    len = %u   val = %s ",
   3873 	    owner->owner.owner_len,
   3874 	    tohex(owner->owner.owner_val, owner->owner.owner_len));
   3875 	detail_clientid(owner->clientid);
   3876 }
   3877 
   3878 static void
   3879 sum_openflag(char *bufp, int buflen, openflag4 *flagp)
   3880 {
   3881 	if (flagp->opentype == OPEN4_CREATE) {
   3882 		switch (flagp->openflag4_u.how.mode) {
   3883 		case UNCHECKED4:
   3884 			snprintf(bufp, buflen, "OT=CR(U)");
   3885 			break;
   3886 		case GUARDED4:
   3887 			snprintf(bufp, buflen, "OT=CR(G)");
   3888 			break;
   3889 		case EXCLUSIVE4:
   3890 			snprintf(bufp, buflen, "OT=CR(E)");
   3891 			break;
   3892 		default:
   3893 			snprintf(bufp, buflen, "OT=CR(?:%d)",
   3894 			    flagp->openflag4_u.how.mode);
   3895 			break;
   3896 		}
   3897 	} else
   3898 		snprintf(bufp, buflen, "OT=NC");
   3899 }
   3900 
   3901 static void
   3902 detail_openflag(openflag4 *flagp)
   3903 {
   3904 	sprintf(get_line(0, 0), "Open Type = %s",
   3905 	    flagp->opentype == OPEN4_CREATE ? "CREATE" : "NOCREATE");
   3906 	if (flagp->opentype == OPEN4_CREATE)
   3907 		detail_createhow4(&flagp->openflag4_u.how);
   3908 }
   3909 
   3910 /*
   3911  * Fill in buf with the given path.
   3912  */
   3913 static void
   3914 sum_pathname4(char *buf, size_t buflen, pathname4 *pathp)
   3915 {
   3916 	char *bp = buf;
   3917 	uint_t component;
   3918 
   3919 	for (component = 0; component < pathp->pathname4_len;
   3920 	    component++) {
   3921 		snprintf(bp, buflen - (bp - buf),
   3922 		    component == 0 ? "%s" : "/%s",
   3923 		    component_name(&pathp->pathname4_val[component]));
   3924 		bp += strlen(bp);
   3925 	}
   3926 }
   3927 
   3928 static void
   3929 sum_compname4(char *buf, size_t buflen, component4 *comp)
   3930 {
   3931 	snprintf(buf, buflen, "%s", component_name(comp));
   3932 }
   3933 
   3934 static void
   3935 detail_compname4(component4 *comp)
   3936 {
   3937 	sprintf(get_line(0, 0), "%s", component_name(comp));
   3938 }
   3939 
   3940 static void
   3941 detail_pathname4(pathname4 *pathp)
   3942 {
   3943 	char *bp = get_line(0, 0);
   3944 	uint_t component;
   3945 
   3946 	sprintf(bp, "File name = ");
   3947 	bp += strlen(bp);
   3948 
   3949 	for (component = 0; component < pathp->pathname4_len; component++) {
   3950 		sprintf(bp, component == 0 ? "%s" : "/%s",
   3951 		    component_name(&pathp->pathname4_val[component]));
   3952 		bp += strlen(bp);
   3953 	}
   3954 }
   3955 
   3956 /*
   3957  * Print detail information about the rpcsec_gss_info that is XDR-encoded
   3958  * at mem.
   3959  */
   3960 
   3961 void
   3962 detail_rpcsec_gss(rpcsec_gss_info *info)
   3963 {
   3964 	sprintf(get_line(0, 0), "OID = %s",
   3965 	    tohex(info->oid.sec_oid4_val, info->oid.sec_oid4_len));
   3966 	sprintf(get_line(0, 0), "QOP = %u", info->qop);
   3967 	sprintf(get_line(0, 0), "Service = %d (%s)",
   3968 	    info->service, gss_svc_name(info->service));
   3969 }
   3970 
   3971 /*
   3972  * Print detail information about the given secinfo4.
   3973  */
   3974 
   3975 void
   3976 detail_secinfo4(secinfo4 *infop)
   3977 {
   3978 	sprintf(get_line(0, 0), "Flavor = %d (%s)",
   3979 	    infop->flavor, flavor_name(infop->flavor));
   3980 	switch (infop->flavor) {
   3981 	case RPCSEC_GSS:
   3982 		detail_rpcsec_gss(&infop->secinfo4_u.flavor_info);
   3983 		break;
   3984 	}
   3985 }
   3986 
   3987 
   3988 /*
   3989  * Return a summary string corresponding to the given nfs_space_limit4.
   3990  */
   3991 
   3992 static char *
   3993 sum_space_limit(nfs_space_limit4 *limitp)
   3994 {
   3995 	static char buf[64];
   3996 	int buflen = sizeof (buf);
   3997 
   3998 	buf[0] = '\0';
   3999 	switch (limitp->limitby) {
   4000 	case NFS_LIMIT_SIZE:
   4001 		snprintf(buf, buflen, "LB=SZ(%llu)",
   4002 		    limitp->nfs_space_limit4_u.filesize);
   4003 		break;
   4004 	case NFS_LIMIT_BLOCKS:
   4005 		snprintf(buf, buflen, "LB=BL(%u*%u)",
   4006 		    limitp->nfs_space_limit4_u.mod_blocks.num_blocks,
   4007 		    limitp->nfs_space_limit4_u.mod_blocks.bytes_per_block);
   4008 		break;
   4009 	default:
   4010 		snprintf(buf, buflen, "LB=?(%d)", limitp->limitby);
   4011 		break;
   4012 	}
   4013 
   4014 	return (buf);
   4015 }
   4016 
   4017 /*
   4018  * Print detail information about the given nfs_space_limit4.
   4019  */
   4020 
   4021 static void
   4022 detail_space_limit(nfs_space_limit4 *limitp)
   4023 {
   4024 	sprintf(get_line(0, 0), "LimitBy = %d (%s)",
   4025 	    limitp->limitby,
   4026 	    limitby_name(limitp->limitby));
   4027 
   4028 	switch (limitp->limitby) {
   4029 	case NFS_LIMIT_SIZE:
   4030 		sprintf(get_line(0, 0), "Bytes = %llu",
   4031 		    limitp->nfs_space_limit4_u.filesize);
   4032 		break;
   4033 	case NFS_LIMIT_BLOCKS:
   4034 		sprintf(get_line(0, 0), "Blocks = %u",
   4035 		    limitp->nfs_space_limit4_u.mod_blocks.num_blocks);
   4036 		sprintf(get_line(0, 0), "Bytes Per Block = %u",
   4037 		    limitp->nfs_space_limit4_u.mod_blocks.bytes_per_block);
   4038 		break;
   4039 	}
   4040 }
   4041 
   4042 
   4043 /*
   4044  * Return the short name of a file type.
   4045  */
   4046 
   4047 static char *
   4048 sum_type_name(nfs_ftype4 type)
   4049 {
   4050 	static char buf[20];
   4051 
   4052 	if (type < num_ftypes)
   4053 		return (ftype_names[type].short_name);
   4054 	else {
   4055 		sprintf(buf, "type %d", type);
   4056 		return (buf);
   4057 	}
   4058 }
   4059 
   4060 
   4061 /*
   4062  * Return string with long/short flag names
   4063  */
   4064 
   4065 static char *
   4066 get_flags(uint_t flag, ftype_names_t *names, uint_t num_flags, int shortname,
   4067 	char *prefix)
   4068 {
   4069 	static char buf[200];
   4070 	char *bp = buf, *str;
   4071 	int i, len, blen = sizeof (buf);
   4072 	ftype_names_t *fn = NULL;
   4073 
   4074 	*bp = '\0';
   4075 
   4076 	if (prefix) {
   4077 		snprintf(bp, blen, "%s", prefix);
   4078 		bp += (len = sizeof (bp));
   4079 		blen -= len;
   4080 	}
   4081 
   4082 	for (i = 0; i < 32; i++)
   4083 		if (flag & (1 << i)) {
   4084 			fn = names + (i < num_flags ? i : num_flags);
   4085 			str = (shortname ? fn->short_name : fn->long_name);
   4086 
   4087 			snprintf(bp, blen, "%s,", str);
   4088 			bp += (len = strlen(bp));
   4089 			blen -= len;
   4090 		}
   4091 
   4092 	if (fn)
   4093 		*(bp - 1) = '\0';
   4094 	else
   4095 		*buf = '\0';
   4096 
   4097 	return (buf);
   4098 }
   4099 
   4100 
   4101 /*
   4102  * Return the long name of a file type.
   4103  */
   4104 
   4105 static char *
   4106 detail_type_name(nfs_ftype4 type)
   4107 {
   4108 	static char buf[20];
   4109 
   4110 	if (type < num_ftypes)
   4111 		return (ftype_names[type].long_name);
   4112 	else {
   4113 		sprintf(buf, "type %d", type);
   4114 		return (buf);
   4115 	}
   4116 }
   4117 
   4118 /*
   4119  * Return the name of an attribute.
   4120  */
   4121 
   4122 static char *
   4123 attr_name(uint_t attrnum)
   4124 {
   4125 	static char buf[20];
   4126 
   4127 	if (attrnum < MAX_ATTRIBUTES)
   4128 		return (attr_info[attrnum].name);
   4129 	else {
   4130 		sprintf(buf, "attr #%d", attrnum);
   4131 		return (buf);
   4132 	}
   4133 }
   4134 
   4135 /*
   4136  * Return the name of the given open_claim_type4.
   4137  */
   4138 
   4139 static char *
   4140 claim_name(enum open_claim_type4 claim_type)
   4141 {
   4142 	char *result;
   4143 
   4144 	switch (claim_type) {
   4145 	case CLAIM_NULL:
   4146 		result = "NULL";
   4147 		break;
   4148 	case CLAIM_PREVIOUS:
   4149 		result = "PREVIOUS";
   4150 		break;
   4151 	case CLAIM_DELEGATE_CUR:
   4152 		result = "DELEGATE CURRENT";
   4153 		break;
   4154 	case CLAIM_DELEGATE_PREV:
   4155 		result = "DELEGATE PREVIOUS";
   4156 		break;
   4157 	case CLAIM_FH:
   4158 		result = "FILEHANDLE";
   4159 		break;
   4160 	default:
   4161 		result = "?";
   4162 		break;
   4163 	}
   4164 
   4165 	return (result);
   4166 }
   4167 
   4168 /*
   4169  * Return a string naming the given delegation.
   4170  */
   4171 
   4172 static char *
   4173 delegation_type_name(enum open_delegation_type4 type)
   4174 {
   4175 	char *result;
   4176 
   4177 	switch (type) {
   4178 	case OPEN_DELEGATE_NONE:
   4179 		result = "NONE";
   4180 		break;
   4181 	case OPEN_DELEGATE_READ:
   4182 		result = "READ";
   4183 		break;
   4184 	case OPEN_DELEGATE_WRITE:
   4185 		result = "WRITE";
   4186 		break;
   4187 	default:
   4188 		result = "?";
   4189 		break;
   4190 	}
   4191 
   4192 	return (result);
   4193 }
   4194 
   4195 /*
   4196  * Return the name of the given authentication flavor.
   4197  */
   4198 
   4199 static char *
   4200 flavor_name(uint_t flavor)
   4201 {
   4202 	char *result;
   4203 	static char buf[50];
   4204 
   4205 	switch (flavor) {
   4206 	case AUTH_SYS:
   4207 		result = "AUTH_SYS";
   4208 		break;
   4209 	case AUTH_NONE:
   4210 		result = "AUTH_NONE";
   4211 		break;
   4212 	case AUTH_DH:
   4213 		result = "AUTH_DH";
   4214 		break;
   4215 	case RPCSEC_GSS:
   4216 		result = "RPCSEC_GSS";
   4217 		break;
   4218 	default:
   4219 		sprintf(buf, "[flavor %d]", flavor);
   4220 		result = buf;
   4221 		break;
   4222 	}
   4223 
   4224 	return (result);
   4225 }
   4226 
   4227 /*
   4228  * Return the name of the given rpc_gss_svc_t.
   4229  */
   4230 
   4231 static char *
   4232 gss_svc_name(rpc_gss_svc_t svc)
   4233 {
   4234 	char *result;
   4235 	static char buf[50];
   4236 
   4237 	switch (svc) {
   4238 	case RPC_GSS_SVC_NONE:
   4239 		result = "NONE";
   4240 		break;
   4241 	case RPC_GSS_SVC_INTEGRITY:
   4242 		result = "INTEGRITY";
   4243 		break;
   4244 	case RPC_GSS_SVC_PRIVACY:
   4245 		result = "PRIVACY";
   4246 		break;
   4247 	default:
   4248 		sprintf(buf, "Service %d", svc);
   4249 		result = buf;
   4250 		break;
   4251 	}
   4252 
   4253 	return (result);
   4254 }
   4255 
   4256 /*
   4257  * Return a string name for the given limit_by4.
   4258  */
   4259 
   4260 static char *
   4261 limitby_name(enum limit_by4 limitby)
   4262 {
   4263 	char *result;
   4264 
   4265 	switch (limitby) {
   4266 	case NFS_LIMIT_SIZE:
   4267 		result = "SIZE";
   4268 		break;
   4269 	case NFS_LIMIT_BLOCKS:
   4270 		result = "BLOCKS";
   4271 		break;
   4272 	default:
   4273 		result = "?";
   4274 		break;
   4275 	}
   4276 
   4277 	return (result);
   4278 }
   4279 
   4280 static char *
   4281 status_name(int status)
   4282 {
   4283 	char *p;
   4284 
   4285 	switch (status) {
   4286 	case NFS4_OK:				/* 0 */
   4287 		p = "NFS4_OK"; break;
   4288 	case NFS4ERR_PERM:			/* 1 */
   4289 		p = "NFS4ERR_PERM"; break;
   4290 	case NFS4ERR_NOENT:			/* 2 */
   4291 		p = "NFS4ERR_NOENT"; break;
   4292 	case NFS4ERR_IO:			/* 5 */
   4293 		p = "NFS4ERR_IO"; break;
   4294 	case NFS4ERR_NXIO:			/* 6 */
   4295 		p = "NFS4ERR_NXIO"; break;
   4296 	case NFS4ERR_ACCESS:			/* 13 */
   4297 		p = "NFS4ERR_ACCESS"; break;
   4298 	case NFS4ERR_EXIST:			/* 17 */
   4299 		p = "NFS4ERR_EXIST"; break;
   4300 	case NFS4ERR_XDEV:			/* 18 */
   4301 		p = "NFS4ERR_XDEV"; break;
   4302 	case NFS4ERR_NOTDIR:			/* 20 */
   4303 		p = "NFS4ERR_NOTDIR"; break;
   4304 	case NFS4ERR_ISDIR:			/* 21 */
   4305 		p = "NFS4ERR_ISDIR"; break;
   4306 	case NFS4ERR_INVAL:			/* 22 */
   4307 		p = "NFS4ERR_INVAL"; break;
   4308 	case NFS4ERR_FBIG:			/* 27 */
   4309 		p = "NFS4ERR_FBIG"; break;
   4310 	case NFS4ERR_NOSPC:			/* 28 */
   4311 		p = "NFS4ERR_NOSPC"; break;
   4312 	case NFS4ERR_ROFS:			/* 30 */
   4313 		p = "NFS4ERR_ROFS"; break;
   4314 	case NFS4ERR_MLINK:			/* 31 */
   4315 		p = "NFS4ERR_MLINK"; break;
   4316 	case NFS4ERR_NAMETOOLONG:		/* 63 */
   4317 		p = "NFS4ERR_NAMETOOLONG"; break;
   4318 	case NFS4ERR_NOTEMPTY:			/* 66 */
   4319 		p = "NFS4ERR_NOTEMPTY"; break;
   4320 	case NFS4ERR_DQUOT:			/* 69 */
   4321 		p = "NFS4ERR_DQUOT"; break;
   4322 	case NFS4ERR_STALE:			/* 70 */
   4323 		p = "NFS4ERR_STALE"; break;
   4324 	case NFS4ERR_BADHANDLE:			/* 10001 */
   4325 		p = "NFS4ERR_BADHANDLE"; break;
   4326 	case NFS4ERR_BAD_COOKIE:		/* 10003 */
   4327 		p = "NFS4ERR_BAD_COOKIE"; break;
   4328 	case NFS4ERR_NOTSUPP:			/* 10004 */
   4329 		p = "NFS4ERR_NOTSUPP"; break;
   4330 	case NFS4ERR_TOOSMALL:			/* 10005 */
   4331 		p = "NFS4ERR_TOOSMALL"; break;
   4332 	case NFS4ERR_SERVERFAULT:		/* 10006 */
   4333 		p = "NFS4ERR_SERVERFAULT"; break;
   4334 	case NFS4ERR_BADTYPE:			/* 10007 */
   4335 		p = "NFS4ERR_BADTYPE"; break;
   4336 	case NFS4ERR_DELAY:			/* 10008 */
   4337 		p = "NFS4ERR_DELAY"; break;
   4338 	case NFS4ERR_SAME:			/* 10009 */
   4339 		p = "NFS4ERR_SAME"; break;
   4340 	case NFS4ERR_DENIED:			/* 10010 */
   4341 		p = "NFS4ERR_DENIED"; break;
   4342 	case NFS4ERR_EXPIRED:			/* 10011 */
   4343 		p = "NFS4ERR_EXPIRED"; break;
   4344 	case NFS4ERR_LOCKED:			/* 10012 */
   4345 		p = "NFS4ERR_LOCKED"; break;
   4346 	case NFS4ERR_GRACE:			/* 10013 */
   4347 		p = "NFS4ERR_GRACE"; break;
   4348 	case NFS4ERR_FHEXPIRED:			/* 10014 */
   4349 		p = "NFS4ERR_FHEXPIRED"; break;
   4350 	case NFS4ERR_SHARE_DENIED:		/* 10015 */
   4351 		p = "NFS4ERR_SHARE_DENIED"; break;
   4352 	case NFS4ERR_WRONGSEC:			/* 10016 */
   4353 		p = "NFS4ERR_WRONGSEC"; break;
   4354 	case NFS4ERR_CLID_INUSE:		/* 10017 */
   4355 		p = "NFS4ERR_CLID_INUSE"; break;
   4356 	case NFS4ERR_RESOURCE:			/* 10018 */
   4357 		p = "NFS4ERR_RESOURCE"; break;
   4358 	case NFS4ERR_MOVED:			/* 10019 */
   4359 		p = "NFS4ERR_MOVED"; break;
   4360 	case NFS4ERR_NOFILEHANDLE:		/* 10020 */
   4361 		p = "NFS4ERR_NOFILEHANDLE"; break;
   4362 	case NFS4ERR_MINOR_VERS_MISMATCH:	/* 10021 */
   4363 		p = "NFS4ERR_MINOR_VERS_MISMATCH"; break;
   4364 	case NFS4ERR_STALE_CLIENTID: 		/* 10022 */
   4365 		p = "NFS4ERR_STALE_CLIENTID"; break;
   4366 	case NFS4ERR_STALE_STATEID:		/* 10023 */
   4367 		p = "NFS4ERR_STALE_STATEID"; break;
   4368 	case NFS4ERR_OLD_STATEID:		/* 10024 */
   4369 		p = "NFS4ERR_OLD_STATEID"; break;
   4370 	case NFS4ERR_BAD_STATEID:		/* 10025 */
   4371 		p = "NFS4ERR_BAD_STATEID"; break;
   4372 	case NFS4ERR_BAD_SEQID:			/* 10026 */
   4373 		p = "NFS4ERR_BAD_SEQID"; break;
   4374 	case NFS4ERR_NOT_SAME:			/* 10027 */
   4375 		p = "NFS4ERR_NOT_SAME"; break;
   4376 	case NFS4ERR_LOCK_RANGE:		/* 10028 */
   4377 		p = "NFS4ERR_LOCK_RANGE"; break;
   4378 	case NFS4ERR_SYMLINK:			/* 10029 */
   4379 		p = "NFS4ERR_SYMLINK"; break;
   4380 	case NFS4ERR_RESTOREFH:			/* 10030 */
   4381 		p = "NFS4ERR_RESTOREFH"; break;
   4382 	case NFS4ERR_LEASE_MOVED:		/* 10031 */
   4383 		p = "NFS4ERR_LEASE_MOVED"; break;
   4384 	case NFS4ERR_ATTRNOTSUPP:		/* 10032 */
   4385 		p = "NFS4ERR_ATTRNOTSUPP"; break;
   4386 	case NFS4ERR_NO_GRACE:			/* 10033 */
   4387 		p = "NFS4ERR_NO_GRACE"; break;
   4388 	case NFS4ERR_RECLAIM_BAD:		/* 10034 */
   4389 		p = "NFS4ERR_RECLAIM_BAD"; break;
   4390 	case NFS4ERR_RECLAIM_CONFLICT:		/* 10035 */
   4391 		p = "NFS4ERR_RECLAIM_CONFLICT"; break;
   4392 	case NFS4ERR_BADXDR:			/* 10036 */
   4393 		p = "NFS4ERR_BADXDR"; break;
   4394 	case NFS4ERR_LOCKS_HELD:		/* 10037 */
   4395 		p = "NFS4ERR_LOCKS_HELD"; break;
   4396 	case NFS4ERR_OPENMODE:			/* 10038 */
   4397 		p = "NFS4ERR_OPENMODE"; break;
   4398 	case NFS4ERR_BADOWNER:			/* 10039 */
   4399 		p = "NFS4ERR_BADOWNER"; break;
   4400 	case NFS4ERR_BADCHAR:			/* 10040 */
   4401 		p = "NFS4ERR_BADCHAR"; break;
   4402 	case NFS4ERR_BADNAME:			/* 10041 */
   4403 		p = "NFS4ERR_BADNAME"; break;
   4404 	case NFS4ERR_BAD_RANGE:			/* 10042 */
   4405 		p = "NFS4ERR_BAD_RANGE"; break;
   4406 	case NFS4ERR_LOCK_NOTSUPP:		/* 10043 */
   4407 		p = "NFS4ERR_LOCK_NOTSUPP"; break;
   4408 	case NFS4ERR_OP_ILLEGAL:		/* 10044 */
   4409 		p = "NFS4ERR_OP_ILLEGAL"; break;
   4410 	case NFS4ERR_DEADLOCK:			/* 10045 */
   4411 		p = "NFS4ERR_DEADLOCK"; break;
   4412 	case NFS4ERR_FILE_OPEN:			/* 10046 */
   4413 		p = "NFS4ERR_FILE_OPEN"; break;
   4414 	case NFS4ERR_ADMIN_REVOKED:		/* 10047 */
   4415 		p = "NFS4ERR_ADMIN_REVOKED"; break;
   4416 	case NFS4ERR_CB_PATH_DOWN:		/* 10048 */
   4417 		p = "NFS4ERR_CB_PATH_DOWN"; break;
   4418 	/* nfs4.1 error code */
   4419 	case NFS4ERR_BADIOMODE:			/* 10049 */
   4420 		p = "NFS4ERR_BADIOMODE"; break;
   4421 	case NFS4ERR_BADLAYOUT:			/* 10050 */
   4422 		p = "NFS4ERR_BADLAYOUT"; break;
   4423 	case NFS4ERR_BAD_SESSION_DIGEST:	/* 10051 */
   4424 		p = "NFS4ERR_BAD_SESSION_DIGEST"; break;
   4425 	case NFS4ERR_BADSESSION:		/* 10052 */
   4426 		p = "NFS4ERR_BADSESSION"; break;
   4427 	case NFS4ERR_BADSLOT:			/* 10053 */
   4428 		p = "NFS4ERR_BADSLOT"; break;
   4429 	case NFS4ERR_COMPLETE_ALREADY:		/* 10054 */
   4430 		p = "NFS4ERR_COMPLETE_ALREADY"; break;
   4431 	case NFS4ERR_CONN_NOT_BOUND_TO_SESSION:	/* 10055 */
   4432 		p = "NFS4ERR_CONN_NOT_BOUND_TO_SESSION"; break;
   4433 	case NFS4ERR_DELEG_ALREADY_WANTED:	/* 10056 */
   4434 		p = "NFS4ERR_DELEG_ALREADY_WANTED"; break;
   4435 	case NFS4ERR_BACK_CHAN_BUSY:		/* 10057 */
   4436 		p = "NFS4ERR_BACK_CHAN_BUSY"; break;
   4437 	case NFS4ERR_LAYOUTTRYLATER:		/* 10058 */
   4438 		p = "NFS4ERR_LAYOUTTRYLATER"; break;
   4439 	case NFS4ERR_LAYOUTUNAVAILABLE:		/* 10059 */
   4440 		p = "NFS4ERR_LAYOUTUNAVAILABLE"; break;
   4441 	case NFS4ERR_NOMATCHING_LAYOUT:		/* 10060 */
   4442 		p = "NFS4ERR_NOMATCHING_LAYOUT"; break;
   4443 	case NFS4ERR_RECALLCONFLICT:		/* 10061 */
   4444 		p = "NFS4ERR_RECALLCONFLICT"; break;
   4445 	case NFS4ERR_UNKNOWN_LAYOUTTYPE:	/* 10062 */
   4446 		p = "NFS4ERR_UNKNOWN_LAYOUTTYPE"; break;
   4447 	case NFS4ERR_SEQ_MISORDERED:		/* 10063 */
   4448 		p = "NFS4ERR_SEQ_MISORDERED"; break;
   4449 	case NFS4ERR_SEQUENCE_POS:		/* 10064 */
   4450 		p = "NFS4ERR_SEQUENCE_POS"; break;
   4451 	case NFS4ERR_REQ_TOO_BIG:		/* 10065 */
   4452 		p = "NFS4ERR_REQ_TOO_BIG"; break;
   4453 	case NFS4ERR_REP_TOO_BIG:		/* 10066 */
   4454 		p = "NFS4ERR_REP_TOO_BIG"; break;
   4455 	case NFS4ERR_REP_TOO_BIG_TO_CACHE:	/* 10067 */
   4456 		p = "NFS4ERR_REP_TOO_BIG_TO_CACHE"; break;
   4457 	case NFS4ERR_RETRY_UNCACHED_REP:	/* 10068 */
   4458 		p = "NFS4ERR_RETRY_UNCACHED_REP"; break;
   4459 	case NFS4ERR_UNSAFE_COMPOUND:		/* 10069 */
   4460 		p = "NFS4ERR_UNSAFE_COMPOUND"; break;
   4461 	case NFS4ERR_TOO_MANY_OPS:		/* 10070 */
   4462 		p = "NFS4ERR_TOO_MANY_OPS"; break;
   4463 	case NFS4ERR_OP_NOT_IN_SESSION:		/* 10071 */
   4464 		p = "NFS4ERR_OP_NOT_IN_SESSION"; break;
   4465 	case NFS4ERR_HASH_ALG_UNSUPP:		/* 10072 */
   4466 		p = "NFS4ERR_HASH_ALG_UNSUPP"; break;
   4467 	/* Error 10073 is unused. */
   4468 	case NFS4ERR_CLIENTID_BUSY:		/* 10074 */
   4469 		p = "NFS4ERR_CLIENTID_BUSY"; break;
   4470 	case NFS4ERR_PNFS_IO_HOLE:		/* 10075 */
   4471 		p = "NFS4ERR_PNFS_IO_HOLE"; break;
   4472 	case NFS4ERR_SEQ_FALSE_RETRY:		/* 10076 */
   4473 		p = "NFS4ERR_SEQ_FALSE_RETRY"; break;
   4474 	case NFS4ERR_BAD_HIGH_SLOT:		/* 10077 */
   4475 		p = "NFS4ERR_BAD_HIGH_SLOT"; break;
   4476 	case NFS4ERR_DEADSESSION:		/* 10078 */
   4477 		p = "NFS4ERR_DEADSESSION"; break;
   4478 	case NFS4ERR_ENCR_ALG_UNSUPP:		/* 10079 */
   4479 		p = "NFS4ERR_ENCR_ALG_UNSUPP"; break;
   4480 	case NFS4ERR_PNFS_NO_LAYOUT:		/* 10080 */
   4481 		p = "NFS4ERR_PNFS_NO_LAYOUT"; break;
   4482 	case NFS4ERR_NOT_ONLY_OP:		/* 10081 */
   4483 		p = "NFS4ERR_NOT_ONLY_OP"; break;
   4484 	case NFS4ERR_WRONG_CRED:		/* 10082 */
   4485 		p = "NFS4ERR_WRONG_CRED"; break;
   4486 	case NFS4ERR_WRONG_TYPE:		/* 10083 */
   4487 		p = "NFS4ERR_WRONG_TYPE"; break;
   4488 	case NFS4ERR_DIRDELEG_UNAVAIL:		/* 10084 */
   4489 		p = "NFS4ERR_DIRDELEG_UNAVAIL"; break;
   4490 	case NFS4ERR_REJECT_DELEG:		/* 10085 */
   4491 		p = "NFS4ERR_REJECT_DELEG"; break;
   4492 	case NFS4ERR_RETURNCONFLICT:		/* 10086 */
   4493 		p = "NFS4ERR_RETURNCONFLICT"; break;
   4494 	default:
   4495 		p = "(unknown error)"; break;
   4496 	}
   4497 
   4498 	return (p);
   4499 }
   4500 
   4501 char *
   4502 nfsstat4_to_name(int status)
   4503 {
   4504 	return (status_name(status));
   4505 }
   4506 
   4507 static char *
   4508 sum_sequenceid(sequenceid4 seq)
   4509 {
   4510 	static char buf[64];
   4511 
   4512 	snprintf(buf, sizeof (buf), "SQ=%u", seq);
   4513 	return (buf);
   4514 }
   4515 
   4516 static void
   4517 sum_sec_parm(char *buf, size_t buflen, callback_sec_parms4 parms)
   4518 {
   4519 	snprintf(buf, buflen, " %s", flavor_name(parms.cb_secflavor));
   4520 }
   4521 
   4522 static void
   4523 sumarg_create_session(char *buf, size_t buflen, void *obj)
   4524 {
   4525 	CREATE_SESSION4args *args = (CREATE_SESSION4args *)obj;
   4526 	char *bp = buf;
   4527 	uint_t i;
   4528 
   4529 	snprintf(bp, buflen, "%s ", sum_clientid(args->csa_clientid));
   4530 	bp += strlen(bp);
   4531 	snprintf(bp, buflen - (bp - buf), "%s ",
   4532 	    sum_sequenceid(args->csa_sequence));
   4533 	bp += strlen(bp);
   4534 	snprintf(bp, buflen - (bp - buf), "%s ", sum_sn_flags(args->csa_flags));
   4535 	bp += strlen(bp);
   4536 	snprintf(bp, buflen - (bp - buf), "CB=%u",
   4537 	    args->csa_cb_program);
   4538 
   4539 	for (i = 0; i < args->csa_sec_parms.csa_sec_parms_len; i++) {
   4540 		bp += strlen(bp);
   4541 		sum_sec_parm(bp, buflen - (bp - buf),
   4542 		    args->csa_sec_parms.csa_sec_parms_val[i]);
   4543 	}
   4544 }
   4545 
   4546 static char *
   4547 sum_sessionid(sessionid4 sid)
   4548 {
   4549 	static char buf[64];
   4550 
   4551 	snprintf(buf, sizeof (buf), "SID=%04X", sessionid_hash(sid));
   4552 	return (buf);
   4553 }
   4554 
   4555 static void
   4556 sumres_create_session(char *buf, size_t buflen, void *obj)
   4557 {
   4558 	CREATE_SESSION4res *res = (CREATE_SESSION4res *)obj;
   4559 	CREATE_SESSION4resok *resok;
   4560 	char *bp = buf;
   4561 
   4562 	strcpy(bp, status_name(res->csr_status));
   4563 	if (res->csr_status == NFS4_OK) {
   4564 		resok = &res->CREATE_SESSION4res_u.csr_resok4;
   4565 		bp += strlen(bp);
   4566 		snprintf(bp, buflen - (bp - buf), " %s",
   4567 		    sum_sessionid(resok->csr_sessionid));
   4568 		bp += strlen(bp);
   4569 		snprintf(bp, buflen - (bp - buf), " %s",
   4570 		    sum_sequenceid(resok->csr_sequence));
   4571 		bp += strlen(bp);
   4572 		snprintf(bp, buflen - (bp -buf), " %s",
   4573 		    sum_sn_flags(resok->csr_flags));
   4574 	}
   4575 }
   4576 
   4577 static void
   4578 detail_sequenceid(sequenceid4 seq)
   4579 {
   4580 	sprintf(get_line(0, 0), "Sequence ID = %u", seq);
   4581 }
   4582 
   4583 static void
   4584 detail_channel_attr(channel_attrs4 attr)
   4585 {
   4586 	int i;
   4587 
   4588 	detail_headerpadsize(attr.ca_headerpadsize);
   4589 	sprintf(get_line(0, 0), "\tMaximum request size = %u",
   4590 	    attr.ca_maxrequestsize);
   4591 	sprintf(get_line(0, 0), "\tMaximum response size = %u",
   4592 	    attr.ca_maxresponsesize);
   4593 	sprintf(get_line(0, 0), "\tMaximum response cache size = %u",
   4594 	    attr.ca_maxresponsesize_cached);
   4595 	sprintf(get_line(0, 0), "\tMaximum number of operations = %u",
   4596 	    attr.ca_maxoperations);
   4597 	sprintf(get_line(0, 0), "\tMaximum number of requests = %u",
   4598 	    attr.ca_maxrequests);
   4599 
   4600 	for (i = 0; i < attr.ca_rdma_ird.ca_rdma_ird_len; i++)
   4601 		sprintf(get_line(0, 0), "\tRDMA channel attribute [i] = %u",
   4602 		    attr.ca_rdma_ird.ca_rdma_ird_val[i]);
   4603 }
   4604 
   4605 static void
   4606 detail_sessionid(sessionid4 sid)
   4607 {
   4608 	sprintf(get_line(0, 0), "Session ID hash = [%04X] ",
   4609 	    sessionid_hash(sid));
   4610 	sprintf(get_line(0, 0), "    (16) %s",
   4611 	    tohex(sid, 16));
   4612 }
   4613 
   4614 static void
   4615 detail_headerpadsize(count4 size)
   4616 {
   4617 	sprintf(get_line(0, 0), "Header padding = %u", size);
   4618 }
   4619 
   4620 static void
   4621 detail_use_in_rdma_mode(bool_t val)
   4622 {
   4623 	sprintf(get_line(0, 0), "Use the connection in RDMA mode = %s",
   4624 	    val ? "TRUE" : "FALSE");
   4625 }
   4626 
   4627 static void
   4628 detail_authsys_parms(authsys_parms aup)
   4629 {
   4630 	uint_t i;
   4631 
   4632 	char *bp = get_line(0, 0);
   4633 	sprintf(bp, "time=%u machine=%s uid=%u gid=%u",
   4634 	    aup.aup_time, aup.aup_machname, aup.aup_uid, aup.aup_gid);
   4635 
   4636 	for (i = 0; i < aup.aup_len; i++) {
   4637 		bp += strlen(bp);
   4638 		sprintf(bp, " gids[i]=%u", aup.aup_gids[i]);
   4639 	}
   4640 }
   4641 
   4642 static void
   4643 detail_gss_handles4(gss_cb_handles4 hdl)
   4644 {
   4645 	uint_t i;
   4646 
   4647 	char *bp = get_line(0, 0);
   4648 	sprintf(bp, "Service = %d (%s); ",
   4649 	    hdl.gcbp_service, gss_svc_name(hdl.gcbp_service));
   4650 
   4651 	bp += strlen(bp);
   4652 	sprintf(bp, "The handle from server=%s;",
   4653 	    tohex(hdl.gcbp_handle_from_server.gsshandle4_t_val,
   4654 	    hdl.gcbp_handle_from_server.gsshandle4_t_len));
   4655 
   4656 	bp += strlen(bp);
   4657 	sprintf(bp, "The handle for client=%s",
   4658 	    tohex(hdl.gcbp_handle_from_client.gsshandle4_t_val,
   4659 	    hdl.gcbp_handle_from_client.gsshandle4_t_len));
   4660 }
   4661 
   4662 static void
   4663 detail_sec_parm(callback_sec_parms4 sec)
   4664 {
   4665 	sprintf(get_line(0, 0), "Flavor = %d (%s)",
   4666 	    sec.cb_secflavor, flavor_name(sec.cb_secflavor));
   4667 
   4668 	switch (sec.cb_secflavor) {
   4669 	case AUTH_NONE:
   4670 		break;
   4671 	case AUTH_SYS:
   4672 		detail_authsys_parms(sec.callback_sec_parms4_u.cbsp_sys_cred);
   4673 		break;
   4674 	case RPCSEC_GSS:
   4675 		detail_gss_handles4(sec.callback_sec_parms4_u.cbsp_gss_handles);
   4676 		break;
   4677 	defaul:
   4678 		break;
   4679 	}
   4680 }
   4681 
   4682 static void
   4683 dtlarg_create_session(void *obj)
   4684 {
   4685 	CREATE_SESSION4args *args = (CREATE_SESSION4args *)obj;
   4686 	callback_sec_parms4 parms;
   4687 	uint_t i;
   4688 
   4689 	detail_clientid(args->csa_clientid);
   4690 	detail_sequenceid(args->csa_sequence);
   4691 	sprintf(get_line(0, 0), "Flags = 0x%x (%s)",
   4692 	    args->csa_flags, detail_sn_flags(args->csa_flags));
   4693 	sprintf(get_line(0, 0), "Attributes of the fore channel: ");
   4694 	detail_channel_attr(args->csa_fore_chan_attrs);
   4695 	sprintf(get_line(0, 0), "Attributes of the back channel: ");
   4696 	detail_channel_attr(args->csa_back_chan_attrs);
   4697 	sprintf(get_line(0, 0), "Callback program ID = %u",
   4698 	    args->csa_cb_program);
   4699 	for (i = 0; i < args->csa_sec_parms.csa_sec_parms_len; i++)
   4700 		parms = args->csa_sec_parms.csa_sec_parms_val[i];
   4701 		detail_sec_parm(parms);
   4702 }
   4703 
   4704 static void
   4705 dtlres_create_session(void *obj)
   4706 {
   4707 	CREATE_SESSION4res *res = (CREATE_SESSION4res *)obj;
   4708 	CREATE_SESSION4resok *resok;
   4709 
   4710 	dtl_nfsstat4(obj);
   4711 	if (res->csr_status == NFS4_OK) {
   4712 		resok = &res->CREATE_SESSION4res_u.csr_resok4;
   4713 		detail_sessionid(resok->csr_sessionid);
   4714 		detail_sequenceid(resok->csr_sequence);
   4715 		sprintf(get_line(0, 0), "Flags = 0x%x (%s)",
   4716 		    resok->csr_flags, detail_sn_flags(resok->csr_flags));
   4717 		sprintf(get_line(0, 0), "Attributes of the fore channel:");
   4718 		detail_channel_attr(resok->csr_fore_chan_attrs);
   4719 		sprintf(get_line(0, 0), "Attributes of the back channel:");
   4720 		detail_channel_attr(resok->csr_back_chan_attrs);
   4721 	}
   4722 }
   4723 
   4724 static char *
   4725 sum_verifier(verifier4 verifier)
   4726 {
   4727 	static char buf[32];
   4728 
   4729 	snprintf(buf, sizeof (buf), "Verf=%s",
   4730 	    tohex(verifier, NFS4_VERIFIER_SIZE));
   4731 
   4732 	return (buf);
   4733 }
   4734 
   4735 static void
   4736 detail_verifier(verifier4 verifier)
   4737 {
   4738 	sprintf(get_line(0, 0), "Verifier=%s",
   4739 	    tohex(verifier, NFS4_VERIFIER_SIZE));
   4740 }
   4741 
   4742 static char *
   4743 print_ei_flag(uint32_t flag)
   4744 {
   4745 	static char buf[64];
   4746 	char *bp = buf;
   4747 	size_t buflen = sizeof (buf);
   4748 
   4749 	if (flag & EXCHGID4_FLAG_SUPP_MOVED_REFER) {
   4750 		snprintf(bp, buflen, "MOVED_REFER ");
   4751 		bp += strlen(buf);
   4752 	}
   4753 
   4754 	if (flag & EXCHGID4_FLAG_SUPP_MOVED_MIGR) {
   4755 		snprintf(bp, buflen - (bp - buf), "MOVED_MIGR ");
   4756 		bp += strlen(bp);
   4757 	}
   4758 
   4759 	if (flag & EXCHGID4_FLAG_BIND_PRINC_STATEID) {
   4760 		snprintf(bp, buflen - (bp - buf), "PRINC_STATEID ");
   4761 		bp += strlen(bp);
   4762 	}
   4763 
   4764 	if (flag & EXCHGID4_FLAG_USE_NON_PNFS) {
   4765 		snprintf(bp, buflen - (bp - buf), "NON_PNFS ");
   4766 		bp += strlen(bp);
   4767 	}
   4768 
   4769 	if (flag & EXCHGID4_FLAG_USE_PNFS_MDS) {
   4770 		snprintf(bp, buflen - (bp - buf), "PNFS_MDS ");
   4771 		bp += strlen(bp);
   4772 	}
   4773 
   4774 	if (flag & EXCHGID4_FLAG_USE_PNFS_DS) {
   4775 		snprintf(bp, buflen - (bp - buf), "PNFS_DS ");
   4776 		bp += strlen(bp);
   4777 	}
   4778 
   4779 	if (flag & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) {
   4780 		snprintf(bp, buflen - (bp - buf), "CONFIRMED_REC_A ");
   4781 		bp += strlen(bp);
   4782 	}
   4783 
   4784 	if (flag & EXCHGID4_FLAG_CONFIRMED_R) {
   4785 		snprintf(bp, buflen - (bp - buf), "CONFIRMED_R ");
   4786 		bp += strlen(bp);
   4787 	}
   4788 
   4789 	return (buf);
   4790 }
   4791 static char *
   4792 sum_ps_name(state_protect_how4 type)
   4793 {
   4794 	static char buf[32];
   4795 
   4796 	if (type < num_ps)
   4797 		return (ps_names[type].short_name);
   4798 	else {
   4799 		sprintf(buf, "ps_how=%d", type);
   4800 		return (buf);
   4801 	}
   4802 }
   4803 
   4804 static char *
   4805 detail_ps_name(state_protect_how4 type)
   4806 {
   4807 	static char buf[64];
   4808 
   4809 	if (type < num_ps)
   4810 		return (ps_names[type].long_name);
   4811 	else {
   4812 		sprintf(buf, "Unkown protect state type = %d", type);
   4813 		return (buf);
   4814 	}
   4815 }
   4816 
   4817 static void
   4818 sum_ei_state_protect4_a(char *buf, size_t buflen, state_protect4_a *spa)
   4819 {
   4820 	char *bp = buf;
   4821 
   4822 	snprintf(bp, buflen - (bp - buf), " %s",
   4823 	    sum_ps_name(spa->spa_how));
   4824 }
   4825 
   4826 static void
   4827 detail_ei_state_protect4_a(state_protect4_a *spa)
   4828 {
   4829 	sprintf(get_line(0, 0), "State protest = %s",
   4830 	    detail_ps_name(spa->spa_how));
   4831 }
   4832 
   4833 static void
   4834 sum_ei_state_protect4_r(char *buf, size_t buflen, state_protect4_r *spr)
   4835 {
   4836 	char *bp = buf;
   4837 
   4838 	snprintf(bp, buflen - (bp - buf), " %s",
   4839 	    sum_ps_name(spr->spr_how));
   4840 }
   4841 
   4842 static void
   4843 detail_ei_state_protect4_r(state_protect4_r *spr)
   4844 {
   4845 	sprintf(get_line(0, 0), "State protect = %s",
   4846 	    detail_ps_name(spr->spr_how));
   4847 }
   4848 
   4849 static void
   4850 sum_nfs_impl_id4(char *buf, size_t buflen, nfs_impl_id4 *impl)
   4851 {
   4852 	char *bp = buf;
   4853 
   4854 	snprintf(bp, buflen - (bp - buf), "%*s.",
   4855 	    impl->nii_name.utf8string_len,
   4856 	    impl->nii_name.utf8string_val);
   4857 	bp += strlen(bp);
   4858 	snprintf(bp, buflen - (bp - buf), "%*s ",
   4859 	    impl->nii_domain.utf8string_len,
   4860 	    impl->nii_domain.utf8string_val);
   4861 	bp += strlen(bp);
   4862 	snprintf(bp, buflen - (bp - buf), "%s ",
   4863 	    format_time(impl->nii_date.seconds, impl->nii_date.nseconds));
   4864 	bp += strlen(bp);
   4865 }
   4866 
   4867 static void
   4868 detail_nfs_impl_id4(nfs_impl_id4 *impl)
   4869 {
   4870 	sprintf(get_line(0, 0), "Domain = %*s",
   4871 	    impl->nii_domain.utf8string_len,
   4872 	    impl->nii_domain.utf8string_val);
   4873 	sprintf(get_line(0, 0), "Name = %*s",
   4874 	    impl->nii_name.utf8string_len,
   4875 	    impl->nii_name.utf8string_val);
   4876 	sprintf(get_line(0, 0), "Time = %s",
   4877 	    format_time(impl->nii_date.seconds, impl->nii_date.nseconds));
   4878 }
   4879 
   4880 static void
   4881 sumarg_exchange_id(char *buf, size_t buflen, void *obj)
   4882 {
   4883 	EXCHANGE_ID4args *args = (EXCHANGE_ID4args *)obj;
   4884 	nfs_impl_id4 *impl;
   4885 	char *bp = buf;
   4886 	int i, n;
   4887 
   4888 	snprintf(bp, buflen, "%s",
   4889 	    sum_verifier(args->eia_clientowner.co_verifier));
   4890 	bp += strlen(bp);
   4891 	snprintf(bp, buflen - (bp - buf), " COID=%04X",
   4892 	    cowner_hash(&args->eia_clientowner.co_ownerid));
   4893 	bp += strlen(bp);
   4894 	snprintf(bp, buflen - (bp - buf), " %s",
   4895 	    print_ei_flag(args->eia_flags));
   4896 	bp += strlen(bp);
   4897 	sum_ei_state_protect4_a(bp, buflen - (bp - buf),
   4898 	    &args->eia_state_protect);
   4899 	bp += strlen(bp);
   4900 
   4901 	n = args->eia_client_impl_id.eia_client_impl_id_len;
   4902 	impl = args->eia_client_impl_id.eia_client_impl_id_val;
   4903 	for (i = 0; i < n; i++) {
   4904 		sum_nfs_impl_id4(bp, buflen - (bp - buf), impl + i);
   4905 		bp += strlen(bp);
   4906 	}
   4907 }
   4908 
   4909 static void
   4910 dtlarg_exchange_id(void *obj)
   4911 {
   4912 	nfs_impl_id4 *impl;
   4913 	int n, i;
   4914 
   4915 	EXCHANGE_ID4args *args = (EXCHANGE_ID4args *)obj;
   4916 
   4917 	detail_verifier(args->eia_clientowner.co_verifier);
   4918 	sprintf(get_line(0, 0), "Client Owner ID hash = [%04X] ",
   4919 	    cowner_hash(&args->eia_clientowner.co_ownerid));
   4920 	sprintf(get_line(0, 0), "    (%d) %s",
   4921 	    args->eia_clientowner.co_ownerid.co_ownerid_len,
   4922 	    tohex(args->eia_clientowner.co_ownerid.co_ownerid_val,
   4923 	    args->eia_clientowner.co_ownerid.co_ownerid_len));
   4924 	sprintf(get_line(0, 0), "Flag = %s",
   4925 	    print_ei_flag(args->eia_flags));
   4926 	detail_ei_state_protect4_a(&args->eia_state_protect);
   4927 
   4928 	n = args->eia_client_impl_id.eia_client_impl_id_len;
   4929 	impl = args->eia_client_impl_id.eia_client_impl_id_val;
   4930 	for (i = 0; i < n; i++)
   4931 		detail_nfs_impl_id4(impl + i);
   4932 }
   4933 
   4934 static void
   4935 sumres_exchange_id(char *buf, size_t buflen, void *obj)
   4936 {
   4937 	EXCHANGE_ID4res *res = (EXCHANGE_ID4res *)obj;
   4938 	EXCHANGE_ID4resok *resok;
   4939 	char *bp = buf;
   4940 
   4941 	strcpy(bp, status_name(res->eir_status));
   4942 	if (res->eir_status != NFS4_OK)
   4943 		return;
   4944 
   4945 	resok = &res->EXCHANGE_ID4res_u.eir_resok4;
   4946 	bp += strlen(bp);
   4947 	snprintf(bp, buflen - (bp - buf), " %s",
   4948 	    sum_clientid(resok->eir_clientid));
   4949 	bp += strlen(bp);
   4950 	snprintf(bp, buflen - (bp - buf), " %s",
   4951 	    sum_sequenceid(resok->eir_sequenceid));
   4952 	bp += strlen(bp);
   4953 	snprintf(bp, buflen - (bp - buf), " %s",
   4954 	    print_ei_flag(resok->eir_flags));
   4955 	bp += strlen(bp);
   4956 	sum_ei_state_protect4_r(bp, buflen - (bp - buf),
   4957 	    &resok->eir_state_protect);
   4958 }
   4959 
   4960 static void
   4961 detail_server_owner(server_owner4 owner)
   4962 {
   4963 	sprintf(get_line(0, 0), "Server owner minor ID = %llu",
   4964 	    owner.so_minor_id);
   4965 	if (owner.so_major_id.so_major_id_len != 0)
   4966 		sprintf(get_line(0, 0), "Server owner major ID = %s",
   4967 		    tohex(owner.so_major_id.so_major_id_val,
   4968 		    owner.so_major_id.so_major_id_len));
   4969 	else
   4970 		sprintf(get_line(0, 0), "Server owner major ID is not set");
   4971 }
   4972 
   4973 static void
   4974 dtlres_exchange_id(void *obj)
   4975 {
   4976 	EXCHANGE_ID4res *res = (EXCHANGE_ID4res *)obj;
   4977 	EXCHANGE_ID4resok *resok;
   4978 	nfs_impl_id4 *impl;
   4979 	int i, n;
   4980 
   4981 	dtl_nfsstat4(obj);
   4982 	if (res->eir_status != NFS4_OK)
   4983 		return;
   4984 
   4985 	resok = &res->EXCHANGE_ID4res_u.eir_resok4;
   4986 	detail_clientid(resok->eir_clientid);
   4987 	detail_sequenceid(resok->eir_sequenceid);
   4988 	sprintf(get_line(0, 0), "Flag = %s",
   4989 	    print_ei_flag(resok->eir_flags));
   4990 	detail_ei_state_protect4_r(&resok->eir_state_protect);
   4991 	detail_server_owner(resok->eir_server_owner);
   4992 	if (resok->eir_server_scope.eir_server_scope_len == 0) {
   4993 		sprintf(get_line(0, 0), "Server scope is not set");
   4994 		return;
   4995 	}
   4996 	sprintf(get_line(0, 0), "Server scope = %s",
   4997 	    tohex(resok->eir_server_scope.eir_server_scope_val,
   4998 	    resok->eir_server_scope.eir_server_scope_len));
   4999 
   5000 	impl = resok->eir_server_impl_id.eir_server_impl_id_val;
   5001 	n = resok->eir_server_impl_id.eir_server_impl_id_len;
   5002 	for (i = 0; i < n; i++)
   5003 		detail_nfs_impl_id4(impl + i);
   5004 }
   5005 
   5006 static char *
   5007 sum_bcts_dir_from_client(channel_dir_from_client4 type)
   5008 {
   5009 	char *result;
   5010 
   5011 	switch (type) {
   5012 	case 0x1:
   5013 		result = "FORE";
   5014 		break;
   5015 	case 0x2:
   5016 		result = "BACK";
   5017 		break;
   5018 	case 0x3:
   5019 		result = "FORE or BOTH";
   5020 		break;
   5021 	case 0x7:
   5022 		result = "BACK or BOTH";
   5023 		break;
   5024 	default:
   5025 		result = "?";
   5026 		break;
   5027 	}
   5028 
   5029 	return (result);
   5030 }
   5031 
   5032 static void
   5033 detail_bcts_dir_from_client(channel_dir_from_client4 type)
   5034 {
   5035 	char *bp = get_line(0, 0);
   5036 
   5037 	switch (type) {
   5038 	case 0x1:
   5039 		sprintf(bp, "Binding to fore channel");
   5040 		break;
   5041 	case 0x2:
   5042 		sprintf(bp, "Binding to back channel");
   5043 		break;
   5044 	case 0x3:
   5045 		sprintf(bp, "Binding to fore or both channel");
   5046 		break;
   5047 	case 0x7:
   5048 		sprintf(bp, "Binding to back or both channel");
   5049 	default:
   5050 		sprintf(bp, "Binding to invalid channel");
   5051 		break;
   5052 	}
   5053 }
   5054 
   5055 static char *
   5056 sum_bcts_dir_from_server(channel_dir_from_server4 type)
   5057 {
   5058 	char *result;
   5059 
   5060 	switch (type) {
   5061 	case 0x1:
   5062 		result = "FORE";
   5063 		break;
   5064 	case 0x2:
   5065 		result = "BACK";
   5066 		break;
   5067 	case 0x3:
   5068 		result = "BOTH";
   5069 		break;
   5070 	default:
   5071 		result = "?";
   5072 		break;
   5073 	}
   5074 
   5075 	return (result);
   5076 }
   5077 
   5078 static void
   5079 detail_bcts_dir_from_server(channel_dir_from_server4 type)
   5080 {
   5081 	char *bp = get_line(0, 0);
   5082 
   5083 	switch (type) {
   5084 	case 0x1:
   5085 		sprintf(bp, "Binding to fore channel");
   5086 		break;
   5087 	case 0x2:
   5088 		sprintf(bp, "Binding to back channel");
   5089 		break;
   5090 	case 0x3:
   5091 		sprintf(bp, "Binding to both channel");
   5092 		break;
   5093 	default:
   5094 		sprintf(bp, "Binding to invalid channel");
   5095 		break;
   5096 	}
   5097 }
   5098 
   5099 static void
   5100 detail_bcts_nonce(uint64_t val)
   5101 {
   5102 	sprintf(get_line(0, 0), "Nonce value = %llu", val);
   5103 }
   5104 
   5105 static void
   5106 sumarg_bind_conn_to_session(char *buf, size_t buflen, void *obj)
   5107 {
   5108 	BIND_CONN_TO_SESSION4args *args = (BIND_CONN_TO_SESSION4args *)obj;
   5109 	char *bp = buf;
   5110 
   5111 	snprintf(bp, buflen, "%s", sum_sessionid(args->bctsa_sessid));
   5112 	bp += strlen(bp);
   5113 	snprintf(bp, buflen - (bp - buf), " %s",
   5114 	    sum_bcts_dir_from_client(args->bctsa_dir));
   5115 	bp += strlen(bp);
   5116 }
   5117 
   5118 static void
   5119 dtlarg_bind_conn_to_session(void *obj)
   5120 {
   5121 	BIND_CONN_TO_SESSION4args *args = (BIND_CONN_TO_SESSION4args *)obj;
   5122 
   5123 	detail_sessionid(args->bctsa_sessid);
   5124 	detail_bcts_dir_from_client(args->bctsa_dir);
   5125 	detail_use_in_rdma_mode(args->bctsa_use_conn_in_rdma_mode);
   5126 }
   5127 
   5128 static void
   5129 sumres_bind_conn_to_session(char *buf, size_t buflen, void *obj)
   5130 {
   5131 	BIND_CONN_TO_SESSION4res *res = (BIND_CONN_TO_SESSION4res *)obj;
   5132 	BIND_CONN_TO_SESSION4resok *resok;
   5133 	char *bp = buf;
   5134 
   5135 	strcpy(bp, status_name(res->bctsr_status));
   5136 	if (res->bctsr_status == NFS4_OK) {
   5137 		resok = &res->BIND_CONN_TO_SESSION4res_u.bctsr_resok4;
   5138 		snprintf(bp, buflen, "%s", sum_sessionid(resok->bctsr_sessid));
   5139 		bp += strlen(bp);
   5140 		snprintf(bp, buflen - (bp - buf), " %s",
   5141 		    sum_bcts_dir_from_server(resok->bctsr_dir));
   5142 		bp += strlen(bp);
   5143 	}
   5144 }
   5145 
   5146 static void
   5147 dtlres_bind_conn_to_session(void *obj)
   5148 {
   5149 	BIND_CONN_TO_SESSION4res *res = (BIND_CONN_TO_SESSION4res *)obj;
   5150 	BIND_CONN_TO_SESSION4resok *resok;
   5151 
   5152 	dtl_nfsstat4(obj);
   5153 	if (res->bctsr_status == NFS4_OK) {
   5154 		resok = &res->BIND_CONN_TO_SESSION4res_u.bctsr_resok4;
   5155 		detail_sessionid(resok->bctsr_sessid);
   5156 		detail_bcts_dir_from_server(resok->bctsr_dir);
   5157 		detail_use_in_rdma_mode(resok->bctsr_use_conn_in_rdma_mode);
   5158 	}
   5159 }
   5160 
   5161 static void
   5162 sumarg_backchannel_ctl(char *buf, size_t buflen, void *obj)
   5163 {
   5164 	BACKCHANNEL_CTL4args *args = (BACKCHANNEL_CTL4args *)obj;
   5165 	char *bp = buf;
   5166 	uint_t i;
   5167 
   5168 	sprintf(bp, "CB=%u", args->bca_cb_program);
   5169 	for (i = 0; i < args->bca_sec_parms.bca_sec_parms_len; i++) {
   5170 		bp += strlen(bp);
   5171 		sum_sec_parm(bp, buflen - (bp - buf),
   5172 		    args->bca_sec_parms.bca_sec_parms_val[i]);
   5173 	}
   5174 }
   5175 
   5176 static void
   5177 dtlarg_backchannel_ctl(void *obj)
   5178 {
   5179 	BACKCHANNEL_CTL4args *args = (BACKCHANNEL_CTL4args *)obj;
   5180 	uint_t i;
   5181 
   5182 	sprintf(get_line(0, 0), "Callback program ID = %u",
   5183 	    args->bca_cb_program);
   5184 	for (i = 0; i < args->bca_sec_parms.bca_sec_parms_len; i++)
   5185 		detail_sec_parm(args->bca_sec_parms.bca_sec_parms_val[i]);
   5186 }
   5187 
   5188 static void
   5189 sumarg_set_ssv(char *buf, size_t buflen, void *obj)
   5190 {
   5191 	SET_SSV4args *args = (SET_SSV4args *)obj;
   5192 
   5193 	snprintf(buf, buflen, "SSV=%s DG=%s",
   5194 	    tohex(args->ssa_ssv.ssa_ssv_val, args->ssa_ssv.ssa_ssv_len),
   5195 	    tohex(args->ssa_digest.ssa_digest_val,
   5196 	    args->ssa_digest.ssa_digest_len));
   5197 }
   5198 
   5199 static void
   5200 dtlarg_set_ssv(void *obj)
   5201 {
   5202 	SET_SSV4args *args = (SET_SSV4args *)obj;
   5203 
   5204 	sprintf(get_line(0, 0), "SSV = %s",
   5205 	    tohex(args->ssa_ssv.ssa_ssv_val, args->ssa_ssv.ssa_ssv_len));
   5206 	sprintf(get_line(0, 0), "Digest = %s",
   5207 	    tohex(args->ssa_digest.ssa_digest_val,
   5208 	    args->ssa_digest.ssa_digest_len));
   5209 }
   5210 
   5211 static void
   5212 sumres_set_ssv(char *buf, size_t buflen, void *obj)
   5213 {
   5214 	SET_SSV4res *res = (SET_SSV4res *)obj;
   5215 	SET_SSV4resok *resok;
   5216 	char *bp = buf;
   5217 
   5218 	strcpy(bp, status_name(res->ssr_status));
   5219 	bp += strlen(bp);
   5220 	if (res->ssr_status == NFS4_OK) {
   5221 		resok = &res->SET_SSV4res_u.ssr_resok4;
   5222 		snprintf(bp, buflen - (bp - buf), "DG=%s",
   5223 		    tohex(resok->ssr_digest.ssr_digest_val,
   5224 		    resok->ssr_digest.ssr_digest_len));
   5225 	}
   5226 }
   5227 
   5228 static void
   5229 dtlres_set_ssv(void *obj)
   5230 {
   5231 	SET_SSV4res *res = (SET_SSV4res *)obj;
   5232 	SET_SSV4resok *resok;
   5233 
   5234 	dtl_nfsstat4(obj);
   5235 	if (res->ssr_status == NFS4_OK) {
   5236 		resok = &res->SET_SSV4res_u.ssr_resok4;
   5237 		sprintf(get_line(0, 0), "Digest = %s",
   5238 		    tohex(resok->ssr_digest.ssr_digest_val,
   5239 		    resok->ssr_digest.ssr_digest_len));
   5240 	}
   5241 }
   5242 
   5243 static void
   5244 sumarg_destroy_session(char *buf, size_t buflen, void *obj)
   5245 {
   5246 	DESTROY_SESSION4args *args = (DESTROY_SESSION4args *)obj;
   5247 
   5248 	snprintf(buf, buflen, "%s", sum_sessionid(args->dsa_sessionid));
   5249 }
   5250 
   5251 static void
   5252 dtlarg_destroy_session(void *obj)
   5253 {
   5254 	DESTROY_SESSION4args *args = (DESTROY_SESSION4args *)obj;
   5255 
   5256 	detail_sessionid(args->dsa_sessionid);
   5257 }
   5258 
   5259 static void
   5260 sumarg_sequence(char *buf, size_t buflen, void *obj)
   5261 {
   5262 	SEQUENCE4args *args = (SEQUENCE4args *)obj;
   5263 	char *bp = buf;
   5264 
   5265 	snprintf(bp, buflen, "%s ", sum_sessionid(args->sa_sessionid));
   5266 	bp += strlen(bp);
   5267 	snprintf(bp, buflen - (bp - buf), "%s ",
   5268 	    sum_sequenceid(args->sa_sequenceid));
   5269 	bp += strlen(bp);
   5270 	snprintf(bp, buflen - (bp - buf), "SLID=%u", args->sa_slotid);
   5271 }
   5272 
   5273 static void
   5274 dtlarg_sequence(void *obj)
   5275 {
   5276 	SEQUENCE4args *args = (SEQUENCE4args *)obj;
   5277 
   5278 	detail_sessionid(args->sa_sessionid);
   5279 	detail_sequenceid(args->sa_sequenceid);
   5280 	sprintf(get_line(0, 0), "Slot ID = %u", args->sa_slotid);
   5281 	sprintf(get_line(0, 0), "Highest slotid = %u", args->sa_highest_slotid);
   5282 	sprintf(get_line(0, 0), "Cache flag = %s",
   5283 	    args->sa_cachethis? "TRUE" : "FALSE");
   5284 }
   5285 
   5286 static char *
   5287 sum_seq_status(uint32_t status)
   5288 {
   5289 	static char buf[32];
   5290 
   5291 	snprintf(buf, sizeof (buf), "ST=%x", status);
   5292 	return (buf);
   5293 }
   5294 
   5295 static void
   5296 detail_seq_status(uint32_t status)
   5297 {
   5298 	int bit;
   5299 
   5300 	sprintf(get_line(0, 0), "status = %x", status);
   5301 	for (bit = 0; bit < SEQ_STATUS_MAX; bit++) {
   5302 		if (status & (1 << bit)) {
   5303 			sprintf(get_line(0, 0), "\t%s",
   5304 			    seq_status[bit]);
   5305 		}
   5306 	}
   5307 }
   5308 
   5309 static void
   5310 sumres_sequence(char *buf, size_t buflen, void *obj)
   5311 {
   5312 	SEQUENCE4res *res = (SEQUENCE4res *)obj;
   5313 	SEQUENCE4resok *resok;
   5314 	char *bp = buf;
   5315 
   5316 	strncpy(bp, status_name(res->sr_status), buflen);
   5317 	if (res->sr_status == NFS4_OK) {
   5318 		resok = &res->SEQUENCE4res_u.sr_resok4;
   5319 		bp += strlen(bp);
   5320 		snprintf(bp, buflen - (bp - buf), " %s",
   5321 		    sum_sessionid(resok->sr_sessionid));
   5322 		bp += strlen(bp);
   5323 		snprintf(bp, buflen - (bp - buf), " %s",
   5324 		    sum_sequenceid(resok->sr_sequenceid));
   5325 		bp += strlen(bp);
   5326 		snprintf(bp, buflen - (bp - buf), " SLID=%u",
   5327 		    resok->sr_slotid);
   5328 		bp += strlen(bp);
   5329 		snprintf(bp, buflen - (bp - buf), " %s",
   5330 		    sum_seq_status(resok->sr_status_flags));
   5331 	}
   5332 }
   5333 
   5334 static void
   5335 dtlres_sequence(void *obj)
   5336 {
   5337 	SEQUENCE4res *res = (SEQUENCE4res *)obj;
   5338 	SEQUENCE4resok *resok;
   5339 
   5340 	dtl_nfsstat4(obj);
   5341 	if (res->sr_status == NFS4_OK) {
   5342 		resok = &res->SEQUENCE4res_u.sr_resok4;
   5343 		detail_sessionid(resok->sr_sessionid);
   5344 		detail_sequenceid(resok->sr_sequenceid);
   5345 		sprintf(get_line(0, 0), "Slot ID = %u", resok->sr_slotid);
   5346 		sprintf(get_line(0, 0), "Highest slotid = %u",
   5347 		    resok->sr_highest_slotid);
   5348 		sprintf(get_line(0, 0), "Target highest slotid = %u",
   5349 		    resok->sr_target_highest_slotid);
   5350 		detail_seq_status(resok->sr_status_flags);
   5351 	}
   5352 }
   5353 
   5354 static void
   5355 sumarg_cb_sequence(char *buf, size_t buflen, void *obj)
   5356 {
   5357 	CB_SEQUENCE4args *args = (CB_SEQUENCE4args *)obj;
   5358 	char *bp = buf;
   5359 
   5360 	snprintf(bp, buflen, "%s ", sum_sessionid(args->csa_sessionid));
   5361 	bp += strlen(bp);
   5362 	snprintf(bp, buflen - (bp - buf), "%s ",
   5363 	    sum_sequenceid(args->csa_sequenceid));
   5364 	bp += strlen(bp);
   5365 	snprintf(bp, buflen - (bp - buf), "SLID=%u", args->csa_slotid);
   5366 	bp += strlen(bp);
   5367 	snprintf(bp, buflen - (bp - buf), "cachethis=%d",
   5368 	    args->csa_cachethis);
   5369 	bp += strlen(bp);
   5370 	snprintf(bp, buflen - (bp - buf), "num calls = %d",
   5371 	    args->csa_referring_call_lists.csa_referring_call_lists_len);
   5372 	bp += strlen(bp);
   5373 }
   5374 
   5375 static void
   5376 detail_referring_call_list(uint_t ref, referring_call_list4 list)
   5377 {
   5378 	referring_call4 *call;
   5379 	uint_t i;
   5380 
   5381 	sprintf(get_line(0, 0),
   5382 	    "Referring call list[%u]: Session ID = %s",
   5383 	    i, tohex(list.rcl_sessionid, 16));
   5384 
   5385 	for (i = 0;
   5386 	    i < list.rcl_referring_calls.rcl_referring_calls_len;
   5387 	    i++) {
   5388 
   5389 		call = &list.rcl_referring_calls.rcl_referring_calls_val[i];
   5390 		sprintf(get_line(0, 0),
   5391 		    "    Sequence ID = %u   Slot ID = %u",
   5392 		    call->rc_sequenceid, call->rc_slotid);
   5393 	}
   5394 }
   5395 
   5396 static void
   5397 dtlarg_cb_sequence(void *obj)
   5398 {
   5399 	CB_SEQUENCE4args *args = (CB_SEQUENCE4args *)obj;
   5400 	referring_call_list4 *list;
   5401 	uint_t i;
   5402 
   5403 	detail_sessionid(args->csa_sessionid);
   5404 	detail_sequenceid(args->csa_sequenceid);
   5405 	sprintf(get_line(0, 0), "Slot ID = %u", args->csa_slotid);
   5406 	sprintf(get_line(0, 0), "Highest slot = %u", args->csa_highest_slotid);
   5407 	sprintf(get_line(0, 0), "Cache this = %s",
   5408 	    args->csa_cachethis ? "TRUE" : "FALSE");
   5409 
   5410 	list = args->csa_referring_call_lists.csa_referring_call_lists_val;
   5411 	for (i = 0;
   5412 	    i < args->csa_referring_call_lists.csa_referring_call_lists_len;
   5413 	    i++) {
   5414 		detail_referring_call_list(i, list[i]);
   5415 	}
   5416 }
   5417 
   5418 static void
   5419 sumres_cb_sequence(char *buf, size_t buflen, void *obj)
   5420 {
   5421 	CB_SEQUENCE4res *res = (CB_SEQUENCE4res *)obj;
   5422 	CB_SEQUENCE4resok *resok;
   5423 	char *bp = buf;
   5424 
   5425 	strcpy(bp, status_name(res->csr_status));
   5426 	if (res->csr_status != NFS4_OK)
   5427 		return;
   5428 
   5429 	resok = &res->CB_SEQUENCE4res_u.csr_resok4;
   5430 	bp += strlen(bp);
   5431 	snprintf(bp, buflen - (bp - buf), "%s ",
   5432 	    sum_sessionid(resok->csr_sessionid));
   5433 	bp += strlen(bp);
   5434 	snprintf(bp, buflen - (bp - buf), "%s ",
   5435 	    sum_sequenceid(resok->csr_sequenceid));
   5436 	bp += strlen(bp);
   5437 	snprintf(bp, buflen - (bp - buf), "SLID=%u ",
   5438 	    resok->csr_slotid);
   5439 	bp += strlen(bp);
   5440 	snprintf(bp, buflen - (bp - buf), "Highest SLID=%u ",
   5441 	    resok->csr_highest_slotid);
   5442 	bp += strlen(bp);
   5443 	snprintf(bp, buflen - (bp - buf), "Target highest SLID=%u ",
   5444 	    resok->csr_target_highest_slotid);
   5445 	bp += strlen(bp);
   5446 }
   5447 
   5448 static void
   5449 dtlres_cb_sequence(void *obj)
   5450 {
   5451 	CB_SEQUENCE4res *res = (CB_SEQUENCE4res *)obj;
   5452 	CB_SEQUENCE4resok *resok;
   5453 
   5454 	dtl_nfsstat4(obj);
   5455 	if (res->csr_status == NFS4_OK) {
   5456 		resok = &res->CB_SEQUENCE4res_u.csr_resok4;
   5457 		detail_sessionid(resok->csr_sessionid);
   5458 		detail_sequenceid(resok->csr_sequenceid);
   5459 		sprintf(get_line(0, 0), "Slot ID = %u", resok->csr_slotid);
   5460 		sprintf(get_line(0, 0), "Highest slotid = %u",
   5461 		    resok->csr_highest_slotid);
   5462 		sprintf(get_line(0, 0), "Target highest slotid = %u",
   5463 		    resok->csr_target_highest_slotid);
   5464 	}
   5465 }
   5466 
   5467 static void
   5468 sumarg_test_stateid(char *buf, size_t buflen, void *obj)
   5469 {
   5470 	TEST_STATEID4args *args = (TEST_STATEID4args *)obj;
   5471 	stateid4 *stateid;
   5472 	char prefix[32];
   5473 	char *bp = buf;
   5474 	uint_t i;
   5475 
   5476 	for (i = 0; i < args->ts_stateids.ts_stateids_len; i++) {
   5477 		stateid = &args->ts_stateids.ts_stateids_val[i];
   5478 		sprintf(prefix, "ST[%u]=", i);
   5479 		snprintf(bp, buflen - (bp - buf), "%s ",
   5480 		    cmn_sum_stateid(stateid, prefix));
   5481 		bp += strlen(bp);
   5482 	}
   5483 }
   5484 
   5485 static void
   5486 dtlarg_test_stateid(void *obj)
   5487 {
   5488 	TEST_STATEID4args *args = (TEST_STATEID4args *)obj;
   5489 	stateid4 *stateid;
   5490 	char prefix[32];
   5491 	uint_t i;
   5492 
   5493 	for (i = 0; i < args->ts_stateids.ts_stateids_len; i++) {
   5494 		stateid = &args->ts_stateids.ts_stateids_val[i];
   5495 		sprintf(prefix, "[%u] : ", i);
   5496 		cmn_detail_stateid(stateid, prefix);
   5497 	}
   5498 }
   5499 
   5500 static void
   5501 sum_ts_resok(char *buf, size_t buflen, TEST_STATEID4resok *resok)
   5502 {
   5503 	nfsstat4 status;
   5504 	char *bp = buf;
   5505 	uint_t i;
   5506 
   5507 	for (i = 0;
   5508 	    i < resok->tsr_status_codes.tsr_status_codes_len;
   5509 	    i++) {
   5510 
   5511 		status = resok->tsr_status_codes.tsr_status_codes_val[i];
   5512 		if (i == 0)
   5513 			snprintf(bp, buflen - (bp - buf), " ");
   5514 		if (i > 0)
   5515 			snprintf(bp, buflen - (bp - buf), ",");
   5516 		bp += strlen(bp);
   5517 		sum_nfsstat4(bp, buflen - (bp -buf), &status);
   5518 		bp += strlen(bp);
   5519 	}
   5520 }
   5521 
   5522 static void
   5523 sumres_test_stateid(char *buf, size_t buflen, void *obj)
   5524 {
   5525 	TEST_STATEID4res *res = (TEST_STATEID4res *)obj;
   5526 	char *bp = buf;
   5527 
   5528 	strncpy(bp, status_name(res->tsr_status), buflen);
   5529 	if (res->tsr_status == NFS4_OK) {
   5530 		bp += strlen(bp);
   5531 		sum_ts_resok(bp, buflen - (bp - buf),
   5532 		    &res->TEST_STATEID4res_u.tsr_resok4);
   5533 	}
   5534 }
   5535 
   5536 static void
   5537 detail_ts_resok(TEST_STATEID4resok *resok)
   5538 {
   5539 	nfsstat4 status;
   5540 	uint_t i;
   5541 
   5542 	for (i = 0;
   5543 	    i < resok->tsr_status_codes.tsr_status_codes_len;
   5544 	    i++) {
   5545 
   5546 		status = resok->tsr_status_codes.tsr_status_codes_val[i];
   5547 		sprintf(get_line(0, 0), "[%u] : Status %d (%s)",
   5548 		    i, status, status_name(status));
   5549 	}
   5550 }
   5551 
   5552 static void
   5553 dtlres_test_stateid(void *obj)
   5554 {
   5555 	TEST_STATEID4res *res = (TEST_STATEID4res *)obj;
   5556 	nfsstat4 status;
   5557 
   5558 	dtl_nfsstat4(obj);
   5559 	if (res->tsr_status == NFS4_OK)
   5560 		detail_ts_resok(&res->TEST_STATEID4res_u.tsr_resok4);
   5561 }
   5562 
   5563 static void
   5564 sumarg_free_stateid(char *buf, size_t buflen, void *obj)
   5565 {
   5566 	FREE_STATEID4args *args = (FREE_STATEID4args *)obj;
   5567 
   5568 	snprintf(buf, buflen, "%s", cmn_sum_stateid(&args->fsa_stateid, "ST="));
   5569 }
   5570 
   5571 static void
   5572 dtlarg_free_stateid(void *obj)
   5573 {
   5574 	FREE_STATEID4args *args = (FREE_STATEID4args *)obj;
   5575 
   5576 	cmn_detail_stateid(&args->fsa_stateid, "");
   5577 }
   5578 
   5579 static void
   5580 sumarg_get_dir_delegation(char *buf, size_t buflen, void *obj)
   5581 {
   5582 }
   5583 
   5584 static void
   5585 dtlarg_get_dir_delegation(void *obj)
   5586 {
   5587 }
   5588 
   5589 static void
   5590 sumres_get_dir_delegation(char *buf, size_t buflen, void *obj)
   5591 {
   5592 }
   5593 
   5594 static void
   5595 dtlres_get_dir_delegation(void *obj)
   5596 {
   5597 }
   5598 
   5599 static char *
   5600 detail_lortype_name(layoutrecall_type4 lortype)
   5601 {
   5602 	static char buf[32];
   5603 
   5604 	if (lortype < num_lortypes)
   5605 		return (lortype_names[lortype].long_name);
   5606 
   5607 	sprintf(buf, "lorec_type=%d", lortype);
   5608 	return (buf);
   5609 }
   5610 
   5611 
   5612 static char *
   5613 sum_lortype_name(layoutrecall_type4 lortype)
   5614 {
   5615 	static char buf[32];
   5616 
   5617 	if (lortype < num_lortypes)
   5618 		return (lortype_names[lortype].short_name);
   5619 
   5620 	sprintf(buf, "lorec_type=%d", lortype);
   5621 	return (buf);
   5622 }
   5623 
   5624 static char *
   5625 sum_lotype_name(layouttype4 type)
   5626 {
   5627 	static char buf[32];
   5628 
   5629 	if (type < num_lotypes)
   5630 		return (lotype_names[type].short_name);
   5631 	else {
   5632 		sprintf(buf, "lotype=%d", type);
   5633 		return (buf);
   5634 	}
   5635 }
   5636 
   5637 char *
   5638 detail_lotype_name(layouttype4 type)
   5639 {
   5640 	static char buf[64];
   5641 
   5642 	if (type >= 0 && type < num_lotypes)
   5643 		return (lotype_names[type].long_name);
   5644 	else {
   5645 		sprintf(buf, "Unknown layout type(%d)", type);
   5646 		return (buf);
   5647 	}
   5648 }
   5649 
   5650 static char *
   5651 sum_iomode_name(layoutiomode4 mode)
   5652 {
   5653 	static char buf[32];
   5654 
   5655 	if (mode < num_iomodes)
   5656 		return (iomode_names[mode].short_name);
   5657 	else {
   5658 		sprintf(buf, "iomode=%d", mode);
   5659 		return (buf);
   5660 	}
   5661 }
   5662 
   5663 char *
   5664 detail_iomode_name(layoutiomode4 mode)
   5665 {
   5666 	static char buf[64];
   5667 
   5668 	if (mode < num_iomodes)
   5669 		return (iomode_names[mode].long_name);
   5670 	else {
   5671 		sprintf(buf, "Unknown layout iomode = %d", mode);
   5672 		return (buf);
   5673 	}
   5674 }
   5675 
   5676 static char *
   5677 sum_lrtype_name(layoutreturn_type4 type)
   5678 {
   5679 	static char buf[32];
   5680 
   5681 	if (type < num_lrtypes)
   5682 		return (lrtype_names[type].short_name);
   5683 	else {
   5684 		sprintf(buf, "lrtype=%d", type);
   5685 		return (buf);
   5686 	}
   5687 }
   5688 
   5689 static char *
   5690 detail_lrtype_name(layoutreturn_type4 type)
   5691 {
   5692 	static char buf[64];
   5693 
   5694 	if (type < num_lrtypes)
   5695 		return (lrtype_names[type].long_name);
   5696 	else {
   5697 		sprintf(buf, "Unkown layoutreturn type = %d", type);
   5698 		return (buf);
   5699 	}
   5700 }
   5701 
   5702 static void
   5703 print_netaddr4(char *buf, size_t buflen, netaddr4 *na)
   5704 {
   5705 	char *copy = NULL;
   5706 	char *bp = buf;
   5707 
   5708 	/*
   5709 	 * We are always able to print addr/net.  We try to print
   5710 	 * more helpful formats for the more common netids.
   5711 	 *
   5712 	 * For "tcp", which is tcp/IPv4, we try to print hostname:portnumber,
   5713 	 * or if hostname cannot be determined, we try to print
   5714 	 * ipaddr:portnumber.
   5715 	 */
   5716 	if (strcmp("tcp", na->na_r_netid) == 0) {
   5717 #ifdef REVERSE_DNS
   5718 		char *copy = strdup(na->na_r_addr);
   5719 		struct hostent *host;
   5720 		struct in_addr addr;
   5721 		char *penultimate;
   5722 		char *ultimate;
   5723 		int port;
   5724 
   5725 		/* chop off final two octets */
   5726 		ultimate = strrchr(copy, '.');
   5727 		if (ultimate == NULL)
   5728 			goto failsafe;
   5729 		*(ultimate++) = '\0';
   5730 		penultimate = strrchr(copy, '.');
   5731 		if (penultimate == NULL)
   5732 			goto failsafe;
   5733 		*(penultimate++) = '\0';
   5734 
   5735 		/* convert final two octets into port number */
   5736 		errno = 0;
   5737 		port = strtol(penultimate, NULL, 0) << 8 +
   5738 		    strtol(ultimate, NULL, 0);
   5739 		if (errno != 0)
   5740 			goto failsafe;
   5741 
   5742 		/* try to convert IPv4 into host name */
   5743 		if ((inet_aton(copy, &addr)) &&
   5744 		    ((host = gethostbyaddr((char *)&addr,
   5745 		    4, AF_INET)) != NULL)) {
   5746 			snprintf(bp, buflen - (bp - buf), " %s", host->h_name);
   5747 		/* otherwise, use IP address */
   5748 		} else {
   5749 			snprintf(bp, buflen - (bp - buf), " %s", copy);
   5750 		}
   5751 		bp += strlen(bp);
   5752 		snprintf(bp, buflen - (bp - buf), ":%d/tcp", port);
   5753 #endif
   5754 		snprintf(bp, buflen - (bp - buf), "tcp:%s", na->na_r_addr);
   5755 
   5756 		return;
   5757 	}
   5758 
   5759 failsafe:
   5760 	/* just print "address/netid". */
   5761 	if (copy != NULL)
   5762 		free(copy);
   5763 	snprintf(bp, buflen - (bp - buf), "%s/%s",
   5764 	    na->na_r_addr, na->na_r_netid);
   5765 }
   5766 
   5767 static void
   5768 print_multipath_list4(char *buf, size_t buflen, multipath_list4 *mpl)
   5769 {
   5770 	char *bp = buf;
   5771 	netaddr4 *addr;
   5772 	int i, n;
   5773 
   5774 	n = mpl->multipath_list4_len;
   5775 	addr = mpl->multipath_list4_val;
   5776 
   5777 	for (i = 0; i < n; i++) {
   5778 		sprintf(bp, " [%u] ", i);
   5779 		bp += strlen(bp);
   5780 		print_netaddr4(bp, buflen - (bp - buf), addr + i);
   5781 		bp += strlen(bp);
   5782 	}
   5783 }
   5784 
   5785 
   5786 static void
   5787 sum_devaddr(char *buf, size_t buflen,
   5788 	device_addr4 *d_addr, layouttype4 type)
   5789 {
   5790 	nfsv4_1_file_layout_ds_addr4 devi;
   5791 	netaddr4 *addr;
   5792 	multipath_list4 *mpl;
   5793 	XDR xdr;
   5794 	int i, n;
   5795 	uint32_t *index;
   5796 	char *bp = buf;
   5797 
   5798 	if (type == LAYOUT4_NFSV4_1_FILES) {
   5799 		xdrmem_create(&xdr,
   5800 		    d_addr->da_addr_body.da_addr_body_val,
   5801 		    d_addr->da_addr_body.da_addr_body_len, XDR_DECODE);
   5802 		bzero(&devi, sizeof (devi));
   5803 		if (! xdr_nfsv4_1_file_layout_ds_addr4(&xdr, &devi))
   5804 			longjmp(xdr_err, 1);
   5805 
   5806 		n = devi.nflda_stripe_indices.nflda_stripe_indices_len;
   5807 		index = devi.nflda_stripe_indices.nflda_stripe_indices_val;
   5808 		for (i = 0; i < n; i++) {
   5809 			snprintf(bp, buflen - (bp - buf), "%s%u",
   5810 			    i ? "," : " ", index[i]);
   5811 			bp += strlen(bp);
   5812 		}
   5813 
   5814 		n = devi.nflda_multipath_ds_list.nflda_multipath_ds_list_len;
   5815 		mpl = devi.nflda_multipath_ds_list.nflda_multipath_ds_list_val;
   5816 		for (i = 0; i < n; i++) {
   5817 			print_multipath_list4(bp, buflen - (bp - buf), mpl + i);
   5818 			bp += strlen(bp);
   5819 		}
   5820 
   5821 		xdr_free(xdr_nfsv4_1_file_layout_ds_addr4, (char *)&devi);
   5822 	}
   5823 }
   5824 
   5825 static void
   5826 detail_devaddr(device_addr4 *d_addr, layouttype4 type)
   5827 {
   5828 	nfsv4_1_file_layout_ds_addr4 devi;
   5829 	netaddr4 *addr;
   5830 	multipath_list4 *mpl;
   5831 	XDR xdr;
   5832 	int i, n;
   5833 	uint32_t *index;
   5834 	char *bp, *buf;
   5835 	size_t buflen;
   5836 
   5837 	if (type == LAYOUT4_NFSV4_1_FILES) {
   5838 		xdrmem_create(&xdr,
   5839 		    d_addr->da_addr_body.da_addr_body_val,
   5840 		    d_addr->da_addr_body.da_addr_body_len, XDR_DECODE);
   5841 		bzero(&devi, sizeof (devi));
   5842 		if (! xdr_nfsv4_1_file_layout_ds_addr4(&xdr, &devi))
   5843 			longjmp(xdr_err, 1);
   5844 
   5845 		n = devi.nflda_stripe_indices.nflda_stripe_indices_len;
   5846 		index = devi.nflda_stripe_indices.nflda_stripe_indices_val;
   5847 		buf = get_line(0, 0);
   5848 		buflen = SUM_COMPND_MAX;
   5849 		sprintf(buf, "    stripe_indices:");
   5850 		bp = buf + strlen(buf);
   5851 		for (i = 0; i < n; i++) {
   5852 			snprintf(bp, buflen - (bp - buf), "%s%u",
   5853 			    i ? ", " : " ", index[i]);
   5854 			bp += strlen(bp);
   5855 		}
   5856 
   5857 		n = devi.nflda_multipath_ds_list.nflda_multipath_ds_list_len;
   5858 		mpl = devi.nflda_multipath_ds_list.nflda_multipath_ds_list_val;
   5859 		for (i = 0; i < n; i++) {
   5860 			buf = get_line(0, 0);
   5861 			buflen = SUM_COMPND_MAX;
   5862 			sprintf(buf, "    multipath_ds_list[%u]:", i);
   5863 			bp = buf + strlen(buf);
   5864 			print_multipath_list4(bp, buflen - (bp - buf), mpl + i);
   5865 		}
   5866 
   5867 		xdr_free(xdr_nfsv4_1_file_layout_ds_addr4, (char *)&devi);
   5868 	}
   5869 }
   5870 
   5871 static void
   5872 detail_deviceid(deviceid4 did)
   5873 {
   5874 	sprintf(get_line(0, 0), "Device ID hash = [%04X] ",
   5875 	    deviceid_hash(did));
   5876 	sprintf(get_line(0, 0), "    (16) %s",
   5877 	    tohex(did, 16));
   5878 }
   5879 
   5880 static void
   5881 sumarg_getdeviceinfo(char *buf, size_t buflen, void *obj)
   5882 {
   5883 	GETDEVICEINFO4args *args = (GETDEVICEINFO4args *)obj;
   5884 	char *bp = buf;
   5885 
   5886 	snprintf(bp, buflen, "DID=%04X",
   5887 	    deviceid_hash(args->gdia_device_id));
   5888 
   5889 	bp += strlen(bp);
   5890 	snprintf(bp, buflen - (bp - buf), " %s",
   5891 	    sum_lotype_name(args->gdia_layout_type));
   5892 
   5893 	bp += strlen(bp);
   5894 	snprintf(bp, buflen - (bp - buf), " MAX=%u",
   5895 	    args->gdia_maxcount);
   5896 }
   5897 
   5898 static void
   5899 dtlarg_getdeviceinfo(void *obj)
   5900 {
   5901 	GETDEVICEINFO4args *args = (GETDEVICEINFO4args *)obj;
   5902 	bitmap4 *bp;
   5903 	int i;
   5904 
   5905 	detail_deviceid(args->gdia_device_id);
   5906 	sprintf(get_line(0, 0), "Layout Type = %s",
   5907 	    detail_lotype_name(args->gdia_layout_type));
   5908 	sprintf(get_line(0, 0), "Max count = %u", args->gdia_maxcount);
   5909 	bp = &args->gdia_notify_types;
   5910 	sprintf(get_line(0, 0), "bitmap4_len = %u", bp->bitmap4_len);
   5911 	for (i = 0; i < bp->bitmap4_len; i++)
   5912 		sprintf(get_line(0, 0), "value: 0x%x", bp->bitmap4_val[i]);
   5913 }
   5914 
   5915 static void
   5916 sumres_getdeviceinfo(char *buf, size_t buflen, void *obj)
   5917 {
   5918 	GETDEVICEINFO4res *res = (GETDEVICEINFO4res *)obj;
   5919 	GETDEVICEINFO4resok *resok;
   5920 	char *bp = buf;
   5921 	layouttype4 lotype;
   5922 
   5923 	strcpy(bp, status_name(res->gdir_status));
   5924 	if (res->gdir_status == NFS4_OK) {
   5925 		resok = &res->GETDEVICEINFO4res_u.gdir_resok4;
   5926 		lotype = resok->gdir_device_addr.da_layout_type;
   5927 		bp += strlen(bp);
   5928 		if (lotype == LAYOUT4_NFSV4_1_FILES) {
   5929 			snprintf(bp, buflen - (bp - buf), " DEV=");
   5930 			bp += strlen(bp);
   5931 			sum_devaddr(bp, buflen - (bp - buf),
   5932 			    &resok->gdir_device_addr, lotype);
   5933 		}
   5934 	}
   5935 }
   5936 
   5937 static void
   5938 dtlres_getdeviceinfo(void *obj)
   5939 {
   5940 	GETDEVICEINFO4res *res = (GETDEVICEINFO4res *)obj;
   5941 	GETDEVICEINFO4resok *resok;
   5942 	layouttype4 lotype;
   5943 	char *buf;
   5944 
   5945 	dtl_nfsstat4(obj);
   5946 	if (res->gdir_status == NFS4_OK) {
   5947 		resok = &res->GETDEVICEINFO4res_u.gdir_resok4;
   5948 		lotype = resok->gdir_device_addr.da_layout_type;
   5949 		sprintf(get_line(0, 0), "Layout type = %s",
   5950 		    detail_lotype_name(lotype));
   5951 		if (lotype == LAYOUT4_NFSV4_1_FILES) {
   5952 			sprintf(get_line(0, 0), "Device address: ");
   5953 			detail_devaddr(&resok->gdir_device_addr, lotype);
   5954 		}
   5955 	}
   5956 }
   5957 
   5958 static void
   5959 sumarg_getdevicelist(char *buf, size_t buflen, void *obj)
   5960 {
   5961 	GETDEVICELIST4args *args = (GETDEVICELIST4args *)obj;
   5962 	char *bp = buf;
   5963 
   5964 	snprintf(bp, buflen - (bp - buf), "%s",
   5965 	    sum_lotype_name(args->gdla_layout_type));
   5966 	bp += strlen(bp);
   5967 	snprintf(bp, buflen - (bp - buf), " Max=%u", args->gdla_maxdevices);
   5968 	bp += strlen(bp);
   5969 	snprintf(bp, buflen - (bp - buf), " CK=%llx", args->gdla_cookie);
   5970 	bp += strlen(bp);
   5971 	snprintf(bp, buflen - (bp - buf), " %s",
   5972 	    sum_verifier(args->gdla_cookieverf));
   5973 }
   5974 
   5975 static void
   5976 dtlarg_getdevicelist(void *obj)
   5977 {
   5978 	GETDEVICELIST4args *args = (GETDEVICELIST4args *)obj;
   5979 
   5980 	sprintf(get_line(0, 0), "%s",
   5981 	    detail_lotype_name(args->gdla_layout_type));
   5982 	sprintf(get_line(0, 0), "Max device count = %u", args->gdla_maxdevices);
   5983 	sprintf(get_line(0, 0), "NFS Cookie = %llx", args->gdla_cookie);
   5984 	detail_verifier(args->gdla_cookieverf);
   5985 }
   5986 
   5987 static void
   5988 sum_devicelist(char *buf, size_t buflen, GETDEVICELIST4resok *resok)
   5989 {
   5990 	deviceid4 *devid;
   5991 	char *bp = buf;
   5992 	uint_t i, len;
   5993 
   5994 	len = resok->gdlr_deviceid_list.gdlr_deviceid_list_len;
   5995 	if (!len) {
   5996 		snprintf(bp, buflen, "NO_DEV");
   5997 		return;
   5998 	}
   5999 	for (i = 0; i < len; i++) {
   6000 		devid = &resok->gdlr_deviceid_list.gdlr_deviceid_list_val[i];
   6001 		snprintf(bp, buflen - (bp - buf), " DEV[i]=%04X ",
   6002 		    deviceid_hash(*devid));
   6003 		bp += strlen(bp);
   6004 	}
   6005 }
   6006 
   6007 static void
   6008 sumres_getdevicelist(char *buf, size_t buflen, void *obj)
   6009 {
   6010 	GETDEVICELIST4res *res = (GETDEVICELIST4res *)obj;
   6011 	GETDEVICELIST4resok *resok;
   6012 	char *bp = buf;
   6013 
   6014 	strcpy(bp, status_name(res->gdlr_status));
   6015 	if (res->gdlr_status == NFS4_OK) {
   6016 		resok = &res->GETDEVICELIST4res_u.gdlr_resok4;
   6017 		bp += strlen(bp);
   6018 		snprintf(bp, buflen - (bp - buf), " CK=%llx",
   6019 		    resok->gdlr_cookie);
   6020 			bp += strlen(bp);
   6021 		snprintf(bp, buflen - (bp - buf), " %s",
   6022 		    sum_verifier(resok->gdlr_cookieverf));
   6023 		bp += strlen(bp);
   6024 		sum_devicelist(bp, buflen - (bp - buf), resok);
   6025 	}
   6026 }
   6027 
   6028 static void
   6029 detail_devicelist(GETDEVICELIST4resok *resok)
   6030 {
   6031 	deviceid4 *devid;
   6032 	uint_t i, len;
   6033 	char *buf;
   6034 	layouttype4 lotype;
   6035 
   6036 	len = resok->gdlr_deviceid_list.gdlr_deviceid_list_len;
   6037 	if (!len) {
   6038 		sprintf(get_line(0, 0), "No device list");
   6039 		return;
   6040 	}
   6041 	for (i = 0; i < len; i++) {
   6042 		devid = &resok->gdlr_deviceid_list.gdlr_deviceid_list_val[i];
   6043 		detail_deviceid(*devid);
   6044 	}
   6045 }
   6046 
   6047 static void
   6048 dtlres_getdevicelist(void *obj)
   6049 {
   6050 	GETDEVICELIST4res *res = (GETDEVICELIST4res *)obj;
   6051 	GETDEVICELIST4resok *resok;
   6052 
   6053 	dtl_nfsstat4(obj);
   6054 	if (res->gdlr_status == NFS4_OK) {
   6055 		resok = &res->GETDEVICELIST4res_u.gdlr_resok4;
   6056 		sprintf(get_line(0, 0), "NFS Cookie = %llx",
   6057 		    resok->gdlr_cookie);
   6058 		detail_verifier(resok->gdlr_cookieverf);
   6059 		detail_devicelist(resok);
   6060 		sprintf(get_line(0, 0), "EOF flag = %s",
   6061 		    resok->gdlr_eof ? "TRUE" : "FALSE");
   6062 	}
   6063 }
   6064 
   6065 static void
   6066 sumarg_layoutcommit(char *buf, size_t buflen, void *obj)
   6067 {
   6068 	LAYOUTCOMMIT4args *args = (LAYOUTCOMMIT4args *)obj;
   6069 	newoffset4 *noff;
   6070 	nfstime4 *time;
   6071 	char *bp = buf;
   6072 
   6073 	snprintf(bp, buflen - (bp - buf), "%s",
   6074 	    sum_stateid(&args->loca_stateid));
   6075 }
   6076 
   6077 static void
   6078 dtlarg_layoutcommit(void *obj)
   6079 {
   6080 	LAYOUTCOMMIT4args *args = (LAYOUTCOMMIT4args *)obj;
   6081 	newoffset4 *noff;
   6082 	nfstime4 *time;
   6083 
   6084 	sprintf(get_line(0, 0), "Offset = %llu",
   6085 	    args->loca_offset);
   6086 	sprintf(get_line(0, 0), "Length = %llu",
   6087 	    args->loca_length);
   6088 
   6089 	sprintf(get_line(0, 0), "Reclaim = %s",
   6090 	    args->loca_reclaim ? "TRUE" : "FALSE");
   6091 
   6092 	detail_stateid(&args->loca_stateid);
   6093 
   6094 	if (args->loca_last_write_offset.no_newoffset) {
   6095 		noff = &args->loca_last_write_offset;
   6096 		sprintf(get_line(0, 0), "Last write offset = %llu",
   6097 		    noff->newoffset4_u.no_offset);
   6098 	} else
   6099 		sprintf(get_line(0, 0), "No last_write_offset provided");
   6100 
   6101 	if (args->loca_time_modify.nt_timechanged) {
   6102 		time = &args->loca_time_modify.newtime4_u.nt_time;
   6103 		sprintf(get_line(0, 0), "Time modify = %s",
   6104 		    format_time(time->seconds, time->nseconds));
   6105 	} else
   6106 		sprintf(get_line(0, 0), "No time_modify provided");
   6107 
   6108 	sprintf(get_line(0, 0), "Layoutupdate type = %s",
   6109 	    detail_lotype_name(args->loca_layoutupdate.lou_type));
   6110 	sprintf(get_line(0, 0), "Layoutupdate data = %s",
   6111 	    tohex(args->loca_layoutupdate.lou_body.lou_body_val,
   6112 	    args->loca_layoutupdate.lou_body.lou_body_len));
   6113 }
   6114 
   6115 static void
   6116 sumres_layoutcommit(char *buf, size_t buflen, void *obj)
   6117 {
   6118 	LAYOUTCOMMIT4res *res = (LAYOUTCOMMIT4res *)obj;
   6119 	LAYOUTCOMMIT4resok *resok;
   6120 	char *bp = buf;
   6121 
   6122 	strcpy(bp, status_name(res->locr_status));
   6123 	if (res->locr_status == NFS4_OK) {
   6124 		resok = &res->LAYOUTCOMMIT4res_u.locr_resok4;
   6125 		bp += strlen(bp);
   6126 		if (resok->locr_newsize.ns_sizechanged)
   6127 			snprintf(bp, buflen - (bp - buf), " NSIZE=%llu",
   6128 			    resok->locr_newsize.newsize4_u.ns_size);
   6129 		else
   6130 			snprintf(bp, buflen - (bp - buf), " NO_CHANGE");
   6131 	}
   6132 }
   6133 
   6134 static void
   6135 dtlres_layoutcommit(void *obj)
   6136 {
   6137 	LAYOUTCOMMIT4res *res = (LAYOUTCOMMIT4res *)obj;
   6138 	LAYOUTCOMMIT4resok *resok;
   6139 
   6140 	dtl_nfsstat4(obj);
   6141 	if (res->locr_status == NFS4_OK) {
   6142 		resok = &res->LAYOUTCOMMIT4res_u.locr_resok4;
   6143 		if (resok->locr_newsize.ns_sizechanged)
   6144 			sprintf(get_line(0, 0), "Changed size = %llu",
   6145 			    resok->locr_newsize.newsize4_u.ns_size);
   6146 		else
   6147 			sprintf(get_line(0, 0), "The size is not changed");
   6148 	}
   6149 }
   6150 
   6151 static void
   6152 sumarg_layoutget(char *buf, size_t buflen, void *obj)
   6153 {
   6154 	LAYOUTGET4args *args = (LAYOUTGET4args *)obj;
   6155 	char *bp = buf;
   6156 
   6157 	snprintf(bp, buflen - (bp - buf), "%s",
   6158 	    sum_stateid(&args->loga_stateid));
   6159 }
   6160 
   6161 static void
   6162 dtlarg_layoutget(void *obj)
   6163 {
   6164 	LAYOUTGET4args *args = (LAYOUTGET4args *)obj;
   6165 
   6166 	sprintf(get_line(0, 0), "Signal layout available = %s",
   6167 	    args->loga_signal_layout_avail ? "TRUE" : "FALSE");
   6168 	sprintf(get_line(0, 0), "Layout type = %s",
   6169 	    detail_lotype_name(args->loga_layout_type));
   6170 	sprintf(get_line(0, 0), "Layout iomode = %s",
   6171 	    detail_iomode_name(args->loga_iomode));
   6172 	sprintf(get_line(0, 0), "Offset = %llu",
   6173 	    args->loga_offset);
   6174 	sprintf(get_line(0, 0), "Length = %llu",
   6175 	    args->loga_length);
   6176 	sprintf(get_line(0, 0), "Minimum size overlap = %llu",
   6177 	    args->loga_minlength);
   6178 	detail_stateid(&args->loga_stateid);
   6179 	sprintf(get_line(0, 0), "Max count = %u",
   6180 	    args->loga_maxcount);
   6181 }
   6182 
   6183 static void
   6184 sum_file_layout(char *buf, size_t buflen, layout4 *lo)
   6185 {
   6186 	static nfsv4_1_file_layout4 fl;
   6187 	char *bp = buf;
   6188 	uint_t i, n;
   6189 	nfs_fh4 *fh;
   6190 	XDR xdr;
   6191 
   6192 	bzero(&fl, sizeof (fl));
   6193 	xdrmem_create(&xdr,
   6194 	    lo->lo_content.loc_body.loc_body_val,
   6195 	    lo->lo_content.loc_body.loc_body_len,
   6196 	    XDR_DECODE);
   6197 	if (! xdr_nfsv4_1_file_layout4(&xdr, &fl))
   6198 		longjmp(xdr_err, 1);
   6199 
   6200 	snprintf(bp, buflen, " %04X 0x%x",
   6201 	    deviceid_hash(fl.nfl_deviceid), fl.nfl_util);
   6202 	bp += strlen(bp);
   6203 	n = fl.nfl_fh_list.nfl_fh_list_len;
   6204 	fh = fl.nfl_fh_list.nfl_fh_list_val;
   6205 	for (i = 0; i < n; i++) {
   6206 		strncat(bp, " ", buflen - (bp - buf));
   6207 		bp += strlen(bp);
   6208 		if (i == fl.nfl_first_stripe_index) {
   6209 			strncat(bp, "<start>", buflen - (bp - buf));
   6210 			bp += strlen(bp);
   6211 		}
   6212 		snprintf(bp, buflen - (bp - buf), "%04X", fh4_hash(fh + i));
   6213 		bp += strlen(bp);
   6214 	}
   6215 
   6216 	xdr_free(xdr_nfsv4_1_file_layout4, (char *)&fl);
   6217 }
   6218 
   6219 static void
   6220 sumres_layoutget(char *buf, size_t buflen, void *obj)
   6221 {
   6222 	LAYOUTGET4res *res = (LAYOUTGET4res *)obj;
   6223 	LAYOUTGET4resok *resok;
   6224 	layout4 *lo;
   6225 	char *bp = buf;
   6226 
   6227 	strcpy(bp, status_name(res->logr_status));
   6228 	if (res->logr_status == NFS4_OK) {
   6229 		resok = &res->LAYOUTGET4res_u.logr_resok4;
   6230 		bp += strlen(bp);
   6231 		snprintf(bp, buflen - (bp - buf), "%s",
   6232 		    sum_stateid(&resok->logr_stateid));
   6233 	} else if (res->logr_status == NFS4ERR_LAYOUTTRYLATER) {
   6234 		bp += strlen(bp);
   6235 		snprintf(bp, buflen - (bp - buf), "%s",
   6236 		    res->LAYOUTGET4res_u.logr_will_signal_layout_avail ?
   6237 		    "SIGNAL" : "NO_SIGNAL");
   6238 	}
   6239 }
   6240 
   6241 void
   6242 detail_file_layout(layout4 *lo)
   6243 {
   6244 	nfsv4_1_file_layout4 fl;
   6245 	uint_t i;
   6246 	XDR xdr;
   6247 
   6248 	bzero(&fl, sizeof (fl));
   6249 	xdrmem_create(&xdr,
   6250 	    lo->lo_content.loc_body.loc_body_val,
   6251 	    lo->lo_content.loc_body.loc_body_len,
   6252 	    XDR_DECODE);
   6253 	if (! xdr_nfsv4_1_file_layout4(&xdr, &fl))
   6254 		longjmp(xdr_err, 1);
   6255 
   6256 	detail_deviceid(fl.nfl_deviceid);
   6257 	sprintf(get_line(0, 0), "Util = 0x%x", fl.nfl_util);
   6258 	sprintf(get_line(0, 0), "    stripe_unit = %d", fl.nfl_util >> 6);
   6259 	if (fl.nfl_util & NFL4_UFLG_DENSE)
   6260 		sprintf(get_line(0, 0), "    UFLG_DENSE");
   6261 	if (fl.nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
   6262 		sprintf(get_line(0, 0), "    UFLG_COMMIT_THRU_MDS");
   6263 	sprintf(get_line(0, 0), "First stripe = %d", fl.nfl_first_stripe_index);
   6264 	for (i = 0; i < fl.nfl_fh_list.nfl_fh_list_len; i++) {
   6265 		sprintf(get_line(0, 0), "fh[%u] = (%u) %s",
   6266 		    i, fl.nfl_fh_list.nfl_fh_list_val[i].nfs_fh4_len,
   6267 		    tohex(fl.nfl_fh_list.nfl_fh_list_val[i].nfs_fh4_val,
   6268 		    fl.nfl_fh_list.nfl_fh_list_val[i].nfs_fh4_len));
   6269 	}
   6270 	xdr_free(xdr_nfsv4_1_file_layout4, (char *)&fl);
   6271 }
   6272 
   6273 static void
   6274 dtlres_layoutget(void *obj)
   6275 {
   6276 	LAYOUTGET4res *res = (LAYOUTGET4res *)obj;
   6277 	LAYOUTGET4resok *resok;
   6278 	layout4 *lo;
   6279 	int i;
   6280 
   6281 	dtl_nfsstat4(obj);
   6282 	if (res->logr_status == NFS4_OK) {
   6283 		resok = &res->LAYOUTGET4res_u.logr_resok4;
   6284 		detail_stateid(&resok->logr_stateid);
   6285 		for (i = 0; i < resok->logr_layout.logr_layout_len; i++) {
   6286 			lo = &resok->logr_layout.logr_layout_val[i];
   6287 			sprintf(get_line(0, 0), "Layout [%u]:", i);
   6288 			sprintf(get_line(0, 0), "Return layout on close = %s",
   6289 			    resok->logr_return_on_close ? "TRUE" : "FALSE");
   6290 			sprintf(get_line(0, 0), "Layout offset = %llu",
   6291 			    lo->lo_offset);
   6292 			sprintf(get_line(0, 0), "Layout length = %llu",
   6293 			    lo->lo_length);
   6294 			sprintf(get_line(0, 0), "Layout iomode = %s",
   6295 			    detail_iomode_name(lo->lo_iomode));
   6296 			sprintf(get_line(0, 0), "Layout type = %s",
   6297 			    detail_lotype_name(lo->lo_content.loc_type));
   6298 			if (lo->lo_content.loc_type == LAYOUT4_NFSV4_1_FILES) {
   6299 				detail_file_layout(lo);
   6300 			} else
   6301 				sprintf(get_line(0, 0), "Non-file layout = %s",
   6302 				    tohex(lo->lo_content.loc_body.loc_body_val,
   6303 				    lo->lo_content.loc_body.loc_body_len));
   6304 		}
   6305 	} else if (res->logr_status == NFS4ERR_LAYOUTTRYLATER) {
   6306 		sprintf(get_line(0, 0), "Will signal layout avail = %s",
   6307 		    res->LAYOUTGET4res_u.logr_will_signal_layout_avail ?
   6308 		    "TRUE" : "FALSE");
   6309 	}
   6310 }
   6311 
   6312 static void
   6313 sumarg_layoutreturn(char *buf, size_t buflen, void *obj)
   6314 {
   6315 	LAYOUTRETURN4args *args = (LAYOUTRETURN4args *)obj;
   6316 	layoutreturn4 *lr = &args->lora_layoutreturn;
   6317 	char *bp = buf;
   6318 
   6319 	if (lr->lr_returntype == LAYOUTRETURN4_FILE)
   6320 		snprintf(bp, buflen - (bp - buf), "%s",
   6321 		    sum_stateid(&lr->layoutreturn4_u.lr_layout.lrf_stateid));
   6322 	else
   6323 		snprintf(bp, buflen - (bp - buf), "Returntype=%s",
   6324 		    sum_lrtype_name(lr->lr_returntype));
   6325 }
   6326 
   6327 static void
   6328 dtlarg_layoutreturn(void *obj)
   6329 {
   6330 	LAYOUTRETURN4args *args = (LAYOUTRETURN4args *)obj;
   6331 	layoutreturn4 *lr = &args->lora_layoutreturn;
   6332 
   6333 	sprintf(get_line(0, 0), "Reclaim = %s",
   6334 	    args->lora_reclaim ? "TRUE" : "FALSE");
   6335 	sprintf(get_line(0, 0), "Layout type = %s",
   6336 	    detail_lotype_name(args->lora_layout_type));
   6337 	sprintf(get_line(0, 0), "Layout iomode = %s",
   6338 	    detail_iomode_name(args->lora_iomode));
   6339 	sprintf(get_line(0, 0), "Layoutreturn type = %s",
   6340 	    detail_lrtype_name(lr->lr_returntype));
   6341 	if (lr->lr_returntype == LAYOUTRETURN4_FILE) {
   6342 		sprintf(get_line(0, 0), "Layoutreturn Offset = %llu",
   6343 		    lr->layoutreturn4_u.lr_layout.lrf_offset);
   6344 		sprintf(get_line(0, 0), "Layoutreturn Length = %llu",
   6345 		    lr->layoutreturn4_u.lr_layout.lrf_length);
   6346 		detail_stateid(&lr->layoutreturn4_u.lr_layout.lrf_stateid);
   6347 	}
   6348 }
   6349 
   6350 
   6351 static void
   6352 sumarg_secinfo_no_name(char *buf, size_t buflen, void *obj)
   6353 {
   6354 	char style;
   6355 
   6356 	switch (*(SECINFO_NO_NAME4args *)obj) {
   6357 	case SECINFO_STYLE4_CURRENT_FH:
   6358 		style = 'C';
   6359 		break;
   6360 	case SECINFO_STYLE4_PARENT:
   6361 		style = 'P';
   6362 		break;
   6363 	default:
   6364 		style = '?';
   6365 		break;
   6366 	}
   6367 	snprintf(buf, buflen, " ST=%c", style);
   6368 }
   6369 
   6370 static void
   6371 dtlarg_secinfo_no_name(void *obj)
   6372 {
   6373 	char *style;
   6374 
   6375 	switch (*(SECINFO_NO_NAME4args *)obj) {
   6376 	case SECINFO_STYLE4_CURRENT_FH:
   6377 		style = "CURRENT_FH";
   6378 		break;
   6379 	case SECINFO_STYLE4_PARENT:
   6380 		style = "PARENT";
   6381 		break;
   6382 	default:
   6383 		style = "???";
   6384 		break;
   6385 	}
   6386 	sprintf(get_line(0, 0), "Style = %s", style);
   6387 }
   6388 
   6389 static void
   6390 sumarg_want_delegation(char *buf, size_t buflen, void *obj)
   6391 {
   6392 }
   6393 
   6394 static void
   6395 dtlarg_want_delegation(void *obj)
   6396 {
   6397 }
   6398 
   6399 static void
   6400 sumres_want_delegation(char *buf, size_t buflen, void *obj)
   6401 {
   6402 }
   6403 
   6404 static void
   6405 dtlres_want_delegation(void *obj)
   6406 {
   6407 }
   6408 
   6409 static void
   6410 sumarg_destroy_clientid(char *buf, size_t buflen, void *obj)
   6411 {
   6412 	DESTROY_CLIENTID4args *a = obj;
   6413 
   6414 	snprintf(buf, buflen, "%s",
   6415 	    sum_clientid(a->dca_clientid));
   6416 }
   6417 
   6418 static void
   6419 dtlarg_destroy_clientid(void *obj)
   6420 {
   6421 	DESTROY_CLIENTID4args *a = obj;
   6422 
   6423 	detail_clientid(a->dca_clientid);
   6424 }
   6425 
   6426 static void
   6427 sumres_destroy_clientid(char *buf, size_t buflen, void *obj)
   6428 {
   6429 }
   6430 
   6431 static void
   6432 dtlres_destroy_clientid(void *obj)
   6433 {
   6434 }
   6435 
   6436 static void
   6437 sumarg_reclaim_complete(char *buf, size_t buflen, void *obj)
   6438 {
   6439 	RECLAIM_COMPLETE4args *a = obj;
   6440 	char *bp = buf;
   6441 
   6442 	snprintf(bp, buflen - (bp - buf), "%s",
   6443 	    (a->rca_one_fs) ? "<one-fs>" : "<all-fs>");
   6444 	bp += strlen(bp);
   6445 }
   6446 
   6447 static void
   6448 dtlarg_reclaim_complete(void *obj)
   6449 {
   6450 	RECLAIM_COMPLETE4args *a = obj;
   6451 
   6452 	sprintf(get_line(0, 0), "One_FS = %d", a->rca_one_fs);
   6453 }
   6454 
   6455 static void
   6456 sumres_reclaim_complete(char *buf, size_t buflen, void *obj)
   6457 {
   6458 }
   6459 
   6460 static void
   6461 dtlres_reclaim_complete(void *obj)
   6462 {
   6463 }
   6464 
   6465 static void
   6466 sumarg_cb_layoutrecall(char *buf, size_t buflen, void *obj)
   6467 {
   6468 	CB_LAYOUTRECALL4args	*args = (CB_LAYOUTRECALL4args *)obj;
   6469 	layoutrecall_file4	*lor_file;
   6470 	fsid4			*lor_fsid;
   6471 	char *bp = buf;
   6472 
   6473 	switch (args->clora_recall.lor_recalltype) {
   6474 	case LAYOUTRECALL4_FILE:
   6475 		lor_file = &args->clora_recall.layoutrecall4_u.lor_layout;
   6476 		snprintf(bp, buflen - (bp - buf), " %s",
   6477 		    sum_stateid(&lor_file->lor_stateid));
   6478 		break;
   6479 	case LAYOUTRECALL4_FSID:
   6480 		lor_fsid = &args->clora_recall.layoutrecall4_u.lor_fsid;
   6481 		snprintf(bp, buflen - (bp - buf), " (%llx, %llx)",
   6482 		    lor_fsid->major, lor_fsid->minor);
   6483 		break;
   6484 	}
   6485 }
   6486 
   6487 static void
   6488 dtlarg_cb_layoutrecall(void *obj)
   6489 {
   6490 	CB_LAYOUTRECALL4args	*args = (CB_LAYOUTRECALL4args *)obj;
   6491 	layoutrecall_file4	*lor_file;
   6492 	fsid4			*lor_fsid;
   6493 
   6494 	sprintf(get_line(0, 0), "Layout type        = %s",
   6495 	    detail_lotype_name(args->clora_type));
   6496 
   6497 	sprintf(get_line(0, 0), "Layout iomode      = %s",
   6498 	    detail_iomode_name(args->clora_iomode));
   6499 
   6500 	sprintf(get_line(0, 0), "Changed            = %s",
   6501 	    args->clora_changed ? "TRUE" : "FALSE");
   6502 
   6503 	sprintf(get_line(0, 0), "Layout Recall type = %s",
   6504 	    detail_lortype_name(args->clora_recall.lor_recalltype));
   6505 
   6506 	switch (args->clora_recall.lor_recalltype) {
   6507 	case LAYOUTRECALL4_FILE:
   6508 		lor_file = &args->clora_recall.layoutrecall4_u.lor_layout;
   6509 		sprintf(get_line(0, 0), "Layout associated with FILE");
   6510 		detail_fh4(&lor_file->lor_fh, "");
   6511 		sprintf(get_line(0, 0), "Offset  = %llu",
   6512 		    lor_file->lor_offset);
   6513 		sprintf(get_line(0, 0), "Length  = %llu",
   6514 		    lor_file->lor_length);
   6515 		detail_stateid(&lor_file->lor_stateid);
   6516 		break;
   6517 	case LAYOUTRECALL4_FSID:
   6518 		lor_fsid = &args->clora_recall.layoutrecall4_u.lor_fsid;
   6519 		sprintf(get_line(0, 0), "Layouts associated with FSID");
   6520 		sprintf(get_line(0, 0), "FS ID: Major = %llx, Minor = %llx",
   6521 		    lor_fsid->major, lor_fsid->minor);
   6522 		break;
   6523 	case LAYOUTRECALL4_ALL:
   6524 		sprintf(get_line(0, 0), "ALL Layouts");
   6525 		break;
   6526 	}
   6527 }
   6528 
   6529 static void
   6530 sumres_cb_layoutrecall(char *buf, size_t buflen, void *obj)
   6531 {
   6532 	CB_LAYOUTRECALL4res *res = (CB_LAYOUTRECALL4res *)obj;
   6533 	char *bp = buf;
   6534 
   6535 	snprintf(bp, buflen - (bp - buf), "%s ",
   6536 	    status_name(res->clorr_status));
   6537 }
   6538 
   6539 static void
   6540 dtlres_cb_layoutrecall(void *obj)
   6541 {
   6542 	dtl_nfsstat4(obj);
   6543 }
   6544 
   6545 static void
   6546 sumarg_cb_notify(char *buf, size_t buflen, void *obj)
   6547 {
   6548 }
   6549 
   6550 static void
   6551 dtlarg_cb_notify(void *obj)
   6552 {
   6553 }
   6554 
   6555 static void
   6556 sumres_cb_notify(char *buf, size_t buflen, void *obj)
   6557 {
   6558 }
   6559 
   6560 static void
   6561 dtlres_cb_notify(void *obj)
   6562 {
   6563 }
   6564 
   6565 static void
   6566 sumarg_cb_push_deleg(char *buf, size_t buflen, void *obj)
   6567 {
   6568 }
   6569 
   6570 static void
   6571 dtlarg_cb_push_deleg(void *obj)
   6572 {
   6573 }
   6574 
   6575 static void
   6576 sumres_cb_push_deleg(char *buf, size_t buflen, void *obj)
   6577 {
   6578 }
   6579 
   6580 static void
   6581 dtlres_cb_push_deleg(void *obj)
   6582 {
   6583 }
   6584 
   6585 static void
   6586 sumarg_cb_recall_any(char *buf, size_t buflen, void *obj)
   6587 {
   6588 }
   6589 
   6590 static void
   6591 dtlarg_cb_recall_any(void *obj)
   6592 {
   6593 }
   6594 
   6595 static void
   6596 sumres_cb_recall_any(char *buf, size_t buflen, void *obj)
   6597 {
   6598 }
   6599 
   6600 static void
   6601 dtlres_cb_recall_any(void *obj)
   6602 {
   6603 }
   6604 
   6605 static void
   6606 sumarg_cb_recallable_obj_avail(char *buf, size_t buflen, void *obj)
   6607 {
   6608 }
   6609 
   6610 static void
   6611 dtlarg_cb_recallable_obj_avail(void *obj)
   6612 {
   6613 }
   6614 
   6615 static void
   6616 sumres_cb_recallable_obj_avail(char *buf, size_t buflen, void *obj)
   6617 {
   6618 }
   6619 
   6620 static void
   6621 dtlres_cb_recallable_obj_avail(void *obj)
   6622 {
   6623 }
   6624 
   6625 static void
   6626 sumarg_cb_recall_slot(char *buf, size_t buflen, void *obj)
   6627 {
   6628 }
   6629 
   6630 static void
   6631 dtlarg_cb_recall_slot(void *obj)
   6632 {
   6633 }
   6634 
   6635 static void
   6636 sumres_cb_recall_slot(char *buf, size_t buflen, void *obj)
   6637 {
   6638 }
   6639 
   6640 static void
   6641 dtlres_cb_recall_slot(void *obj)
   6642 {
   6643 }
   6644 
   6645 static void
   6646 sumarg_cb_wants_cancelled(char *buf, size_t buflen, void *obj)
   6647 {
   6648 }
   6649 
   6650 static void
   6651 dtlarg_cb_wants_cancelled(void *obj)
   6652 {
   6653 }
   6654 
   6655 static void
   6656 sumres_cb_wants_cancelled(char *buf, size_t buflen, void *obj)
   6657 {
   6658 }
   6659 
   6660 static void
   6661 dtlres_cb_wants_cancelled(void *obj)
   6662 {
   6663 }
   6664 
   6665 static void
   6666 sumarg_cb_notify_lock(char *buf, size_t buflen, void *obj)
   6667 {
   6668 }
   6669 
   6670 static void
   6671 dtlarg_cb_notify_lock(void *obj)
   6672 {
   6673 }
   6674 
   6675 static void
   6676 sumres_cb_notify_lock(char *buf, size_t buflen, void *obj)
   6677 {
   6678 }
   6679 
   6680 static void
   6681 dtlres_cb_notify_lock(void *obj)
   6682 {
   6683 }
   6684 
   6685 
   6686 /*
   6687  * Attribute print functions.  See attr_info_t.
   6688  */
   6689 
   6690 static void
   6691 prt_supported_attrs(XDR *xdr)
   6692 {
   6693 	static bitmap4 val;
   6694 
   6695 	if (!xdr_bitmap4(xdr, &val))
   6696 		longjmp(xdr_err, 1);
   6697 	sprintf(get_line(0, 0), "Supported Attributes:");
   6698 	detail_attr_bitmap("\t", &val, NULL);
   6699 	xdr_free(xdr_bitmap4, (char *)&val);
   6700 }
   6701 
   6702 static void
   6703 prt_type(XDR *xdr)
   6704 {
   6705 	nfs_ftype4 val;
   6706 
   6707 	if (!xdr_nfs_ftype4(xdr, &val))
   6708 		longjmp(xdr_err, 1);
   6709 	sprintf(get_line(0, 0), "Type = %s", sum_type_name(val));
   6710 }
   6711 
   6712 static void
   6713 prt_fh_expire_type(XDR *xdr)
   6714 {
   6715 	fattr4_fh_expire_type