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 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 #include <ctype.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/errno.h>
37 #include <sys/tiuser.h>
38 #include <setjmp.h>
39
40 #include <rpc/types.h>
41 #include <rpc/xdr.h>
42 #include <rpc/auth.h>
43 #include <rpc/clnt.h>
44 #include <rpc/rpc_msg.h>
45 #include "snoop.h"
46
47 #include <sys/stat.h>
48 #include <sys/param.h>
49 #include <sys/sysmacros.h>
50 #include <rpcsvc/nfs_prot.h>
51 /* use the same nfs4_prot.h as the xdr code */
52 #include "rpcsvc/nfs4_prot.h"
53
54 /*
55 * XXX With NFS v2 and v3, we only need to xdr the pieces that we care
56 * about. Anything else we can ignore and just skip to the next packet.
57 * So all the stuff that deals directly with XDR lives in snoop_display.c
58 * With v4, we need to XDR entire structures so that we can skip over
59 * uninteresting bits in a compound array, so we call XDR directly from
60 * here. We need to rethink how we're going to structure XDR access. Do
61 * we continue to hide it all in snoop_display.c, or do we expose it to all
62 * the protocol modules?
63 */
64 extern XDR xdrm;
65
66 #ifndef MIN
67 #define MIN(a, b) ((a) < (b) ? (a) : (b))
68 #endif
69
70 /*
71 * Maximum number of characters to display in compound4 summary line.
72 */
73 #define SUM_COMPND_MAX 100
74
75 /*
76 * Maximum number of recognized attributes.
77 */
78 #define MAX_ATTRIBUTES 56
79
80 /*
81 * This data structure provides a more convenient way to access an
82 * attribute bitmask. map[N] = value of bit N in a bitmap4.
83 * It's defined as a struct so as to step around all the weird rules in C
84 * about arrays, pointers, passing them as arguments, etc.
85 */
86
87 typedef struct {
88 char map[MAX_ATTRIBUTES];
89 } unpkd_attrmap_t;
90
91
92 static void sumarg_cb_getattr(char *buf, size_t buflen, void *obj);
93 static void dtlarg_cb_getattr(void *obj);
94 static void sumarg_cb_recall(char *buf, size_t buflen, void *obj);
95 static void dtlarg_cb_recall(void *obj);
96
97
98 static void sumarg_access(char *buf, size_t buflen, void *obj);
99 static void dtlarg_access(void *obj);
100 static void sumarg_close(char *buf, size_t buflen, void *obj);
101 static void dtlarg_close(void *obj);
102 static void sumarg_commit(char *buf, size_t buflen, void *obj);
103 static void dtlarg_commit(void *obj);
104 static void sumarg_compnt(char *buf, size_t buflen, void *obj);
105 static void dtlarg_compnt(void *obj);
106 static void sumarg_create(char *buf, size_t buflen, void *obj);
107 static void dtlarg_create(void *obj);
108 static void sumarg_delprge(char *buf, size_t buflen, void *obj);
109 static void dtlarg_delprge(void *obj);
110 static void sumarg_delret(char *buf, size_t buflen, void *obj);
111 static void dtlarg_delret(void *obj);
112 static void sumarg_getattr(char *buf, size_t buflen, void *obj);
113 static void dtlarg_getattr(void *obj);
114 static void sumarg_link(char *buf, size_t buflen, void *obj);
115 static void dtlarg_link(void *obj);
116 static void sum_open_to_lock_owner(char *buf, int buflen,
117 open_to_lock_owner4 *own);
118 static void sum_exist_lock_owner(char *buf, int buflen,
119 exist_lock_owner4 *own);
120 static void sum_locker(char *buf, size_t buflen, locker4 *lk);
121 static void sumarg_lock(char *buf, size_t buflen, void *obj);
122 static void detail_open_to_lock_owner(open_to_lock_owner4 *own);
123 static void detail_exist_lock_owner(exist_lock_owner4 *own);
124 static void detail_locker(locker4 *lk);
125 static void dtlarg_lock(void *obj);
126 static void sumarg_lockt(char *buf, size_t buflen, void *obj);
127 static void dtlarg_lockt(void *obj);
128 static void sumarg_locku(char *buf, size_t buflen, void *obj);
129 static void dtlarg_locku(void *obj);
130 static void sumarg_lookup(char *buf, size_t buflen, void *obj);
131 static void dtlarg_lookup(void *obj);
132 static void sumarg_open(char *buf, size_t buflen, void *obj);
133 static void dtlarg_open(void *obj);
134 static void sumarg_openattr(char *buf, size_t buflen, void *obj);
135 static void dtlarg_openattr(void *obj);
136 static void sumarg_open_confirm(char *buf, size_t buflen, void *obj);
137 static void dtlarg_open_confirm(void *obj);
138 static void sumarg_open_downgrd(char *buf, size_t buflen, void *obj);
139 static void dtlarg_open_downgrd(void *obj);
140 static void sumarg_putfh(char *buf, size_t buflen, void *obj);
141 static void dtlarg_putfh(void *obj);
142 static void sumarg_read(char *buf, size_t buflen, void *obj);
143 static void dtlarg_read(void *obj);
144 static void sumarg_readdir(char *buf, size_t buflen, void *obj);
145 static void dtlarg_readdir(void *obj);
146 static void sumarg_release_lkown(char *buf, size_t buflen, void *obj);
147 static void dtlarg_release_lkown(void *obj);
148 static void sumarg_rename(char *buf, size_t buflen, void *obj);
149 static void dtlarg_rename(void *obj);
150 static void sumarg_renew(char *buf, size_t buflen, void *obj);
151 static void dtlarg_renew(void *buf);
152 static void sumarg_secinfo(char *buf, size_t buflen, void *obj);
153 static void dtlarg_secinfo(void *obj);
154 static void sumarg_setattr(char *buf, size_t buflen, void *obj);
155 static void dtlarg_setattr(void *obj);
156 static void sumarg_setclid(char *buf, size_t buflen, void *obj);
157 static void dtlarg_setclid(void *obj);
158 static void sumarg_setclid_cfm(char *buf, size_t buflen, void *obj);
159 static void dtlarg_setclid_cfm(void *obj);
160 static void dtlarg_verify(void *obj);
161 static void sumarg_write(char *buf, size_t buflen, void *obj);
162 static void dtlarg_write(void *obj);
163
164 static void sumres_cb_getattr(char *buf, size_t buflen, void *obj);
165 static void dtlres_cb_getattr(void *obj);
166
167 static void sumres_access(char *buf, size_t buflen, void *obj);
168 static void dtlres_access(void *obj);
169 static void sumres_close(char *buf, size_t buflen, void *obj);
170 static void dtlres_close(void *obj);
171 static void sumres_commit(char *buf, size_t buflen, void *obj);
172 static void dtlres_commit(void *obj);
173 static void dtlres_create(void *obj);
174 static void sumres_getattr(char *buf, size_t buflen, void *obj);
175 static void dtlres_getattr(void *obj);
176 static void sumres_getfh(char *buf, size_t buflen, void *obj);
177 static void dtlres_getfh(void *obj);
178 static void dtlres_link(void *obj);
179 static void sumres_lock(char *buf, size_t buflen, void *obj);
180 static void dtlres_lock(void *obj);
181 static void sumres_lockt(char *buf, size_t buflen, void *obj);
182 static void dtlres_lockt(void *obj);
183 static void sumres_locku(char *buf, size_t buflen, void *obj);
184 static void dtlres_locku(void *obj);
185 static void sumres_open(char *buf, size_t buflen, void *obj);
186 static void dtlres_open(void *obj);
187 static void sumres_open_confirm(char *buf, size_t buflen, void *obj);
188 static void dtlres_open_confirm(void *obj);
189 static void sumres_open_downgrd(char *buf, size_t buflen, void *obj);
190 static void dtlres_open_downgrd(void *obj);
191 static void sumres_read(char *buf, size_t buflen, void *obj);
192 static void dtlres_read(void *obj);
193 static void sumres_readdir(char *buf, size_t buflen, void *obj);
194 static void dtlres_readdir(void *obj);
195 static void sumres_readlnk(char *buf, size_t buflen, void *obj);
196 static void dtlres_readlnk(void *obj);
197 static void dtlres_remove(void *obj);
198 static void dtlres_rename(void *obj);
199 static void sumres_secinfo(char *buf, size_t buflen, void *obj);
200 static void dtlres_secinfo(void *obj);
201 static void sumres_setattr(char *buf, size_t buflen, void *obj);
202 static void dtlres_setattr(void *obj);
203 static void sumres_setclid(char *buf, size_t buflen, void *obj);
204 static void dtlres_setclid(void *obj);
205 static void sumres_write(char *buf, size_t buflen, void *obj);
206 static void dtlres_write(void *obj);
207 static void sum_nfsstat4(char *buf, size_t buflen, void *obj);
208 static void dtl_nfsstat4(void *obj);
209 static uint32_t adler16(void *, int);
210 static void nfs4_xdr_skip(int nbytes);
211 static char *sum_lock_type_name(enum nfs_lock_type4 type);
212
213 int nfs4_pkt_start;
214 int nfs4_pkt_len;
215 int nfs4_skip_bytes;
216 int nfs4_fragged_rpc;
217 char *nfs4err_fragrpc = "<Fragmented RPC>";
218 char *nfs4err_xdrfrag = "<XDR Error or Fragmented RPC>";
219
220 /*
221 * need a way to enable this if current testcases are parsing snoop
222 * error text. -- maybe an env var would do as temp workaround until
223 * testcases changed to grep for new error text.
224 */
225 int nfs4_use_old_error_text = 0;
226
227 /*
228 * Information about each operation that can appear in a compound call.
229 * The function pointers are to formatting functions for summary arguments
230 * and results, and detail arguments & results.
231 */
232
233 typedef struct {
234 char *name;
235 void (*sumarg)(char *, size_t, void *);
236 void (*sumres)(char *, size_t, void *);
237 void (*dtlarg)(void *);
238 void (*dtlres)(void *);
239 } op_info_t;
240
241 static op_info_t cb_opcode_info[] = {
242 {"OP_ZERO", NULL, NULL, NULL, NULL}, /* 0 */
243 {"OP_ONE", NULL, NULL, NULL, NULL},
244 {"OP_TWO", NULL, NULL, NULL, NULL}, /* minor vers */
245 {"CB_GETATTR",
246 sumarg_cb_getattr, sumres_cb_getattr,
247 dtlarg_cb_getattr, dtlres_cb_getattr},
248 {"CB_RECALL",
249 sumarg_cb_recall, sum_nfsstat4,
250 dtlarg_cb_recall, dtl_nfsstat4},
251 };
252 static uint_t cb_num_opcodes = ARRAY_SIZE(cb_opcode_info);
253
254 static op_info_t opcode_info[] = {
255 {"OP_ZERO", NULL, NULL, NULL, NULL}, /* 0 */
256 {"OP_ONE", NULL, NULL, NULL, NULL},
257 {"OP_TWO", NULL, NULL, NULL, NULL}, /* minor vers */
258 {"ACCESS",
259 sumarg_access, sumres_access, dtlarg_access, dtlres_access},
260 {"CLOSE",
261 sumarg_close, sumres_close, dtlarg_close, dtlres_close},
262 {"COMMIT",
263 sumarg_commit, sumres_commit, dtlarg_commit, dtlres_commit},
264 {"CREATE", /* 5 */
265 sumarg_create, sum_nfsstat4, dtlarg_create, dtlres_create},
266 {"DELEGPURGE",
267 sumarg_delprge, sum_nfsstat4, dtlarg_delprge, dtl_nfsstat4},
268 {"DELEGRETURN",
269 sumarg_delret, sum_nfsstat4, dtlarg_delret, dtl_nfsstat4},
270 {"GETATTR",
271 sumarg_getattr, sumres_getattr, dtlarg_getattr, dtlres_getattr},
272 {"GETFH",
273 NULL, sumres_getfh, NULL, dtlres_getfh},
274 {"LINK", /* 10 */
275 sumarg_link, sum_nfsstat4, dtlarg_link, dtlres_link},
276 {"LOCK",
277 sumarg_lock, sumres_lock, dtlarg_lock, dtlres_lock},
278 {"LOCKT",
279 sumarg_lockt, sumres_lockt, dtlarg_lockt, dtlres_lockt},
280 {"LOCKU",
281 sumarg_locku, sumres_locku, dtlarg_locku, dtlres_locku},
282 {"LOOKUP",
283 sumarg_lookup, sum_nfsstat4, dtlarg_lookup, dtl_nfsstat4},
284 {"LOOKUPP", /* 15 */
285 NULL, sum_nfsstat4, NULL, dtl_nfsstat4},
286 {"NVERIFY",
287 NULL, sum_nfsstat4, dtlarg_verify, dtl_nfsstat4},
288 {"OPEN",
289 sumarg_open, sumres_open, dtlarg_open, dtlres_open},
290 {"OPENATTR",
291 sumarg_openattr, sum_nfsstat4, dtlarg_openattr, dtl_nfsstat4},
292 {"OPEN_CONFIRM",
293 sumarg_open_confirm,
294 sumres_open_confirm,
295 dtlarg_open_confirm,
296 dtlres_open_confirm},
297 {"OPEN_DOWNGRADE",
298 sumarg_open_downgrd,
299 sumres_open_downgrd,
300 dtlarg_open_downgrd,
301 dtlres_open_downgrd},
302 {"PUTFH",
303 sumarg_putfh, sum_nfsstat4, dtlarg_putfh, dtl_nfsstat4},
304 {"PUTPUBFH", /* 20 */
305 NULL, sum_nfsstat4, NULL, dtl_nfsstat4},
306 {"PUTROOTFH",
307 NULL, sum_nfsstat4, NULL, dtl_nfsstat4},
308 {"READ",
309 sumarg_read, sumres_read, dtlarg_read, dtlres_read},
310 {"READDIR",
311 sumarg_readdir, sumres_readdir, dtlarg_readdir, dtlres_readdir},
312 {"READLINK",
313 NULL, sumres_readlnk, NULL, dtlres_readlnk},
314 {"REMOVE", /* 25 */
315 sumarg_compnt, sum_nfsstat4, dtlarg_compnt, dtlres_remove},
316 {"RENAME",
317 sumarg_rename, sum_nfsstat4, dtlarg_rename, dtlres_rename},
318 {"RENEW",
319 sumarg_renew, sum_nfsstat4, dtlarg_renew, dtl_nfsstat4},
320 {"RESTOREFH",
321 NULL, sum_nfsstat4, NULL, dtl_nfsstat4},
322 {"SAVEFH",
323 NULL, sum_nfsstat4, NULL, dtl_nfsstat4},
324 {"SECINFO", /* 30 */
325 sumarg_secinfo, sumres_secinfo, dtlarg_secinfo, dtlres_secinfo},
326 {"SETATTR",
327 sumarg_setattr, sumres_setattr, dtlarg_setattr, dtlres_setattr},
328 {"SETCLIENTID",
329 sumarg_setclid, sumres_setclid, dtlarg_setclid, dtlres_setclid},
330 {"SETCLIENTID_CONFIRM",
331 sumarg_setclid_cfm,
332 sum_nfsstat4,
333 dtlarg_setclid_cfm,
334 dtl_nfsstat4},
335 {"VERIFY",
336 NULL, sum_nfsstat4, dtlarg_verify, dtl_nfsstat4},
337 {"WRITE",
338 sumarg_write, sumres_write, dtlarg_write, dtlres_write},
339 {"RELEASE_LOCKOWNER",
340 sumarg_release_lkown, sum_nfsstat4,
341 dtlarg_release_lkown, dtl_nfsstat4},
342 };
343 static uint_t num_opcodes = ARRAY_SIZE(opcode_info);
344
345 /*
346 * File types.
347 */
348
349 typedef struct {
350 char *short_name; /* for summary output */
351 char *long_name; /* for detail output */
352 } ftype_names_t;
353
354 static ftype_names_t ftype_names[] = {
355 {"Type 0", "Type 0"},
356 {"REG", "Regular File"},
357 {"DIR", "Directory"},
358 {"BLK", "Block Device"},
359 {"CHR", "Character Device"},
360 {"LNK", "Symbolic Link"}, /* 5 */
361 {"SOCK", "Socket"},
362 {"FIFO", "FIFO"},
363 {"ATTRDIR", "Attribute Directory"},
364 {"NAMEDATTR", "Named Attribute"},
365 };
366 static uint_t num_ftypes = sizeof (ftype_names) / sizeof (ftype_names_t);
367
368 static ftype_names_t open_rflags[] = {
369 {"?", "UNKNOWN"}, /* 0 */
370 {"CF", "CONFIRM"}, /* 1 */
371 {"PL", "POSIX LOCK"}, /* 2 */
372 {"?", "UNKNOWN"},
373 };
374 static uint_t num_open_rflags =
375 sizeof (open_rflags) / sizeof (ftype_names_t) - 1;
376
377 static char *get_flags(uint_t, ftype_names_t *, uint_t, int, char *);
378
379 #define sum_open_rflags(flag) \
380 get_flags((flag), open_rflags, num_open_rflags, 1, " RF=")
381
382 #define detail_open_rflags(flag) \
383 get_flags((flag), open_rflags, num_open_rflags, 0, NULL)
384
385 static void prt_supported_attrs(XDR *);
386 static void prt_type(XDR *);
387 static void prt_fh_expire_type(XDR *);
388 static void prt_change(XDR *);
389 static void prt_size(XDR *);
390 static void prt_link_support(XDR *);
391 static void prt_symlink_support(XDR *);
392 static void prt_named_attr(XDR *);
393 static void prt_fsid(XDR *);
394 static void prt_unique_handles(XDR *);
395 static void prt_lease_time(XDR *);
396 static void prt_rdattr_error(XDR *);
397 static void prt_acl(XDR *);
398 static void prt_aclsupport(XDR *);
399 static void prt_archive(XDR *);
400 static void prt_cansettime(XDR *);
401 static void prt_case_insensitive(XDR *);
402 static void prt_case_preserving(XDR *);
403 static void prt_chown_restricted(XDR *);
404 static void prt_filehandle(XDR *);
405 static void prt_fileid(XDR *);
406 static void prt_mounted_on_fileid(XDR *);
407 static void prt_files_avail(XDR *);
408 static void prt_files_free(XDR *);
409 static void prt_files_total(XDR *);
410 static void prt_fs_locations(XDR *);
411 static void prt_hidden(XDR *);
412 static void prt_homogeneous(XDR *);
413 static void prt_maxfilesize(XDR *);
414 static void prt_maxlink(XDR *);
415 static void prt_maxname(XDR *);
416 static void prt_maxread(XDR *);
417 static void prt_maxwrite(XDR *);
418 static void prt_mimetype(XDR *);
419 static void prt_mode(XDR *);
420 static void prt_no_trunc(XDR *);
421 static void prt_numlinks(XDR *);
422 static void prt_owner(XDR *);
423 static void prt_owner_group(XDR *);
424 static void prt_quota_avail_hard(XDR *);
425 static void prt_quota_avail_soft(XDR *);
426 static void prt_quota_used(XDR *);
427 static void prt_rawdev(XDR *);
428 static void prt_space_avail(XDR *);
429 static void prt_space_free(XDR *);
430 static void prt_space_total(XDR *);
431 static void prt_space_used(XDR *);
432 static void prt_system(XDR *);
433 static void prt_time_access(XDR *);
434 static void prt_time_access_set(XDR *);
435 static void prt_time_backup(XDR *);
436 static void prt_time_create(XDR *);
437 static void prt_time_delta(XDR *);
438 static void prt_time_metadata(XDR *);
439 static void prt_time_modify(XDR *);
440 static void prt_time_modify_set(XDR *);
441
442
443
444 /*
445 * Information for attributes.
446 * name name of the attribute.
447 * prt_details function to XDR decode the attribute and print it.
448 *
449 * XXX If this table ever gets extensively changed (including
450 * reorganization to track changes to the spec), it would probably be a
451 * good idea to change to a scheme where the table is mechanically
452 * generated. Look at $SRC/uts/common/rpcsvc for how this is done in the
453 * kernel.
454 */
455
456 typedef struct {
457 char *name;
458 void (*prt_details)(XDR *);
459 } attr_info_t;
460
461 static attr_info_t attr_info[MAX_ATTRIBUTES] = {
462 {"SUPPORTED_ATTRS", prt_supported_attrs},
463 {"TYPE", prt_type},
464 {"FH_EXPIRE_TYPE", prt_fh_expire_type},
465 {"CHANGE", prt_change},
466 {"SIZE", prt_size},
467 {"LINK_SUPPORT", prt_link_support}, /* 5 */
468 {"SYMLINK_SUPPORT", prt_symlink_support},
469 {"NAMED_ATTR", prt_named_attr},
470 {"FSID", prt_fsid},
471 {"UNIQUE_HANDLES", prt_unique_handles},
472 {"LEASE_TIME", prt_lease_time}, /* 10 */
473 {"RDATTR_ERROR", prt_rdattr_error},
474 {"ACL", prt_acl},
475 {"ACLSUPPORT", prt_aclsupport},
476 {"ARCHIVE", prt_archive},
477 {"CANSETTIME", prt_cansettime}, /* 15 */
478 {"CASE_INSENSITIVE", prt_case_insensitive},
479 {"CASE_PRESERVING", prt_case_preserving},
480 {"CHOWN_RESTRICTED", prt_chown_restricted},
481 {"FILEHANDLE", prt_filehandle},
482 {"FILEID", prt_fileid}, /* 20 */
483 {"FILES_AVAIL", prt_files_avail},
484 {"FILES_FREE", prt_files_free},
485 {"FILES_TOTAL", prt_files_total},
486 {"FS_LOCATIONS", prt_fs_locations},
487 {"HIDDEN", prt_hidden}, /* 25 */
488 {"HOMOGENEOUS", prt_homogeneous},
489 {"MAXFILESIZE", prt_maxfilesize},
490 {"MAXLINK", prt_maxlink},
491 {"MAXNAME", prt_maxname},
492 {"MAXREAD", prt_maxread}, /* 30 */
493 {"MAXWRITE", prt_maxwrite},
494 {"MIMETYPE", prt_mimetype},
495 {"MODE", prt_mode},
496 {"NO_TRUNC", prt_no_trunc},
497 {"NUMLINKS", prt_numlinks}, /* 35 */
498 {"OWNER", prt_owner},
499 {"OWNER_GROUP", prt_owner_group},
500 {"QUOTA_AVAIL_HARD", prt_quota_avail_hard},
501 {"QUOTA_AVAIL_SOFT", prt_quota_avail_soft},
502 {"QUOTA_USED", prt_quota_used}, /* 40 */
503 {"RAWDEV", prt_rawdev},
504 {"SPACE_AVAIL", prt_space_avail},
505 {"SPACE_FREE", prt_space_free},
506 {"SPACE_TOTAL", prt_space_total},
507 {"SPACE_USED", prt_space_used}, /* 45 */
508 {"SYSTEM", prt_system},
509 {"TIME_ACCESS", prt_time_access},
510 {"TIME_ACCESS_SET", prt_time_access_set},
511 {"TIME_BACKUP", prt_time_backup},
512 {"TIME_CREATE", prt_time_create}, /* 50 */
513 {"TIME_DELTA", prt_time_delta},
514 {"TIME_METADATA", prt_time_metadata},
515 {"TIME_MODIFY", prt_time_modify},
516 {"TIME_MODIFY_SET", prt_time_modify_set},
517 {"MOUNTED_ON_FILEID", prt_mounted_on_fileid},
518 };
519
520 extern char *get_sum_line();
521
522 extern jmp_buf xdr_err;
523
524 static void sum_comp4res(char *, char *(*)(void));
525 static char *sum_compound4args(void);
526 static char *sum_compound4res(void);
527 static char *sum_operand(nfs_argop4 *opp);
528 static char *sum_result(nfs_resop4 *resp);
529
530 static char *sum_cb_compound4args(void);
531 static char *sum_cb_compound4res(void);
532 static char *sum_cb_operand(nfs_cb_argop4 *opp);
533 static char *sum_cb_result(nfs_cb_resop4 *resp);
534
535 static void detail_acetype4(acetype4);
536 static void detail_uint32_bitmap(uint32_t, char *[], int);
537 static void detail_aceflag4(aceflag4);
538 static void detail_acemask4(acemask4);
539 static void detail_nfs_argop4(void);
540 static void detail_nfs_resop4(void);
541 static void detail_cb_argop4(void);
542 static void detail_cb_resop4(void);
543
544 static char *attr_name(uint_t);
545 static char *claim_name(enum open_claim_type4 claim_type);
546 static char *delegation_type_name(enum open_delegation_type4 type);
547 static char *flavor_name(uint_t flavor);
548 static char *gss_svc_name(rpc_gss_svc_t svc);
549 static char *limitby_name(enum limit_by4 limitby);
550 static char *lock_type_name(enum nfs_lock_type4);
551 static char *opcode_name(uint_t);
552 static char *cb_opcode_name(uint_t opnum);
553 static char *status_name(int);
554 static char *status_name_compat(int);
555 static char *status_name_pcol(int);
556 static char *sum_type_name(nfs_ftype4);
557 static void sum_access4(char *buf, size_t buflen, uint32_t bits);
558 static void detail_access4(char *, uint32_t);
559 static void sum_claim(char *buf, size_t buflen, open_claim4 *claim);
560 static void detail_claim(open_claim4 *claim);
561 static char *sum_clientid(clientid4 client);
562 static void detail_clientid(clientid4 client);
563 static char *_sum_stateid(stateid4 *, char *prefix);
564 static void sum_delegation(char *buf, size_t buflen, open_delegation4 *delp);
565 static void detail_delegation(open_delegation4 *delp);
566 static void detail_lock_owner(lock_owner4 *owner);
567 static void detail_open_owner(open_owner4 *owner);
568 static void sum_openflag(char *bufp, int buflen, openflag4 *flagp);
569 static char *get_deleg_typestr(open_delegation_type4 dt);
570 static void detail_openflag(openflag4 *flagp);
571 static void sum_name(char *buf, size_t buflen, open_claim4 *claim);
572 static void detail_rpcsec_gss(rpcsec_gss_info *);
573 static void detail_secinfo4(secinfo4 *infop);
574 static char *sum_space_limit(nfs_space_limit4 *limitp);
575 static void detail_space_limit(nfs_space_limit4 *limitp);
576 static char *detail_type_name(nfs_ftype4);
577 static char *createhow4_name(createhow4 *crtp);
578
579
580 static void showxdr_utf8string(char *);
581 static char *utf8localize(utf8string *);
582 static void utf8free(void);
583 static void sum_pathname4(char *, size_t, pathname4 *);
584 static void detail_pathname4(pathname4 *pathp, char *);
585 static void sum_compname4(char *buf, size_t buflen, component4 *comp);
586 static void detail_compname4(component4 *comp);
587
588 static void detail_fattr4(fattr4 *attrp);
589 static void detail_attr_bitmap(char *, bitmap4 *, unpkd_attrmap_t *);
590 static void sum_attr_bitmap(char *buf, size_t buflen, bitmap4 *mapp);
591 static void detail_fattr4_change(char *msg, fattr4_change chg);
592 static char *sum_fh4(nfs_fh4 *fhp);
593 static void detail_fh4(nfs_fh4 *fh);
594
595 #define fh4_hash(fh) adler16((fh)->nfs_fh4_val, (fh)->nfs_fh4_len)
596 #define stateid_hash(st) adler16((st)->other, sizeof ((st)->other))
597 #define owner_hash(own) adler16((own)->owner_val, (own)->owner_len)
598
599 #define sum_deleg_stateid(st) _sum_stateid((st), "DST=")
600 #define sum_open_stateid(st) _sum_stateid((st), "OST=")
601 #define sum_lock_stateid(st) _sum_stateid((st), "LST=")
602 #define sum_stateid(st) _sum_stateid((st), "ST=")
603
604 #define detail_deleg_stateid(st) _detail_stateid((st), "Delegation ")
605 #define detail_open_stateid(st) _detail_stateid((st), "Open ")
606 #define detail_lock_stateid(st) _detail_stateid((st), "Lock ")
607 #define detail_stateid(st) _detail_stateid((st), "")
608
609 #define SPECIAL_STATEID0 "SPC0"
610 #define SPECIAL_STATEID1 "SPC1"
611
612 #define DONT_CHANGE 0
613 #define SET_TO_SERVER_TIME 1
614 #define SET_TO_CLIENT_TIME 2
615
616 static stateid4 spec_stateid_0 =
617 {0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
618 static stateid4 spec_stateid_1 =
619 {0xFFFFFFFF, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
620
621 static char *procnames_short[] = {
622 "NULL4", /* 0 */
623 "COMPOUND4" /* 1 */
624 };
625
626 static char *procnames_long[] = {
627 "Null procedure", /* 0 */
628 "Compound", /* 1 */
629 };
630
631 static char *cb_procnames_short[] = {
632 "CB_NULL", /* 0 */
633 "CB_COMPOUND" /* 1 */
634 };
635
636 static char *cb_procnames_long[] = {
637 "Null CallBack procedure", /* 0 */
638 "CallBack compound", /* 1 */
639 };
640
641 static char *acetype4_names[] = {
642 "ACE4_ACCESS_ALLOWED_ACE_TYPE",
643 "ACE4_ACCESS_DENIED_ACE_TYPE",
644 "ACE4_SYSTEM_AUDIT_ACE_TYPE",
645 "ACE4_SYSTEM_ALARM_ACE_TYPE"
646 };
647 #define ACETYPE4_NAMES_MAX (sizeof (acetype4_names) / sizeof (char *))
648
649 static char *aceflag4_names[] = {
650 "ACE4_FILE_INHERIT_ACE",
651 "ACE4_DIRECTORY_INHERIT_ACE",
652 "ACE4_NO_PROPAGATE_INHERIT_ACE",
653 "ACE4_INHERIT_ONLY_ACE",
654 "ACE4_SUCCESSFUL_ACCESS_ACE_FLAG",
655 "ACE4_FAILED_ACCESS_ACE_FLAG",
656 "ACE4_IDENTIFIER_GROUP"
657 };
658 #define ACEFLAG4_NAMES_MAX (sizeof (aceflag4_names) / sizeof (char *))
659
660 static char *acemask4_names[] = {
661 "ACE4_READ_DATA/ACE4_LIST_DIRECTORY",
662 "ACE4_WRITE_DATA/ACE4_ADD_FILE",
663 "ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY",
664 "ACE4_READ_NAMED_ATTRS",
665 "ACE4_WRITE_NAMED_ATTRS",
666 "ACE4_EXECUTE",
667 "ACE4_DELETE_CHILD",
668 "ACE4_READ_ATTRIBUTES",
669 "ACE4_WRITE_ATTRIBUTES",
670 "UNDEFINED", /* 0x00000200 */
671 "UNDEFINED", /* 0x00000400 */
672 "UNDEFINED", /* 0x00000800 */
673 "UNDEFINED", /* 0x00001000 */
674 "UNDEFINED", /* 0x00002000 */
675 "UNDEFINED", /* 0x00004000 */
676 "UNDEFINED", /* 0x00008000 */
677 "ACE4_DELETE",
678 "ACE4_READ_ACL",
679 "ACE4_WRITE_ACL",
680 "ACE4_WRITE_OWNER",
681 "ACE4_SYNCHRONIZE"
682 };
683 #define ACEMASK4_NAMES_MAX (sizeof (acemask4_names) / sizeof (char *))
684
685 #define MAXPROC 1
686
687 /*ARGSUSED*/
688 void
interpret_nfs4_cb(int flags,int type,int xid,int vers,int proc,char * data,int len)689 interpret_nfs4_cb(int flags, int type, int xid, int vers, int proc,
690 char *data, int len)
691 {
692 char *line = NULL;
693
694 if (proc < 0 || proc > MAXPROC)
695 return;
696
697 if (flags & F_SUM) {
698 line = get_sum_line();
699
700 if (type == CALL) {
701 (void) sprintf(line, "NFS C %s",
702 proc == CB_COMPOUND ? "CB4" :
703 cb_procnames_short[proc]);
704 line += strlen(line);
705
706 if (proc == CB_COMPOUND) {
707 static utf8string tag;
708
709 if (!xdr_utf8string(&xdrm, &tag))
710 longjmp(xdr_err, 1);
711 sprintf(line, " (%.20s) %s",
712 utf8localize(&tag),
713 sum_cb_compound4args());
714 xdr_free(xdr_utf8string, (char *)&tag);
715 }
716 check_retransmit(line, xid);
717 } else {
718 (void) sprintf(line, "NFS R %s ",
719 proc == CB_COMPOUND ? "CB4" :
720 cb_procnames_short[proc]);
721 line += strlen(line);
722 if (proc == CB_COMPOUND)
723 sum_comp4res(line, sum_cb_compound4res);
724 }
725 }
726
727 if (flags & F_DTAIL) {
728 show_header("NFS: ", "Sun NFS4 CallBack", len);
729 show_space();
730 (void) sprintf(get_line(0, 0), "Proc = %d (%s)",
731 proc, cb_procnames_long[proc]);
732 if (proc == CB_COMPOUND) {
733 if (type == CALL) {
734 showxdr_utf8string("Tag = %s");
735 detail_cb_argop4();
736 } else {
737 nfsstat4 status;
738
739 status = getxdr_long();
740 showxdr_utf8string("Tag = %s");
741 sprintf(get_line(0, 0), "Status = %d (%s)",
742 status, status_name(status));
743 detail_cb_resop4();
744 }
745 }
746 show_trailer();
747 }
748
749 utf8free(); /* cf. utf8localize() */
750 }
751
752
753 /*ARGSUSED*/
754 void
interpret_nfs4(int flags,int type,int xid,int vers,int proc,char * data,int len)755 interpret_nfs4(int flags, int type, int xid, int vers, int proc,
756 char *data, int len)
757 {
758 char *line = NULL;
759
760 if (proc < 0 || proc > MAXPROC)
761 return;
762
763 nfs4_fragged_rpc = 0;
764 nfs4_pkt_len = len;
765 nfs4_pkt_start = xdr_getpos(&xdrm);
766
767 if (flags & F_SUM) {
768 line = get_sum_line();
769
770 if (type == CALL) {
771 (void) sprintf(line, "NFS C %s",
772 proc == NFSPROC4_COMPOUND ? "4" :
773 procnames_short[proc]);
774 line += strlen(line);
775
776 if (proc == NFSPROC4_COMPOUND) {
777 static utf8string tag;
778
779 if (!xdr_utf8string(&xdrm, &tag))
780 longjmp(xdr_err, 1);
781 sprintf(line, " (%.20s) %s",
782 utf8localize(&tag),
783 sum_compound4args());
784 xdr_free(xdr_utf8string, (char *)&tag);
785 }
786 check_retransmit(line, xid);
787 } else {
788 (void) sprintf(line, "NFS R %s ",
789 proc == NFSPROC4_COMPOUND ? "4" :
790 procnames_short[proc]);
791 line += strlen(line);
792
793 if (proc == NFSPROC4_COMPOUND)
794 sum_comp4res(line, sum_compound4res);
795 }
796 }
797
798 if (flags & F_DTAIL) {
799 show_header("NFS: ", "Sun NFS", len);
800 show_space();
801 (void) sprintf(get_line(0, 0), "Proc = %d (%s)",
802 proc, procnames_long[proc]);
803 if (proc == NFSPROC4_COMPOUND) {
804 if (type == CALL) {
805 showxdr_utf8string("Tag = %s");
806 detail_nfs_argop4();
807 } else {
808 nfsstat4 status;
809
810 status = getxdr_long();
811 showxdr_utf8string("Tag = %s");
812 sprintf(get_line(0, 0), "Status = %d (%s)",
813 status, status_name(status));
814 detail_nfs_resop4();
815 }
816 }
817 show_trailer();
818 }
819
820 utf8free(); /* cf. utf8localize() */
821 }
822
823
824
825 /*
826 * Return the names and arguments of the oplist elements, up to
827 * SUM_COMPND_MAX characters. If the elements don't fit, include a "..."
828 * at the end of the string.
829 */
830
831 static char *
sum_compound4args(void)832 sum_compound4args(void)
833 {
834 static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
835 int numops;
836 const size_t buflen = sizeof (buf);
837 char *bp;
838 nfs_argop4 one_op;
839 uint32_t minor_version;
840
841 buf[0] = '\0';
842
843 if (setjmp(xdr_err)) {
844 bp = buf + strlen(buf);
845 snprintf(bp, buflen - (bp - buf),
846 nfs4_fragged_rpc ? nfs4err_fragrpc : nfs4err_xdrfrag);
847 return (buf);
848 }
849
850 /*
851 * might be nice to print minor version, but doesn't
852 * seem like very useful info for summary mode
853 */
854 if (!xdr_uint32_t(&xdrm, &minor_version))
855 longjmp(xdr_err, 1);
856
857 numops = getxdr_long();
858 bp = buf;
859 while (numops-- > 0) {
860 char *operand;
861
862 bzero(&one_op, sizeof (one_op));
863
864 if (!xdr_nfs_argop4(&xdrm, &one_op)) {
865 xdr_free(xdr_nfs_argop4, (char *)&one_op);
866 longjmp(xdr_err, 1);
867 }
868 snprintf(bp, buflen - (bp - buf), "%s ",
869 opcode_name(one_op.argop));
870 bp += strlen(bp);
871
872 operand = sum_operand(&one_op);
873 if (strlen(operand) > 0) {
874 snprintf(bp, buflen - (bp - buf), "%s ", operand);
875 bp += strlen(bp);
876 }
877
878 /* nfs4_skip_bytes set by xdr_nfs4_argop4 */
879 if (nfs4_skip_bytes != 0)
880 nfs4_xdr_skip(nfs4_skip_bytes);
881
882 xdr_free(xdr_nfs_argop4, (char *)&one_op);
883
884 /* add "..." if past the "end" of the buffer */
885 if (bp - buf > SUM_COMPND_MAX) {
886 strcpy(buf + SUM_COMPND_MAX - strlen("..."),
887 "...");
888 break;
889 }
890 }
891
892 return (buf);
893 }
894
895 static void
nfs4_xdr_skip(int nbytes)896 nfs4_xdr_skip(int nbytes)
897 {
898 int resid, off, len, cur_pos, new_pos;
899
900 len = RNDUP(nbytes);
901 cur_pos = xdr_getpos(&xdrm);
902
903 /*
904 * Time to skip over the rd/wr data. If the
905 * rd/wr data is completely contained in the first
906 * frag, we must skip over it to process the rest of
907 * the packet.
908 *
909 * nfs4_pkt_start: XDR position of start of NFS4 compound
910 * nfs4_pkt_len: number of bytes in pkt relative to
911 * nfs4_pkt_start
912 *
913 * cur_pos: current XDR position
914 * off: current XDR position relative to nfs4_pkt_start
915 * resid: number of unprocessed bytes in current pkt
916 * (relative to cur_pos/off)
917 *
918 * If nbytes <= resid, then we must skip over the rd/wr
919 * bytes so we can read the next op/compound in this
920 * packet. Otherwise, set the fragged flag so we can
921 * display the fragged_rpc message.
922 */
923 off = cur_pos - nfs4_pkt_start;
924 resid = nfs4_pkt_len - off;
925
926 /*
927 * set nfs4_fragged_rpc if the requested number of "skip"
928 * bytes is larger than the bytes remaining in the XDR
929 * stream/current packet. The global is reset to 0 at
930 * start of interpret_nfs4.
931 */
932 new_pos = cur_pos + ((nfs4_fragged_rpc = len > resid) ? resid : len);
933
934 /* there's nothing to do for error case (if it fails pkt is doomed) */
935 xdr_setpos(&xdrm, new_pos);
936 }
937
938
939 /*
940 * Return the names and arguments of the oplist elements, up to
941 * SUM_COMPND_MAX characters. If the elements don't fit, include a "..."
942 * at the end of the string.
943 */
944 static char *
sum_cb_compound4args(void)945 sum_cb_compound4args(void)
946 {
947 static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
948 int numops;
949 const size_t buflen = sizeof (buf);
950 char *bp;
951 nfs_cb_argop4 one_op;
952 uint32_t minor_version, callback_ident;
953
954 buf[0] = '\0';
955 if (setjmp(xdr_err)) {
956 bp = buf + strlen(buf);
957 snprintf(bp, buflen - (bp - buf), "<XDR Error or Fragmented"
958 " RPC>");
959 return (buf);
960 }
961
962 /*
963 * might be nice to print minor version, but doesn't
964 * seem like very useful info for summary mode
965 */
966 if (!xdr_uint32_t(&xdrm, &minor_version))
967 longjmp(xdr_err, 1);
968
969 /* print callback_ident */
970 if (!xdr_uint32_t(&xdrm, &callback_ident))
971 longjmp(xdr_err, 1);
972 snprintf(buf, buflen, "CBID=%u ", callback_ident);
973
974 bp = buf + strlen(buf);
975 numops = getxdr_long();
976
977 while (numops-- > 0) {
978 char *operand;
979
980 bzero(&one_op, sizeof (one_op));
981 if (!xdr_nfs_cb_argop4(&xdrm, &one_op)) {
982 xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
983 longjmp(xdr_err, 1);
984 }
985
986 snprintf(bp, buflen - (bp - buf), "%s ",
987 cb_opcode_name(one_op.argop));
988 bp += strlen(bp);
989 operand = sum_cb_operand(&one_op);
990 if (strlen(operand) > 0) {
991 snprintf(bp, buflen - (bp - buf), "%s ", operand);
992 bp += strlen(bp);
993 }
994
995 xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
996
997 /* add "..." if past the "end" of the buffer */
998 if (bp - buf > SUM_COMPND_MAX) {
999 strcpy(buf + SUM_COMPND_MAX - strlen("..."),
1000 "...");
1001 break;
1002 }
1003 }
1004
1005 return (buf);
1006 }
1007
1008 /*
1009 * Return the summarized argument list for the given nfs_argop4.
1010 */
1011
1012 static char *
sum_operand(nfs_argop4 * opp)1013 sum_operand(nfs_argop4 *opp)
1014 {
1015 static char buf[1024];
1016 void (*fmtproc)(char *, size_t, void *);
1017
1018 buf[0] = '\0';
1019 if (opp->argop < num_opcodes) {
1020 fmtproc = opcode_info[opp->argop].sumarg;
1021 if (fmtproc != NULL)
1022 fmtproc(buf, sizeof (buf), &opp->nfs_argop4_u);
1023 }
1024
1025 return (buf);
1026 }
1027
1028 /*
1029 * Return the summarized argument list for the given nfs_argop4.
1030 */
1031
1032 static char *
sum_cb_operand(nfs_cb_argop4 * opp)1033 sum_cb_operand(nfs_cb_argop4 *opp)
1034 {
1035 static char buf[1024];
1036 void (*fmtproc)(char *, size_t, void *);
1037
1038 buf[0] = '\0';
1039 if (opp->argop < cb_num_opcodes) {
1040 fmtproc = cb_opcode_info[opp->argop].sumarg;
1041 if (fmtproc != NULL)
1042 fmtproc(buf, sizeof (buf), &opp->nfs_cb_argop4_u);
1043 }
1044
1045 return (buf);
1046 }
1047
1048 /*
1049 * Print details about the nfs_argop4 that is next in the XDR stream.
1050 */
1051
1052 static void
detail_nfs_argop4(void)1053 detail_nfs_argop4(void)
1054 {
1055 int numops;
1056 nfs_argop4 one_op;
1057 void (*fmtproc)(void *);
1058 uint32_t minor_version;
1059
1060 if (!xdr_uint32_t(&xdrm, &minor_version))
1061 longjmp(xdr_err, 1);
1062
1063 (void) sprintf(get_line(0, 0), "Minor version = %u",
1064 minor_version);
1065
1066 numops = getxdr_long();
1067 (void) sprintf(get_line(0, 0), "Number of operations = %d",
1068 numops);
1069
1070 while (numops-- > 0) {
1071 bzero(&one_op, sizeof (one_op));
1072
1073 if (!xdr_nfs_argop4(&xdrm, &one_op)) {
1074 xdr_free(xdr_nfs_argop4, (char *)&one_op);
1075 longjmp(xdr_err, 1);
1076 }
1077
1078 get_line(0, 0); /* blank line to separate ops */
1079 sprintf(get_line(0, 0), "Op = %d (%s)",
1080 one_op.argop, opcode_name(one_op.argop));
1081 if (one_op.argop < num_opcodes) {
1082 fmtproc = opcode_info[one_op.argop].dtlarg;
1083 if (fmtproc != NULL)
1084 fmtproc(&one_op.nfs_argop4_u);
1085 }
1086
1087 /* nfs4_skip_bytes set by xdr_nfs_argop4() */
1088 if (nfs4_skip_bytes)
1089 nfs4_xdr_skip(nfs4_skip_bytes);
1090
1091 xdr_free(xdr_nfs_argop4, (char *)&one_op);
1092 }
1093 }
1094
1095
1096 /*
1097 * Print details about the nfs_argop4 that is next in the XDR stream.
1098 */
1099 static void
detail_cb_argop4(void)1100 detail_cb_argop4(void)
1101 {
1102 int numops;
1103 nfs_cb_argop4 one_op;
1104 void (*fmtproc)(void *);
1105 uint32_t minor_version, callback_ident;
1106
1107 if (!xdr_uint32_t(&xdrm, &minor_version))
1108 longjmp(xdr_err, 1);
1109 (void) sprintf(get_line(0, 0), "Minor version = %u",
1110 minor_version);
1111
1112 if (!xdr_uint32_t(&xdrm, &callback_ident))
1113 longjmp(xdr_err, 1);
1114 (void) sprintf(get_line(0, 0), "Callback Ident = %u",
1115 callback_ident);
1116
1117 numops = getxdr_long();
1118 (void) sprintf(get_line(0, 0), "Number of operations = %d",
1119 numops);
1120
1121 while (numops-- > 0) {
1122 bzero(&one_op, sizeof (one_op));
1123 if (!xdr_nfs_cb_argop4(&xdrm, &one_op)) {
1124 xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
1125 longjmp(xdr_err, 1);
1126 }
1127
1128 get_line(0, 0); /* blank line to separate ops */
1129 sprintf(get_line(0, 0), "Op = %d (%s)",
1130 one_op.argop, cb_opcode_name(one_op.argop));
1131 if (one_op.argop < cb_num_opcodes) {
1132 fmtproc = cb_opcode_info[one_op.argop].dtlarg;
1133 if (fmtproc != NULL)
1134 fmtproc(&one_op.nfs_cb_argop4_u);
1135 }
1136
1137 xdr_free(xdr_nfs_cb_argop4, (char *)&one_op);
1138 }
1139 }
1140
1141 /*
1142 * component_name: return a printable string for the given component4. I'm
1143 * leaving this as a separate function (as opposed to having the callers
1144 * call utf8localize() directly) in case the definition of component4
1145 * changes.
1146 */
1147
1148 static char *
component_name(component4 * cp)1149 component_name(component4 *cp)
1150 {
1151 return (utf8localize(cp));
1152 }
1153
1154 /*
1155 * linktext_name. cf. component_name().
1156 */
1157
1158 static char *
linktext_name(linktext4 * lp)1159 linktext_name(linktext4 *lp)
1160 {
1161 return (utf8localize((utf8string *)lp));
1162 }
1163
1164 /*
1165 * stable_how4_name: return a string for "how".
1166 */
1167
1168 static char *
stable_how4_name(stable_how4 how)1169 stable_how4_name(stable_how4 how)
1170 {
1171 char *result;
1172
1173 switch (how) {
1174 case UNSTABLE4:
1175 result = "ASYNC";
1176 break;
1177 case DATA_SYNC4:
1178 result = "DSYNC";
1179 break;
1180 case FILE_SYNC4:
1181 result = "FSYNC";
1182 break;
1183 default:
1184 result = "?";
1185 break;
1186 }
1187
1188 return (result);
1189 }
1190
1191 /*
1192 * sum_open_share_access: return a string corresponding to the
1193 * given OPEN share access bitmask.
1194 */
1195
1196 static char *
sum_open_share_access(int32_t mask)1197 sum_open_share_access(int32_t mask)
1198 {
1199 char *result;
1200
1201 switch (mask) {
1202 case 0:
1203 result = "N";
1204 break;
1205 case OPEN4_SHARE_ACCESS_READ:
1206 result = "R";
1207 break;
1208 case OPEN4_SHARE_ACCESS_WRITE:
1209 result = "W";
1210 break;
1211 case OPEN4_SHARE_ACCESS_BOTH:
1212 result = "RW";
1213 break;
1214 default:
1215 result = "?";
1216 break;
1217 }
1218
1219 return (result);
1220 }
1221
1222 /*
1223 * sum_open_share_deny: return a string corresponding to the
1224 * given OPEN share deny bitmask.
1225 */
1226
1227 static char *
sum_open_share_deny(int32_t mask)1228 sum_open_share_deny(int32_t mask)
1229 {
1230 char *result;
1231
1232 switch (mask) {
1233 case OPEN4_SHARE_DENY_NONE:
1234 result = "N";
1235 break;
1236 case OPEN4_SHARE_DENY_READ:
1237 result = "R";
1238 break;
1239 case OPEN4_SHARE_DENY_WRITE:
1240 result = "W";
1241 break;
1242 case OPEN4_SHARE_DENY_BOTH:
1243 result = "RW";
1244 break;
1245 default:
1246 result = "?";
1247 break;
1248 }
1249
1250 return (result);
1251 }
1252
1253 static int
special_stateid(stateid4 * stateid)1254 special_stateid(stateid4 *stateid)
1255 {
1256
1257 if (! memcmp(stateid, &spec_stateid_0, sizeof (*stateid)))
1258 return (0);
1259
1260 if (! memcmp(stateid, &spec_stateid_1, sizeof (*stateid)))
1261 return (1);
1262
1263 return (-1);
1264 }
1265
1266 static char *
_sum_stateid(stateid4 * stateid,char * prefix)1267 _sum_stateid(stateid4 *stateid, char *prefix)
1268 {
1269 static char buf[32];
1270 int spec;
1271
1272 if ((spec = special_stateid(stateid)) < 0)
1273 snprintf(buf, sizeof (buf), "%s%04X:%u", prefix,
1274 stateid_hash(stateid), stateid->seqid);
1275 else
1276 snprintf(buf, sizeof (buf), "%s%s", prefix,
1277 spec == 0 ? "SPC0" : (spec == 1 ? "SPC1" : "SPC?"));
1278 return (buf);
1279 }
1280
1281 static void
_detail_stateid(stateid4 * stateid,char * prefix)1282 _detail_stateid(stateid4 *stateid, char *prefix)
1283 {
1284 int spec;
1285 char seqstr[32] = {0};
1286
1287 spec = special_stateid(stateid);
1288
1289 if (spec < 0)
1290 sprintf(get_line(0, 0), "%sState ID hash = %04X",
1291 prefix, stateid_hash(stateid));
1292 else
1293 sprintf(get_line(0, 0), "%sState ID hash = %s", prefix,
1294 spec == 0 ? "SPECIAL_0" :
1295 (spec == 1 ? "SPECIAL_1" : "SPECIAL_?"));
1296
1297 sprintf(get_line(0, 0), " len = %u val = %s",
1298 sizeof (stateid->other),
1299 tohex(stateid->other, sizeof (stateid->other)));
1300
1301 /*
1302 * If spec 0/1 stateid, print seqid in hex; otherwise,
1303 * use decimal. This makes it more clear how spec stateids
1304 * are constructed [obvious that either all bits are 0, or all
1305 * bits are 1].
1306 */
1307 if (spec == -1)
1308 sprintf(seqstr, "%d", stateid->seqid);
1309 else
1310 sprintf(seqstr, "%08X", stateid->seqid);
1311
1312 sprintf(get_line(0, 0), " %sState ID Sequence ID = %s",
1313 prefix, seqstr);
1314 }
1315
1316
1317 static char *
sum_lock_denied(LOCK4denied * denied)1318 sum_lock_denied(LOCK4denied *denied)
1319 {
1320 static char buf[64];
1321
1322 sprintf(buf, "%s %llu:%llu LO=%04X",
1323 sum_lock_type_name(denied->locktype),
1324 denied->offset, denied->length,
1325 owner_hash(&denied->owner.owner));
1326
1327 return (buf);
1328 }
1329
1330 static void
detail_lock_denied(LOCK4denied * denied)1331 detail_lock_denied(LOCK4denied *denied)
1332 {
1333 sprintf(get_line(0, 0), "Type = %s", lock_type_name(denied->locktype));
1334 detail_lock_owner(&denied->owner);
1335 sprintf(get_line(0, 0), "Offset = %llu", denied->offset);
1336 sprintf(get_line(0, 0), "Length = %llu", denied->length);
1337 }
1338
1339 /*
1340 * sum_createhow4: return the string name of "how".
1341 */
1342
1343 static char *
createhow4_name(createhow4 * crtp)1344 createhow4_name(createhow4 *crtp)
1345 {
1346 char *result;
1347
1348 switch (crtp->mode) {
1349 case UNCHECKED4:
1350 result = "UNCHECKED";
1351 break;
1352 case GUARDED4:
1353 result = "GUARDED";
1354 break;
1355 case EXCLUSIVE4:
1356 result = "EXCLUSIVE";
1357 break;
1358 default:
1359 result = "?";
1360 break;
1361 }
1362
1363 return (result);
1364 }
1365
1366 /*
1367 * detail_createhow4: print detail information about "how".
1368 */
1369
1370 static void
detail_createhow4(createhow4 * crtp)1371 detail_createhow4(createhow4 *crtp)
1372 {
1373 sprintf(get_line(0, 0), "Method = %s",
1374 createhow4_name(crtp));
1375
1376 switch (crtp->mode) {
1377 case UNCHECKED4:
1378 case GUARDED4:
1379 detail_fattr4(&crtp->createhow4_u.createattrs);
1380 break;
1381 case EXCLUSIVE4:
1382 sprintf(get_line(0, 0), " Verifier = %s",
1383 tohex(crtp->createhow4_u.createverf,
1384 NFS4_VERIFIER_SIZE));
1385 break;
1386 }
1387 }
1388
1389 static void
detail_createtype4(createtype4 * crtp)1390 detail_createtype4(createtype4 *crtp)
1391 {
1392 sprintf(get_line(0, 0), "Type = %s",
1393 detail_type_name(crtp->type));
1394 switch (crtp->type) {
1395 case NF4LNK:
1396 sprintf(get_line(0, 0), "Linkdata = %s",
1397 utf8localize((utf8string *)&crtp->createtype4_u.linkdata));
1398 break;
1399 case NF4BLK:
1400 case NF4CHR:
1401 sprintf(get_line(0, 0), "Specdata1 = %04x Specdata2 = %04x",
1402 crtp->createtype4_u.devdata.specdata1,
1403 crtp->createtype4_u.devdata.specdata2);
1404 break;
1405 default:
1406 break;
1407 }
1408 }
1409
1410 static void
sumarg_access(char * buf,size_t buflen,void * obj)1411 sumarg_access(char *buf, size_t buflen, void *obj)
1412 {
1413 ACCESS4args *args = (ACCESS4args *)obj;
1414
1415 sum_access4(buf, buflen, args->access);
1416 }
1417
1418 static void
dtlarg_access(void * obj)1419 dtlarg_access(void *obj)
1420 {
1421 ACCESS4args *args = (ACCESS4args *)obj;
1422
1423 detail_access4("Access bits", args->access);
1424 }
1425
1426 static void
sumarg_close(char * buf,size_t buflen,void * obj)1427 sumarg_close(char *buf, size_t buflen, void *obj)
1428 {
1429 CLOSE4args *args = (CLOSE4args *)obj;
1430
1431 snprintf(buf, buflen, "SQ=%u %s",
1432 args->seqid, sum_open_stateid(&args->open_stateid));
1433 }
1434
1435 static void
dtlarg_close(void * obj)1436 dtlarg_close(void *obj)
1437 {
1438 CLOSE4args *args = (CLOSE4args *)obj;
1439
1440 detail_open_stateid(&args->open_stateid);
1441 sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
1442 }
1443
1444 static void
sumarg_commit(char * buf,size_t buflen,void * obj)1445 sumarg_commit(char *buf, size_t buflen, void *obj)
1446 {
1447 COMMIT4args *args = (COMMIT4args *)obj;
1448
1449 snprintf(buf, buflen, "at %llu for %u ", args->offset,
1450 args->count);
1451 }
1452
1453 static void
dtlarg_commit(void * obj)1454 dtlarg_commit(void *obj)
1455 {
1456 COMMIT4args *args = (COMMIT4args *)obj;
1457
1458 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
1459 sprintf(get_line(0, 0), "Count = %u", args->count);
1460 }
1461
1462 static void
sumarg_compnt(char * buf,size_t buflen,void * obj)1463 sumarg_compnt(char *buf, size_t buflen, void *obj)
1464 {
1465 component4 *comp = (component4 *)obj;
1466
1467 snprintf(buf, buflen, "%s", component_name(comp));
1468 }
1469
1470 static void
dtlarg_compnt(void * obj)1471 dtlarg_compnt(void *obj)
1472 {
1473 component4 *comp = (component4 *)obj;
1474
1475 sprintf(get_line(0, 0), "Name = %s", component_name(comp));
1476 }
1477
1478 static void
sumarg_create(char * buf,size_t buflen,void * obj)1479 sumarg_create(char *buf, size_t buflen, void *obj)
1480 {
1481 CREATE4args *args = (CREATE4args *)obj;
1482
1483 snprintf(buf, buflen, "%s %s ", component_name(&args->objname),
1484 sum_type_name(args->objtype.type));
1485 }
1486
1487 static void
dtlarg_create(void * obj)1488 dtlarg_create(void *obj)
1489 {
1490 CREATE4args *args = (CREATE4args *)obj;
1491
1492 sprintf(get_line(0, 0), "Name = %s", component_name(&args->objname));
1493 detail_createtype4(&args->objtype);
1494 detail_fattr4(&args->createattrs);
1495 }
1496
1497 static void
sumarg_delprge(char * buf,size_t buflen,void * obj)1498 sumarg_delprge(char *buf, size_t buflen, void *obj)
1499 {
1500 DELEGPURGE4args *args = (DELEGPURGE4args *)obj;
1501
1502 snprintf(buf, buflen, "%s", sum_clientid(args->clientid));
1503 }
1504
1505 static void
dtlarg_delprge(void * obj)1506 dtlarg_delprge(void *obj)
1507 {
1508 DELEGPURGE4args *args = (DELEGPURGE4args *)obj;
1509
1510 detail_clientid(args->clientid);
1511 }
1512
1513 static void
sumarg_delret(char * buf,size_t buflen,void * obj)1514 sumarg_delret(char *buf, size_t buflen, void *obj)
1515 {
1516 DELEGRETURN4args *args = (DELEGRETURN4args *)obj;
1517
1518 snprintf(buf, buflen, "%s", sum_deleg_stateid(&args->deleg_stateid));
1519 }
1520
1521 static void
dtlarg_delret(void * obj)1522 dtlarg_delret(void *obj)
1523 {
1524 DELEGRETURN4args *args = (DELEGRETURN4args *)obj;
1525
1526 detail_deleg_stateid(&args->deleg_stateid);
1527 }
1528
1529 static void
sumarg_getattr(char * buf,size_t buflen,void * obj)1530 sumarg_getattr(char *buf, size_t buflen, void *obj)
1531 {
1532 GETATTR4args *args = (GETATTR4args *)obj;
1533
1534 sum_attr_bitmap(buf, buflen, &args->attr_request);
1535 }
1536
1537 static void
dtlarg_getattr(void * obj)1538 dtlarg_getattr(void *obj)
1539 {
1540 GETATTR4args *args = (GETATTR4args *)obj;
1541
1542 detail_attr_bitmap("", &args->attr_request, NULL);
1543 }
1544
1545 static void
sumarg_cb_getattr(char * buf,size_t buflen,void * obj)1546 sumarg_cb_getattr(char *buf, size_t buflen, void *obj)
1547 {
1548 CB_GETATTR4args *args = (CB_GETATTR4args *)obj;
1549 char *bp = buf;
1550
1551 snprintf(bp, buflen, "%s ", sum_fh4(&args->fh));
1552 bp += strlen(bp);
1553 sum_attr_bitmap(bp, buflen - (bp - buf), &args->attr_request);
1554 }
1555
1556 static void
dtlarg_cb_getattr(void * obj)1557 dtlarg_cb_getattr(void *obj)
1558 {
1559 CB_GETATTR4args *args = (CB_GETATTR4args *)obj;
1560
1561 detail_fh4(&args->fh);
1562 detail_attr_bitmap("", &args->attr_request, NULL);
1563 }
1564
1565 static void
sumarg_cb_recall(char * buf,size_t buflen,void * obj)1566 sumarg_cb_recall(char *buf, size_t buflen, void *obj)
1567 {
1568 CB_RECALL4args *args = (CB_RECALL4args *)obj;
1569 char *bp = buf;
1570
1571 snprintf(bp, buflen, "%s %s TR=%s", sum_fh4(&args->fh),
1572 sum_stateid(&args->stateid), args->truncate ? "T" : "F");
1573 }
1574
1575 static void
dtlarg_cb_recall(void * obj)1576 dtlarg_cb_recall(void *obj)
1577 {
1578 CB_RECALL4args *args = (CB_RECALL4args *)obj;
1579
1580 detail_fh4(&args->fh);
1581 detail_stateid(&args->stateid);
1582 sprintf(get_line(0, 0), "Truncate = %s",
1583 args->truncate ? "True" : "False");
1584 }
1585
1586
1587 /*
1588 * name openhow seqid claim access deny owner
1589 */
1590 static void
sumarg_open(char * buf,size_t buflen,void * obj)1591 sumarg_open(char *buf, size_t buflen, void *obj)
1592 {
1593 OPEN4args *args = (OPEN4args *)obj;
1594 char *bp = buf;
1595 int blen = buflen, len;
1596
1597 sum_name(bp, buflen, &args->claim);
1598 bp += (len = strlen(bp));
1599 blen -= len;
1600
1601 sum_openflag(bp, blen, &args->openhow);
1602 bp += (len = strlen(bp));
1603 blen -= len;
1604
1605 snprintf(bp, blen, " SQ=%u", args->seqid);
1606 bp += (len = strlen(bp));
1607 blen -= len;
1608
1609 sum_claim(bp, blen, &args->claim);
1610 bp += (len = strlen(bp));
1611 blen -= len;
1612
1613 snprintf(bp, blen, " AC=%s DN=%s OO=%04X",
1614 sum_open_share_access(args->share_access),
1615 sum_open_share_deny(args->share_deny),
1616 owner_hash(&args->owner.owner));
1617 }
1618
1619 static void
dtlarg_open(void * obj)1620 dtlarg_open(void *obj)
1621 {
1622 OPEN4args *args = (OPEN4args *)obj;
1623
1624 detail_claim(&args->claim);
1625 detail_openflag(&args->openhow);
1626 detail_open_owner(&args->owner);
1627 sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
1628 sprintf(get_line(0, 0), "Access = 0x%x (%s)",
1629 args->share_access, sum_open_share_access(args->share_access));
1630 sprintf(get_line(0, 0), "Deny = 0x%x (%s)",
1631 args->share_deny, sum_open_share_access(args->share_deny));
1632 }
1633
1634 static void
sumarg_openattr(char * buf,size_t buflen,void * obj)1635 sumarg_openattr(char *buf, size_t buflen, void *obj)
1636 {
1637 OPENATTR4args *args = (OPENATTR4args *)obj;
1638
1639 snprintf(buf, buflen, "CD=%s",
1640 args->createdir ? "T" : "F");
1641 }
1642
1643 static void
dtlarg_openattr(void * obj)1644 dtlarg_openattr(void *obj)
1645 {
1646 OPENATTR4args *args = (OPENATTR4args *)obj;
1647
1648 sprintf(get_line(0, 0), "CreateDir = %s",
1649 args->createdir ? "True" : "False");
1650 }
1651
1652 static void
sumarg_open_confirm(char * buf,size_t buflen,void * obj)1653 sumarg_open_confirm(char *buf, size_t buflen, void *obj)
1654 {
1655 char *bp = buf;
1656 OPEN_CONFIRM4args *args = (OPEN_CONFIRM4args *)obj;
1657
1658 snprintf(bp, buflen, "SQ=%u %s", args->seqid,
1659 sum_open_stateid(&args->open_stateid));
1660 }
1661
1662 static void
dtlarg_open_confirm(void * obj)1663 dtlarg_open_confirm(void *obj)
1664 {
1665 OPEN_CONFIRM4args *args = (OPEN_CONFIRM4args *)obj;
1666
1667 sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
1668 detail_open_stateid(&args->open_stateid);
1669 }
1670
1671 static void
sumarg_open_downgrd(char * buf,size_t buflen,void * obj)1672 sumarg_open_downgrd(char *buf, size_t buflen, void *obj)
1673 {
1674 OPEN_DOWNGRADE4args *args = (OPEN_DOWNGRADE4args *)obj;
1675
1676 snprintf(buf, buflen, "SQ=%u %s AC=%s DN=%s",
1677 args->seqid, sum_open_stateid(&args->open_stateid),
1678 sum_open_share_access(args->share_access),
1679 sum_open_share_deny(args->share_deny));
1680 }
1681
1682 static void
dtlarg_open_downgrd(void * obj)1683 dtlarg_open_downgrd(void *obj)
1684 {
1685 OPEN_DOWNGRADE4args *args = (OPEN_DOWNGRADE4args *)obj;
1686
1687 sprintf(get_line(0, 0), "Open Sequence ID = %u", args->seqid);
1688 detail_open_stateid(&args->open_stateid);
1689 sprintf(get_line(0, 0), "Access = 0x%x (%s)",
1690 args->share_access, sum_open_share_access(args->share_access));
1691 sprintf(get_line(0, 0), "Deny = 0x%x (%s)",
1692 args->share_deny, sum_open_share_access(args->share_deny));
1693 }
1694
1695 static void
sumarg_putfh(char * buf,size_t buflen,void * obj)1696 sumarg_putfh(char *buf, size_t buflen, void *obj)
1697 {
1698 PUTFH4args *args = (PUTFH4args *)obj;
1699
1700 snprintf(buf, buflen, "%s", sum_fh4(&args->object));
1701 }
1702
1703 static void
dtlarg_putfh(void * obj)1704 dtlarg_putfh(void *obj)
1705 {
1706 PUTFH4args *args = (PUTFH4args *)obj;
1707
1708 detail_fh4(&args->object);
1709 }
1710
1711 static void
sumarg_link(char * buf,size_t buflen,void * obj)1712 sumarg_link(char *buf, size_t buflen, void *obj)
1713 {
1714 LINK4args *args = (LINK4args *)obj;
1715
1716 snprintf(buf, buflen, "%s", component_name(&args->newname));
1717 }
1718
1719 static void
dtlarg_link(void * obj)1720 dtlarg_link(void *obj)
1721 {
1722 LINK4args *args = (LINK4args *)obj;
1723
1724 sprintf(get_line(0, 0), "New name = %s",
1725 component_name(&args->newname));
1726 }
1727
1728 static void
sum_open_to_lock_owner(char * buf,int buflen,open_to_lock_owner4 * own)1729 sum_open_to_lock_owner(char *buf, int buflen, open_to_lock_owner4 *own)
1730 {
1731 snprintf(buf, buflen, " OSQ=%u %s LSQ=%u LO=%04X", own->open_seqid,
1732 sum_open_stateid(&own->open_stateid), own->lock_seqid,
1733 owner_hash(&own->lock_owner.owner));
1734 }
1735
1736 static void
sum_exist_lock_owner(char * buf,int buflen,exist_lock_owner4 * own)1737 sum_exist_lock_owner(char *buf, int buflen, exist_lock_owner4 *own)
1738 {
1739 snprintf(buf, buflen, " LSQ=%u %s", own->lock_seqid,
1740 sum_lock_stateid(&own->lock_stateid));
1741 }
1742
1743 static void
sum_locker(char * buf,size_t len,locker4 * lk)1744 sum_locker(char *buf, size_t len, locker4 *lk)
1745 {
1746 if (lk->new_lock_owner == TRUE)
1747 sum_open_to_lock_owner(buf, len, &lk->locker4_u.open_owner);
1748 else
1749 sum_exist_lock_owner(buf, len, &lk->locker4_u.lock_owner);
1750 }
1751
1752 static char *
sum_lock_type_name(enum nfs_lock_type4 type)1753 sum_lock_type_name(enum nfs_lock_type4 type)
1754 {
1755 char *result;
1756
1757 switch (type) {
1758 case READ_LT:
1759 result = "RD";
1760 break;
1761 case WRITE_LT:
1762 result = "WR";
1763 break;
1764 case READW_LT:
1765 result = "RDW";
1766 break;
1767 case WRITEW_LT:
1768 result = "WRW";
1769 break;
1770 default:
1771 result = "?";
1772 break;
1773 }
1774
1775 return (result);
1776 }
1777
1778 static void
sumarg_lock(char * buf,size_t buflen,void * obj)1779 sumarg_lock(char *buf, size_t buflen, void *obj)
1780 {
1781 LOCK4args *args = (LOCK4args *)obj;
1782 char *bp = buf;
1783
1784 snprintf(buf, buflen, "%s%s%llu:%llu",
1785 sum_lock_type_name(args->locktype),
1786 args->reclaim ? " reclaim " : " ",
1787 args->offset, args->length);
1788
1789 bp += strlen(buf);
1790 sum_locker(bp, buflen - (bp - buf), &args->locker);
1791 }
1792
1793 static void
detail_open_to_lock_owner(open_to_lock_owner4 * own)1794 detail_open_to_lock_owner(open_to_lock_owner4 *own)
1795 {
1796 sprintf(get_line(0, 0), "Open Sequence ID = %u", own->open_seqid);
1797 detail_open_stateid(&own->open_stateid);
1798 sprintf(get_line(0, 0), "Lock Sequence ID = %u", own->lock_seqid);
1799 detail_lock_owner(&own->lock_owner);
1800 }
1801
1802 static void
detail_exist_lock_owner(exist_lock_owner4 * own)1803 detail_exist_lock_owner(exist_lock_owner4 *own)
1804 {
1805 detail_lock_stateid(&own->lock_stateid);
1806 sprintf(get_line(0, 0), "Lock Sequence ID = %u", own->lock_seqid);
1807 }
1808
1809 static void
detail_locker(locker4 * lk)1810 detail_locker(locker4 *lk)
1811 {
1812 if (lk->new_lock_owner == TRUE)
1813 detail_open_to_lock_owner(&lk->locker4_u.open_owner);
1814 else
1815 detail_exist_lock_owner(&lk->locker4_u.lock_owner);
1816 }
1817
1818 static void
dtlarg_lock(void * obj)1819 dtlarg_lock(void *obj)
1820 {
1821 LOCK4args *args = (LOCK4args *)obj;
1822
1823 sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
1824 sprintf(get_line(0, 0), "Reclaim = %s",
1825 args->reclaim ? "TRUE" : "FALSE");
1826 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
1827 sprintf(get_line(0, 0), "Length = %llu", args->length);
1828 detail_locker(&args->locker);
1829 }
1830
1831 static void
sumarg_lockt(char * buf,size_t buflen,void * obj)1832 sumarg_lockt(char *buf, size_t buflen, void *obj)
1833 {
1834 LOCKT4args *args = (LOCKT4args *)obj;
1835
1836 snprintf(buf, buflen, "%s %llu:%llu",
1837 sum_lock_type_name(args->locktype),
1838 args->offset, args->length);
1839 }
1840
1841 static void
dtlarg_lockt(void * obj)1842 dtlarg_lockt(void *obj)
1843 {
1844 LOCKT4args *args = (LOCKT4args *)obj;
1845
1846 sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
1847 detail_lock_owner(&args->owner);
1848 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
1849 sprintf(get_line(0, 0), "Length = %llu", args->length);
1850 }
1851
1852 static void
sumarg_locku(char * buf,size_t buflen,void * obj)1853 sumarg_locku(char *buf, size_t buflen, void *obj)
1854 {
1855 LOCKU4args *args = (LOCKU4args *)obj;
1856
1857 snprintf(buf, buflen, "%llu:%llu LSQ=%u %s",
1858 args->offset, args->length, args->seqid,
1859 sum_lock_stateid(&args->lock_stateid));
1860 }
1861
1862
1863 static void
dtlarg_locku(void * obj)1864 dtlarg_locku(void *obj)
1865 {
1866 LOCKU4args *args = (LOCKU4args *)obj;
1867
1868 sprintf(get_line(0, 0), "Type = %s", lock_type_name(args->locktype));
1869 sprintf(get_line(0, 0), "Sequence ID = %u", args->seqid);
1870 detail_lock_stateid(&args->lock_stateid);
1871 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
1872 sprintf(get_line(0, 0), "Length = %llu", args->length);
1873 }
1874
1875 static void
sumarg_lookup(char * buf,size_t buflen,void * obj)1876 sumarg_lookup(char *buf, size_t buflen, void *obj)
1877 {
1878 LOOKUP4args *args = (LOOKUP4args *)obj;
1879
1880 sum_compname4(buf, buflen, &args->objname);
1881 }
1882
1883 static void
dtlarg_lookup(void * obj)1884 dtlarg_lookup(void *obj)
1885 {
1886 LOOKUP4args *args = (LOOKUP4args *)obj;
1887
1888 detail_compname4(&args->objname);
1889 }
1890
1891 static void
sumarg_read(char * buf,size_t buflen,void * obj)1892 sumarg_read(char *buf, size_t buflen, void *obj)
1893 {
1894 READ4args *args = (READ4args *)obj;
1895
1896 snprintf(buf, buflen, "%s at %llu for %u",
1897 sum_stateid(&args->stateid), args->offset, args->count);
1898 }
1899
1900 static void
dtlarg_read(void * obj)1901 dtlarg_read(void *obj)
1902 {
1903 READ4args *args = (READ4args *)obj;
1904
1905 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
1906 sprintf(get_line(0, 0), "Count = %u", args->count);
1907 detail_stateid(&args->stateid);
1908 }
1909
1910 static void
sumarg_readdir(char * buf,size_t buflen,void * obj)1911 sumarg_readdir(char *buf, size_t buflen, void *obj)
1912 {
1913 READDIR4args *args = (READDIR4args *)obj;
1914
1915 snprintf(buf, buflen, "Cookie=%llu (%s) for %u/%u",
1916 args->cookie, tohex(args->cookieverf, NFS4_VERIFIER_SIZE),
1917 args->dircount, args->maxcount);
1918 }
1919
1920 static void
dtlarg_readdir(void * obj)1921 dtlarg_readdir(void *obj)
1922 {
1923 READDIR4args *args = (READDIR4args *)obj;
1924
1925 sprintf(get_line(0, 0), "Cookie = %llu", args->cookie);
1926 sprintf(get_line(0, 0), "Verifier = %s",
1927 tohex(args->cookieverf, NFS4_VERIFIER_SIZE));
1928 sprintf(get_line(0, 0), "Dircount = %u", args->dircount);
1929 sprintf(get_line(0, 0), "Maxcount = %u", args->maxcount);
1930 detail_attr_bitmap("", &args->attr_request, NULL);
1931 }
1932
1933 static void
dtlarg_release_lkown(void * obj)1934 dtlarg_release_lkown(void *obj)
1935 {
1936 RELEASE_LOCKOWNER4args *args = (RELEASE_LOCKOWNER4args *)obj;
1937
1938 detail_lock_owner(&args->lock_owner);
1939 }
1940
1941 static void
sumarg_release_lkown(char * buf,size_t buflen,void * obj)1942 sumarg_release_lkown(char *buf, size_t buflen, void *obj)
1943 {
1944 RELEASE_LOCKOWNER4args *args = (RELEASE_LOCKOWNER4args *)obj;
1945
1946 snprintf(buf, buflen, "LO=%04X", owner_hash(&args->lock_owner.owner));
1947 }
1948
1949 static void
sumarg_rename(char * buf,size_t buflen,void * obj)1950 sumarg_rename(char *buf, size_t buflen, void *obj)
1951 {
1952 RENAME4args *args = (RENAME4args *)obj;
1953
1954 snprintf(buf, buflen, "%s to %s",
1955 component_name(&args->oldname),
1956 component_name(&args->newname));
1957 }
1958
1959 static void
dtlarg_rename(void * obj)1960 dtlarg_rename(void *obj)
1961 {
1962 RENAME4args *args = (RENAME4args *)obj;
1963
1964 sprintf(get_line(0, 0), "Old name = %s",
1965 component_name(&args->oldname));
1966 sprintf(get_line(0, 0), "New name = %s",
1967 component_name(&args->newname));
1968 }
1969
1970 static void
sumarg_renew(char * buf,size_t buflen,void * obj)1971 sumarg_renew(char *buf, size_t buflen, void *obj)
1972 {
1973 RENEW4args *args = (RENEW4args *)obj;
1974
1975 snprintf(buf, buflen, "%s", sum_clientid(args->clientid));
1976 }
1977 static void
dtlarg_renew(void * obj)1978 dtlarg_renew(void *obj)
1979 {
1980 RENEW4args *args = (RENEW4args *)obj;
1981
1982 detail_clientid(args->clientid);
1983 }
1984
1985 static void
sumarg_secinfo(char * buf,size_t buflen,void * obj)1986 sumarg_secinfo(char *buf, size_t buflen, void *obj)
1987 {
1988 SECINFO4args *args = (SECINFO4args *)obj;
1989
1990 snprintf(buf, buflen, "%s",
1991 component_name(&args->name));
1992 }
1993
1994 static void
dtlarg_secinfo(void * obj)1995 dtlarg_secinfo(void *obj)
1996 {
1997 SECINFO4args *args = (SECINFO4args *)obj;
1998
1999 sprintf(get_line(0, 0), "Name = %s",
2000 component_name(&args->name));
2001 }
2002
2003 static void
sumarg_setattr(char * buf,size_t buflen,void * obj)2004 sumarg_setattr(char *buf, size_t buflen, void *obj)
2005 {
2006 SETATTR4args *args = (SETATTR4args *)obj;
2007
2008 snprintf(buf, buflen, "%s", sum_stateid(&args->stateid));
2009 }
2010
2011 static void
dtlarg_setattr(void * obj)2012 dtlarg_setattr(void *obj)
2013 {
2014 SETATTR4args *args = (SETATTR4args *)obj;
2015
2016 detail_stateid(&args->stateid);
2017 detail_fattr4(&args->obj_attributes);
2018 }
2019
2020 static void
sumarg_setclid(char * buf,size_t buflen,void * obj)2021 sumarg_setclid(char *buf, size_t buflen, void *obj)
2022 {
2023 SETCLIENTID4args *args = (SETCLIENTID4args *)obj;
2024
2025 snprintf(buf, buflen, "Prog=%u ID=%s Addr=%s CBID=%u",
2026 args->callback.cb_program,
2027 args->callback.cb_location.na_r_netid,
2028 args->callback.cb_location.na_r_addr, args->callback_ident);
2029 }
2030
2031 static void
dtlarg_setclid(void * obj)2032 dtlarg_setclid(void *obj)
2033 {
2034 SETCLIENTID4args *args = (SETCLIENTID4args *)obj;
2035
2036 sprintf(get_line(0, 0), "Verifier=%s",
2037 tohex(args->client.verifier, NFS4_VERIFIER_SIZE));
2038 sprintf(get_line(0, 0), "ID = (%d) %s",
2039 args->client.id.id_len,
2040 tohex(args->client.id.id_val, args->client.id.id_len));
2041
2042 sprintf(get_line(0, 0), "Callback Program = %u",
2043 args->callback.cb_program);
2044 sprintf(get_line(0, 0), "Callback Net ID = %s",
2045 args->callback.cb_location.na_r_netid);
2046 sprintf(get_line(0, 0), "Callback Addr = %s",
2047 args->callback.cb_location.na_r_addr);
2048 sprintf(get_line(0, 0), "Callback Ident = %u", args->callback_ident);
2049 }
2050
2051 static void
sumarg_setclid_cfm(char * buf,size_t buflen,void * obj)2052 sumarg_setclid_cfm(char *buf, size_t buflen, void *obj)
2053 {
2054 SETCLIENTID_CONFIRM4args *args = (SETCLIENTID_CONFIRM4args *)obj;
2055
2056 snprintf(buf, buflen, "%s CFV=%s", sum_clientid(args->clientid),
2057 tohex(args->setclientid_confirm, NFS4_VERIFIER_SIZE));
2058 }
2059
2060 static void
dtlarg_setclid_cfm(void * obj)2061 dtlarg_setclid_cfm(void *obj)
2062 {
2063 SETCLIENTID_CONFIRM4args *args = (SETCLIENTID_CONFIRM4args *)obj;
2064
2065 detail_clientid(args->clientid);
2066 sprintf(get_line(0, 0), "Set Client ID Confirm Verifier = %s",
2067 tohex(args->setclientid_confirm, NFS4_VERIFIER_SIZE));
2068 }
2069
2070
2071 static void
dtlarg_verify(void * obj)2072 dtlarg_verify(void *obj)
2073 {
2074 NVERIFY4args *args = (NVERIFY4args *)obj;
2075
2076 detail_fattr4(&args->obj_attributes);
2077 }
2078
2079 static void
sumarg_write(char * buf,size_t buflen,void * obj)2080 sumarg_write(char *buf, size_t buflen, void *obj)
2081 {
2082 WRITE4args *args = (WRITE4args *)obj;
2083
2084 snprintf(buf, buflen, "%s at %llu for %u",
2085 sum_stateid(&args->stateid), args->offset, args->data.data_len);
2086 }
2087
2088 static void
dtlarg_write(void * obj)2089 dtlarg_write(void *obj)
2090 {
2091 WRITE4args *args = (WRITE4args *)obj;
2092
2093 sprintf(get_line(0, 0), "Offset = %llu", args->offset);
2094 sprintf(get_line(0, 0), "Count = %u", args->data.data_len);
2095 sprintf(get_line(0, 0), "Stable = %s", stable_how4_name(args->stable));
2096 detail_stateid(&args->stateid);
2097 }
2098
2099 static char *
sum_fh4(nfs_fh4 * fh)2100 sum_fh4(nfs_fh4 *fh)
2101 {
2102 static char buf[20];
2103
2104 sprintf(buf, "FH=%04X", fh4_hash(fh));
2105
2106 return (buf);
2107 }
2108
2109 static void
detail_fh4(nfs_fh4 * fh)2110 detail_fh4(nfs_fh4 *fh)
2111 {
2112 int i;
2113 uchar_t *cp;
2114 char *bufp;
2115
2116 sprintf(get_line(0, 0), "File handle = [%04X]", fh4_hash(fh));
2117 bufp = get_line(0, 0);
2118 sprintf(bufp, "(%d) ", fh->nfs_fh4_len);
2119 bufp += strlen(bufp);
2120 /* XXX use tohex()? */
2121 for (i = 0, cp = (uchar_t *)fh->nfs_fh4_val;
2122 i < fh->nfs_fh4_len;
2123 i++, cp++) {
2124 if (i != 0 && i % 32 == 0)
2125 bufp = get_line(0, 0);
2126 sprintf(bufp, "%02x", *cp);
2127 bufp += strlen(bufp);
2128 }
2129 }
2130
2131 static void
detail_fattr4(fattr4 * attrp)2132 detail_fattr4(fattr4 *attrp)
2133 {
2134 unpkd_attrmap_t provided;
2135 uint_t attrnum;
2136 XDR attrxdr;
2137 jmp_buf old_errbuf;
2138
2139 xdrmem_create(&attrxdr, attrp->attr_vals.attrlist4_val,
2140 attrp->attr_vals.attrlist4_len, XDR_DECODE);
2141
2142 bcopy(xdr_err, old_errbuf, sizeof (old_errbuf));
2143 if (setjmp(xdr_err)) {
2144 sprintf(get_line(0, 0), "<attr_vals too short>");
2145 goto done;
2146 }
2147
2148 detail_attr_bitmap("", &attrp->attrmask, &provided);
2149 for (attrnum = 0; attrnum < MAX_ATTRIBUTES; attrnum++) {
2150 if (provided.map[attrnum]) {
2151 attr_info[attrnum].prt_details(&attrxdr);
2152 }
2153 }
2154
2155 done:
2156 bcopy(old_errbuf, xdr_err, sizeof (old_errbuf));
2157 }
2158
2159 static void
sum_attr_bitmap(char * buf,size_t buflen,bitmap4 * mapp)2160 sum_attr_bitmap(char *buf, size_t buflen, bitmap4 *mapp)
2161 {
2162 uint_t num_words;
2163 char *bp;
2164 size_t curlen, remaining;
2165
2166 buf[0] = '\0';
2167 for (num_words = 0; num_words < mapp->bitmap4_len; num_words++) {
2168 curlen = strlen(buf);
2169 if (curlen + sizeof ("<Too Long>") >= buflen) {
2170 strcpy(buf + buflen - sizeof ("<Too Long>"),
2171 "<Too Long>");
2172 return;
2173 }
2174 bp = buf + curlen;
2175 remaining = buflen - curlen;
2176 snprintf(bp, remaining,
2177 num_words == 0 ? "%x" : " %x",
2178 mapp->bitmap4_val[num_words]);
2179 }
2180 }
2181
2182 /*
2183 * Print detail information for the given attribute bitmap, and fill in the
2184 * unpacked version of the map if "unpacked" is non-null. Returns the
2185 * number of bytes in the bitmap. "prefix" is an initial string that is
2186 * printed at the front of each line.
2187 */
2188
2189 static void
detail_attr_bitmap(char * prefix,bitmap4 * bitp,unpkd_attrmap_t * unpacked)2190 detail_attr_bitmap(char *prefix, bitmap4 *bitp, unpkd_attrmap_t *unpacked)
2191 {
2192 uint_t num_words;
2193 uint32_t *wp;
2194 uint_t byte_num;
2195
2196 if (unpacked != NULL)
2197 memset(unpacked, 0, sizeof (unpkd_attrmap_t));
2198
2199 /*
2200 * Break the bitmap into octets, then print in hex and
2201 * symbolically.
2202 */
2203
2204 for (num_words = 0, wp = bitp->bitmap4_val;
2205 num_words < bitp->bitmap4_len;
2206 num_words++, wp++) {
2207 for (byte_num = 0; byte_num < 4; byte_num++) {
2208 uchar_t val = (*wp) >> (byte_num * 8);
2209 char *buf = get_line(0, 0);
2210 uint_t attrnum;
2211 int bit;
2212
2213 sprintf(buf, "%s 0x%02x ", prefix, val);
2214 attrnum = num_words * 32 + byte_num * 8;
2215 for (bit = 7; bit >= 0; bit--) {
2216 if (val & (1 << bit)) {
2217 strcat(buf, " ");
2218 strcat(buf,
2219 attr_name(attrnum + bit));
2220 if (unpacked != NULL)
2221 unpacked->map[attrnum + bit] =
2222 1;
2223 }
2224 }
2225 }
2226 }
2227 }
2228
2229 /*
2230 * Format the summary line results from a COMPOUND4 call.
2231 */
2232
2233 static void
sum_comp4res(char * line,char * (* sumres_fn)(void))2234 sum_comp4res(char *line, char *(*sumres_fn)(void))
2235 {
2236 nfsstat4 status;
2237 static utf8string tag;
2238
2239 status = getxdr_long();
2240 if (!xdr_utf8string(&xdrm, &tag))
2241 longjmp(xdr_err, 1);
2242
2243 sprintf(line, "(%.20s) %s %s", utf8localize(&tag),
2244 status_name(status), sumres_fn());
2245
2246 xdr_free(xdr_utf8string, (char *)&tag);
2247 }
2248
2249
2250 /*
2251 * Return a set of summary strings for the result data that's next in the
2252 * XDR stream, up to SUM_COMPND_MAX characters. If the strings don't fit,
2253 * include a "..." at the end of the string.
2254 */
2255
2256 static char *
sum_compound4res(void)2257 sum_compound4res(void)
2258 {
2259 static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
2260 int numres;
2261 const size_t buflen = sizeof (buf);
2262 char *bp;
2263 nfs_resop4 one_res;
2264
2265 buf[0] = '\0';
2266 if (setjmp(xdr_err)) {
2267 bp = buf + strlen(buf);
2268 snprintf(bp, buflen - (bp - buf),
2269 nfs4_fragged_rpc ? nfs4err_fragrpc : nfs4err_xdrfrag);
2270 return (buf);
2271 }
2272
2273 numres = getxdr_long();
2274 bp = buf;
2275 while (numres-- > 0) {
2276 char *result;
2277
2278 bzero(&one_res, sizeof (one_res));
2279
2280 if (!xdr_nfs_resop4(&xdrm, &one_res)) {
2281 xdr_free(xdr_nfs_resop4, (char *)&one_res);
2282 longjmp(xdr_err, 1);
2283 }
2284
2285 snprintf(bp, buflen - (bp - buf), "%s ",
2286 opcode_name(one_res.resop));
2287 bp += strlen(bp);
2288
2289 result = sum_result(&one_res);
2290 if (strlen(result) > 0) {
2291 snprintf(bp, buflen - (bp - buf), "%s ", result);
2292 bp += strlen(bp);
2293 }
2294
2295 /* nfs4_skip_bytes set by xdr_nfs4_argop4() */
2296 if (nfs4_skip_bytes != 0)
2297 nfs4_xdr_skip(nfs4_skip_bytes);
2298
2299 xdr_free(xdr_nfs_resop4, (char *)&one_res);
2300 /* add "..." if past the "end" of the buffer */
2301 if (bp - buf > SUM_COMPND_MAX) {
2302 strcpy(buf + SUM_COMPND_MAX - strlen("..."),
2303 "...");
2304 break;
2305 }
2306 }
2307
2308 return (buf);
2309 }
2310
2311
2312 /*
2313 * Return a set of summary strings for the result data that's next in the
2314 * XDR stream, up to SUM_COMPND_MAX characters. If the strings don't fit,
2315 * include a "..." at the end of the string.
2316 */
2317
2318 static char *
sum_cb_compound4res(void)2319 sum_cb_compound4res(void)
2320 {
2321 static char buf[SUM_COMPND_MAX + 2]; /* 1 for null, 1 for overflow */
2322 int numres;
2323 const size_t buflen = sizeof (buf);
2324 char *bp;
2325 nfs_cb_resop4 one_res;
2326
2327 buf[0] = '\0';
2328 if (setjmp(xdr_err)) {
2329 bp = buf + strlen(buf);
2330 snprintf(bp, buflen - (bp - buf), "<XDR Error or Fragmented"
2331 " RPC>");
2332 return (buf);
2333 }
2334
2335 numres = getxdr_long();
2336 bp = buf;
2337 while (numres-- > 0) {
2338 bzero(&one_res, sizeof (one_res));
2339 if (!xdr_nfs_cb_resop4(&xdrm, &one_res)) {
2340 xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
2341 longjmp(xdr_err, 1);
2342 }
2343 snprintf(bp, buflen - (bp - buf), "%s %s ",
2344 cb_opcode_name(one_res.resop),
2345 sum_cb_result(&one_res));
2346 bp += strlen(bp);
2347
2348 xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
2349
2350 /* add "..." if past the "end" of the buffer */
2351 if (bp - buf > SUM_COMPND_MAX) {
2352 strcpy(buf + SUM_COMPND_MAX - strlen("..."),
2353 "...");
2354 break;
2355 }
2356 }
2357
2358 return (buf);
2359 }
2360
2361
2362 /*
2363 * Return the summarized results for the given resultdata.
2364 */
2365
2366 static char *
sum_result(nfs_resop4 * resp)2367 sum_result(nfs_resop4 *resp)
2368 {
2369 static char buf[1024];
2370 void (*fmtproc)(char *, size_t, void *);
2371
2372 buf[0] = '\0';
2373 if (resp->resop < num_opcodes)
2374 fmtproc = opcode_info[resp->resop].sumres;
2375 else if (resp->resop == OP_ILLEGAL)
2376 fmtproc = sum_nfsstat4;
2377 else
2378 fmtproc = NULL;
2379
2380 if (fmtproc != NULL)
2381 fmtproc(buf, sizeof (buf), &resp->nfs_resop4_u);
2382
2383 return (buf);
2384 }
2385
2386 /*
2387 * Return the summarized results for the given resultdata.
2388 */
2389
2390 static char *
sum_cb_result(nfs_cb_resop4 * resp)2391 sum_cb_result(nfs_cb_resop4 *resp)
2392 {
2393 static char buf[1024];
2394 void (*fmtproc)(char *, size_t, void *);
2395
2396 buf[0] = '\0';
2397 if (resp->resop < cb_num_opcodes)
2398 fmtproc = cb_opcode_info[resp->resop].sumres;
2399 else if (resp->resop == OP_CB_ILLEGAL)
2400 fmtproc = sum_nfsstat4;
2401 else
2402 fmtproc = NULL;
2403
2404 if (fmtproc != NULL)
2405 fmtproc(buf, sizeof (buf), &resp->nfs_cb_resop4_u);
2406
2407 return (buf);
2408 }
2409
2410
2411 static void
dtl_change_info(char * msg,change_info4 * infop)2412 dtl_change_info(char *msg, change_info4 *infop)
2413 {
2414 sprintf(get_line(0, 0), "%s:", msg);
2415 sprintf(get_line(0, 0), " Atomic = %s",
2416 infop->atomic ? "TRUE" : "FALSE");
2417 detail_fattr4_change(" Before", infop->before);
2418 detail_fattr4_change(" After", infop->after);
2419 }
2420
2421 static void
detail_fattr4_change(char * msg,fattr4_change chg)2422 detail_fattr4_change(char *msg, fattr4_change chg)
2423 {
2424 sprintf(get_line(0, 0), "%s: 0x%llx", msg, chg);
2425 /* XXX print as time_t, too? */
2426 }
2427
2428 static void
sum_nfsstat4(char * buf,size_t buflen,void * obj)2429 sum_nfsstat4(char *buf, size_t buflen, void *obj)
2430 {
2431 nfsstat4 status = *(nfsstat4 *)obj;
2432
2433 strncpy(buf, status_name(status), buflen);
2434 }
2435
2436 static void
dtl_nfsstat4(void * obj)2437 dtl_nfsstat4(void *obj)
2438 {
2439 nfsstat4 status = *(nfsstat4 *)obj;
2440
2441 sprintf(get_line(0, 0), "Status = %d (%s)", status,
2442 status_name(status));
2443 }
2444
2445 static void
sumres_access(char * buf,size_t buflen,void * obj)2446 sumres_access(char *buf, size_t buflen, void *obj)
2447 {
2448 ACCESS4res *res = (ACCESS4res *)obj;
2449 char *bp = buf;
2450 int len, blen = buflen;
2451
2452 strcpy(bp, status_name(res->status));
2453 if (res->status == NFS4_OK) {
2454 bp += (len = strlen(bp));
2455 blen -= len;
2456
2457 snprintf(bp, blen, " Supp=");
2458 bp += (len = strlen(bp));
2459 blen -= len;
2460
2461 sum_access4(bp, blen, res->ACCESS4res_u.resok4.supported);
2462 bp += (len = strlen(bp));
2463 blen -= len;
2464
2465 snprintf(bp, blen, " Allow=");
2466 bp += (len = strlen(bp));
2467 blen -= len;
2468
2469 sum_access4(bp, blen, res->ACCESS4res_u.resok4.access);
2470 }
2471 }
2472
2473 static void
dtlres_access(void * obj)2474 dtlres_access(void *obj)
2475 {
2476 ACCESS4res *res = (ACCESS4res *)obj;
2477
2478 dtl_nfsstat4(obj);
2479 if (res->status == NFS4_OK) {
2480 detail_access4("Supported Attributes",
2481 res->ACCESS4res_u.resok4.supported);
2482 detail_access4("Allowed Attributes",
2483 res->ACCESS4res_u.resok4.access);
2484 }
2485 }
2486
2487 static void
sumres_close(char * buf,size_t buflen,void * obj)2488 sumres_close(char *buf, size_t buflen, void *obj)
2489 {
2490 CLOSE4res *res = (CLOSE4res *)obj;
2491
2492 if (res->status == NFS4_OK)
2493 snprintf(buf, buflen, "%s",
2494 sum_open_stateid(&res->CLOSE4res_u.open_stateid));
2495 }
2496
2497 static void
dtlres_close(void * obj)2498 dtlres_close(void *obj)
2499 {
2500 CLOSE4res *res = (CLOSE4res *)obj;
2501
2502 dtl_nfsstat4(obj);
2503 if (res->status == NFS4_OK) {
2504 detail_open_stateid(&res->CLOSE4res_u.open_stateid);
2505 }
2506 }
2507
2508 static void
sumres_commit(char * buf,size_t buflen,void * obj)2509 sumres_commit(char *buf, size_t buflen, void *obj)
2510 {
2511 COMMIT4res *res = (COMMIT4res *)obj;
2512
2513 if (res->status == NFS4_OK)
2514 snprintf(buf, buflen, "Verf=%s",
2515 tohex(res->COMMIT4res_u.resok4.writeverf,
2516 NFS4_VERIFIER_SIZE));
2517 }
2518
2519 static void
dtlres_commit(void * obj)2520 dtlres_commit(void *obj)
2521 {
2522 COMMIT4res *res = (COMMIT4res *)obj;
2523
2524 dtl_nfsstat4(obj);
2525 if (res->status == NFS4_OK) {
2526 sprintf(get_line(0, 0), "Verifier = %s",
2527 tohex(res->COMMIT4res_u.resok4.writeverf,
2528 NFS4_VERIFIER_SIZE));
2529 }
2530 }
2531
2532 static void
dtlres_create(void * obj)2533 dtlres_create(void *obj)
2534 {
2535 CREATE4res *res = (CREATE4res *)obj;
2536
2537 dtl_nfsstat4(obj);
2538 if (res->status == NFS4_OK) {
2539 dtl_change_info("Change Information",
2540 &res->CREATE4res_u.resok4.cinfo);
2541 detail_attr_bitmap("", &res->CREATE4res_u.resok4.attrset,
2542 NULL);
2543 }
2544 }
2545
2546 static void
sumres_getattr(char * buf,size_t buflen,void * obj)2547 sumres_getattr(char *buf, size_t buflen, void *obj)
2548 {
2549 GETATTR4res *res = (GETATTR4res *)obj;
2550
2551 strncpy(buf, status_name(res->status), buflen);
2552 }
2553
2554 static void
dtlres_getattr(void * obj)2555 dtlres_getattr(void *obj)
2556 {
2557 GETATTR4res *res = (GETATTR4res *)obj;
2558
2559 dtl_nfsstat4(obj);
2560 if (res->status == NFS4_OK) {
2561 detail_fattr4(&res->GETATTR4res_u.resok4.obj_attributes);
2562 }
2563 }
2564
2565 static void
sumres_cb_getattr(char * buf,size_t buflen,void * obj)2566 sumres_cb_getattr(char *buf, size_t buflen, void *obj)
2567 {
2568 CB_GETATTR4res *res = (CB_GETATTR4res *)obj;
2569
2570 strncpy(buf, status_name(res->status), buflen);
2571 }
2572
2573 static void
dtlres_cb_getattr(void * obj)2574 dtlres_cb_getattr(void *obj)
2575 {
2576 CB_GETATTR4res *res = (CB_GETATTR4res *)obj;
2577
2578 dtl_nfsstat4(obj);
2579 if (res->status == NFS4_OK) {
2580 detail_fattr4(&res->CB_GETATTR4res_u.resok4.obj_attributes);
2581 }
2582 }
2583
2584
2585 static void
sumres_getfh(char * buf,size_t buflen,void * obj)2586 sumres_getfh(char *buf, size_t buflen, void *obj)
2587 {
2588 char *bp;
2589 GETFH4res *res = (GETFH4res *)obj;
2590
2591 strncpy(buf, status_name(res->status), buflen);
2592 if (res->status == NFS4_OK) {
2593 bp = buf + strlen(buf);
2594 snprintf(bp, buflen - (bp - buf), " %s",
2595 sum_fh4(&res->GETFH4res_u.resok4.object));
2596 }
2597 }
2598
2599 static void
dtlres_getfh(void * obj)2600 dtlres_getfh(void *obj)
2601 {
2602 GETFH4res *res = (GETFH4res *)obj;
2603
2604 dtl_nfsstat4(obj);
2605 if (res->status == NFS4_OK) {
2606 detail_fh4(&res->GETFH4res_u.resok4.object);
2607 }
2608 }
2609
2610 static void
dtlres_link(void * obj)2611 dtlres_link(void *obj)
2612 {
2613 LINK4res *res = (LINK4res *)obj;
2614
2615 dtl_nfsstat4(obj);
2616 if (res->status == NFS4_OK) {
2617 dtl_change_info("Change Information",
2618 &res->LINK4res_u.resok4.cinfo);
2619 }
2620 }
2621
2622 static void
sumres_lock(char * buf,size_t buflen,void * obj)2623 sumres_lock(char *buf, size_t buflen, void *obj)
2624 {
2625 char *bp;
2626 LOCK4res *res = (LOCK4res *)obj;
2627
2628 strncpy(buf, status_name(res->status), buflen);
2629 if (res->status == NFS4_OK) {
2630 bp = buf + strlen(buf);
2631 snprintf(bp, buflen - (bp - buf), " %s",
2632 sum_lock_stateid(&res->LOCK4res_u.resok4.lock_stateid));
2633 }
2634 if (res->status == NFS4ERR_DENIED) {
2635 bp = buf + strlen(buf);
2636 snprintf(bp, buflen - (bp - buf), " %s",
2637 sum_lock_denied(&res->LOCK4res_u.denied));
2638 }
2639 }
2640
2641 static void
dtlres_lock(void * obj)2642 dtlres_lock(void *obj)
2643 {
2644 LOCK4res *res = (LOCK4res *)obj;
2645
2646 dtl_nfsstat4(obj);
2647 if (res->status == NFS4_OK) {
2648 detail_lock_stateid(&res->LOCK4res_u.resok4.lock_stateid);
2649 }
2650 if (res->status == NFS4ERR_DENIED) {
2651 detail_lock_denied(&res->LOCK4res_u.denied);
2652 }
2653 }
2654
2655 static void
sumres_lockt(char * buf,size_t buflen,void * obj)2656 sumres_lockt(char *buf, size_t buflen, void *obj)
2657 {
2658 char *bp;
2659 LOCKT4res *res = (LOCKT4res *)obj;
2660
2661 strcpy(buf, status_name(res->status));
2662 if (res->status == NFS4ERR_DENIED) {
2663 bp = buf + strlen(buf);
2664 snprintf(bp, buflen - (bp - buf), " %s",
2665 sum_lock_denied(&res->LOCKT4res_u.denied));
2666 }
2667 }
2668
2669 static void
dtlres_lockt(void * obj)2670 dtlres_lockt(void *obj)
2671 {
2672 LOCKT4res *res = (LOCKT4res *)obj;
2673
2674 dtl_nfsstat4(obj);
2675 if (res->status == NFS4ERR_DENIED) {
2676 detail_lock_denied(&res->LOCKT4res_u.denied);
2677 }
2678 }
2679
2680 static void
sumres_locku(char * buf,size_t buflen,void * obj)2681 sumres_locku(char *buf, size_t buflen, void *obj)
2682 {
2683 char *bp;
2684 LOCKU4res *res = (LOCKU4res *)obj;
2685
2686 strncpy(buf, status_name(res->status), buflen);
2687 bp = buf + strlen(buf);
2688 if (res->status == NFS4_OK)
2689 snprintf(bp, buflen - (bp - buf), " %s",
2690 sum_lock_stateid(&res->LOCKU4res_u.lock_stateid));
2691 }
2692
2693 static void
dtlres_locku(void * obj)2694 dtlres_locku(void *obj)
2695 {
2696 LOCKU4res *res = (LOCKU4res *)obj;
2697
2698 dtl_nfsstat4(obj);
2699 if (res->status == NFS4_OK)
2700 detail_lock_stateid(&res->LOCKU4res_u.lock_stateid);
2701 }
2702
2703 static void
sumres_open(char * buf,size_t buflen,void * obj)2704 sumres_open(char *buf, size_t buflen, void *obj)
2705 {
2706 char *bp = buf;
2707 OPEN4res *res = (OPEN4res *)obj;
2708 uint_t rflags;
2709 int len, blen = buflen;
2710
2711 strncpy(bp, status_name(res->status), blen);
2712
2713 if (res->status == NFS4_OK) {
2714 bp += (len = strlen(bp));
2715 blen -= len;
2716
2717 snprintf(bp, blen, " %s",
2718 sum_stateid(&res->OPEN4res_u.resok4.stateid));
2719 bp += (len = strlen(bp));
2720 blen -= len;
2721
2722 if ((rflags = res->OPEN4res_u.resok4.rflags) != 0) {
2723 snprintf(bp, blen, "%s", sum_open_rflags(rflags));
2724 bp += (len = strlen(bp));
2725 blen -= len;
2726 }
2727
2728 sum_delegation(bp, blen, &res->OPEN4res_u.resok4.delegation);
2729 }
2730 }
2731
2732 static void
dtlres_open(void * obj)2733 dtlres_open(void *obj)
2734 {
2735 OPEN4res *res = (OPEN4res *)obj;
2736
2737 dtl_nfsstat4(obj);
2738 if (res->status == NFS4_OK) {
2739 detail_stateid(&res->OPEN4res_u.resok4.stateid);
2740 dtl_change_info("Change Information",
2741 &res->OPEN4res_u.resok4.cinfo);
2742 sprintf(get_line(0, 0), "Flags = 0x%x (%s)",
2743 res->OPEN4res_u.resok4.rflags,
2744 detail_open_rflags(res->OPEN4res_u.resok4.rflags));
2745 detail_attr_bitmap("", &res->OPEN4res_u.resok4.attrset,
2746 NULL);
2747 detail_delegation(&res->OPEN4res_u.resok4.delegation);
2748 }
2749 }
2750
2751 static void
sumres_open_confirm(char * buf,size_t buflen,void * obj)2752 sumres_open_confirm(char *buf, size_t buflen, void *obj)
2753 {
2754 char *bp;
2755 OPEN_CONFIRM4res *res = (OPEN_CONFIRM4res *)obj;
2756
2757 strncpy(buf, status_name(res->status), buflen);
2758 if (res->status == NFS4_OK) {
2759 bp = buf + strlen(buf);
2760 snprintf(bp, buflen - (bp - buf), " %s",
2761 sum_open_stateid(&res->OPEN_CONFIRM4res_u.resok4.
2762 open_stateid));
2763 }
2764 }
2765
2766 static void
dtlres_open_confirm(void * obj)2767 dtlres_open_confirm(void *obj)
2768 {
2769 OPEN_CONFIRM4res *res = (OPEN_CONFIRM4res *)obj;
2770
2771 dtl_nfsstat4(obj);
2772 if (res->status == NFS4_OK) {
2773 detail_open_stateid(&res->OPEN_CONFIRM4res_u.resok4.
2774 open_stateid);
2775 }
2776 }
2777
2778 static void
sumres_open_downgrd(char * buf,size_t buflen,void * obj)2779 sumres_open_downgrd(char *buf, size_t buflen, void *obj)
2780 {
2781 char *bp;
2782 OPEN_DOWNGRADE4res *res = (OPEN_DOWNGRADE4res *)obj;
2783
2784 strncpy(buf, status_name(res->status), buflen);
2785 if (res->status == NFS4_OK) {
2786 bp = buf + strlen(buf);
2787 snprintf(bp, buflen - (bp - buf), " %s",
2788 sum_open_stateid(&res->OPEN_DOWNGRADE4res_u.resok4.
2789 open_stateid));
2790 }
2791 }
2792
2793 static void
dtlres_open_downgrd(void * obj)2794 dtlres_open_downgrd(void *obj)
2795 {
2796 OPEN_DOWNGRADE4res *res = (OPEN_DOWNGRADE4res *)obj;
2797
2798 dtl_nfsstat4(obj);
2799 if (res->status == NFS4_OK) {
2800 detail_open_stateid(&res->OPEN_DOWNGRADE4res_u.resok4.
2801 open_stateid);
2802 }
2803 }
2804
2805 static void
sumres_read(char * buf,size_t buflen,void * obj)2806 sumres_read(char *buf, size_t buflen, void *obj)
2807 {
2808 char *bp;
2809 READ4res *res = (READ4res *)obj;
2810
2811 strncpy(buf, status_name(res->status), buflen);
2812 if (res->status == NFS4_OK) {
2813 bp = buf + strlen(buf);
2814 snprintf(bp, buflen - (bp - buf), " (%u bytes) %s",
2815 res->READ4res_u.resok4.data.data_len,
2816 res->READ4res_u.resok4.eof ? "EOF" : "");
2817 }
2818 }
2819
2820 static void
dtlres_read(void * obj)2821 dtlres_read(void *obj)
2822 {
2823 READ4res *res = (READ4res *)obj;
2824
2825 dtl_nfsstat4(obj);
2826 if (res->status == NFS4_OK) {
2827 sprintf(get_line(0, 0), "Count = %u bytes read",
2828 res->READ4res_u.resok4.data.data_len);
2829 sprintf(get_line(0, 0), "End of file = %s",
2830 res->READ4res_u.resok4.eof ? "TRUE" : "FALSE");
2831 }
2832 }
2833
2834 static void
sumres_readdir(char * buf,size_t buflen,void * obj)2835 sumres_readdir(char *buf, size_t buflen, void *obj)
2836 {
2837 char *bp;
2838 READDIR4res *res = (READDIR4res *)obj;
2839 int num_entries = 0;
2840 entry4 *ep;
2841
2842 strncpy(buf, status_name(res->status), buflen);
2843 if (res->status == NFS4_OK) {
2844 for (ep = res->READDIR4res_u.resok4.reply.entries;
2845 ep != NULL;
2846 ep = ep->nextentry)
2847 num_entries++;
2848 bp = buf + strlen(buf);
2849 snprintf(bp, buflen - (bp - buf), " %d entries (%s)",
2850 num_entries,
2851 res->READDIR4res_u.resok4.reply.eof
2852 ? "No more" : "More");
2853 }
2854 }
2855
2856 static void
dtlres_readdir(void * obj)2857 dtlres_readdir(void *obj)
2858 {
2859 READDIR4res *res = (READDIR4res *)obj;
2860 int num_entries = 0;
2861 entry4 *ep;
2862
2863 dtl_nfsstat4(obj);
2864 if (res->status == NFS4_OK) {
2865 for (ep = res->READDIR4res_u.resok4.reply.entries;
2866 ep != NULL;
2867 ep = ep->nextentry) {
2868 num_entries++;
2869 sprintf(get_line(0, 0),
2870 "------------------ entry #%d",
2871 num_entries);
2872 sprintf(get_line(0, 0), "Cookie = %llu",
2873 ep->cookie);
2874 sprintf(get_line(0, 0), "Name = %s",
2875 component_name(&ep->name));
2876 detail_fattr4(&ep->attrs);
2877 }
2878 if (num_entries == 0)
2879 sprintf(get_line(0, 0), "(No entries)");
2880 sprintf(get_line(0, 0), "EOF = %s",
2881 res->READDIR4res_u.resok4.reply.eof ? "TRUE" : "FALSE");
2882 sprintf(get_line(0, 0), "Verifer = %s",
2883 tohex(res->READDIR4res_u.resok4.cookieverf,
2884 NFS4_VERIFIER_SIZE));
2885 }
2886 }
2887
2888 static void
sumres_readlnk(char * buf,size_t buflen,void * obj)2889 sumres_readlnk(char *buf, size_t buflen, void *obj)
2890 {
2891 char *bp;
2892 READLINK4res *res = (READLINK4res *)obj;
2893
2894 strncpy(buf, status_name(res->status), buflen);
2895 if (res->status == NFS4_OK) {
2896 bp = buf + strlen(buf);
2897 snprintf(bp, buflen - (bp - buf), " %s",
2898 linktext_name(&res->READLINK4res_u.resok4.link));
2899 }
2900 }
2901
2902 static void
dtlres_readlnk(void * obj)2903 dtlres_readlnk(void *obj)
2904 {
2905 READLINK4res *res = (READLINK4res *)obj;
2906
2907 dtl_nfsstat4(obj);
2908 if (res->status == NFS4_OK) {
2909 sprintf(get_line(0, 0), "Link = %s",
2910 linktext_name(&res->READLINK4res_u.resok4.link));
2911 }
2912 }
2913
2914 static void
dtlres_remove(void * obj)2915 dtlres_remove(void *obj)
2916 {
2917 REMOVE4res *res = (REMOVE4res *)obj;
2918
2919 dtl_nfsstat4(obj);
2920 if (res->status == NFS4_OK) {
2921 dtl_change_info("Change Information",
2922 &res->REMOVE4res_u.resok4.cinfo);
2923 }
2924 }
2925
2926 static void
dtlres_rename(void * obj)2927 dtlres_rename(void *obj)
2928 {
2929 RENAME4res *res = (RENAME4res *)obj;
2930
2931 dtl_nfsstat4(obj);
2932 if (res->status == NFS4_OK) {
2933 dtl_change_info("Source Change Information",
2934 &res->RENAME4res_u.resok4.source_cinfo);
2935 dtl_change_info("Target Change Information",
2936 &res->RENAME4res_u.resok4.target_cinfo);
2937 }
2938 }
2939
2940 static void
sumres_secinfo(char * buf,size_t buflen,void * obj)2941 sumres_secinfo(char *buf, size_t buflen, void *obj)
2942 {
2943 char *bp;
2944 SECINFO4res *res = (SECINFO4res *)obj;
2945
2946 strncpy(buf, status_name(res->status), buflen);
2947 bp = buf + strlen(buf);
2948 if (res->status == NFS4_OK) {
2949 uint_t numinfo = res->SECINFO4res_u.resok4.SECINFO4resok_len;
2950 secinfo4 *infop;
2951
2952 for (infop = res->SECINFO4res_u.resok4.SECINFO4resok_val;
2953 numinfo != 0;
2954 infop++, numinfo--) {
2955 snprintf(bp, buflen - (bp - buf), " %s",
2956 flavor_name(infop->flavor));
2957 bp += strlen(bp);
2958 }
2959 }
2960 }
2961
2962 static void
dtlres_secinfo(void * obj)2963 dtlres_secinfo(void *obj)
2964 {
2965 SECINFO4res *res = (SECINFO4res *)obj;
2966
2967 dtl_nfsstat4(obj);
2968 if (res->status == NFS4_OK) {
2969 uint_t numinfo =
2970 res->SECINFO4res_u.resok4.SECINFO4resok_len;
2971 secinfo4 *infop;
2972
2973 for (infop = res->SECINFO4res_u.resok4.SECINFO4resok_val;
2974 numinfo != 0;
2975 infop++, numinfo--) {
2976 detail_secinfo4(infop);
2977 }
2978 }
2979 }
2980
2981 static void
sumres_setattr(char * buf,size_t buflen,void * obj)2982 sumres_setattr(char *buf, size_t buflen, void *obj)
2983 {
2984 SETATTR4res *res = (SETATTR4res *)obj;
2985 size_t len;
2986
2987 (void) snprintf(buf, buflen, "%s ", status_name(res->status));
2988 len = strlen(buf);
2989 sum_attr_bitmap(buf + len, buflen - len, &res->attrsset);
2990 }
2991
2992 static void
dtlres_setattr(void * obj)2993 dtlres_setattr(void *obj)
2994 {
2995 SETATTR4res *res = (SETATTR4res *)obj;
2996
2997 dtl_nfsstat4(obj);
2998 detail_attr_bitmap("", &res->attrsset, NULL);
2999 }
3000
3001 static void
sumres_setclid(char * buf,size_t buflen,void * obj)3002 sumres_setclid(char *buf, size_t buflen, void *obj)
3003 {
3004 char *bp;
3005 SETCLIENTID4res *res = (SETCLIENTID4res *)obj;
3006
3007 strncpy(buf, status_name(res->status), buflen);
3008 switch (res->status) {
3009 case NFS_OK:
3010 bp = buf + strlen(buf);
3011 snprintf(bp, buflen - (bp - buf), " %s CFV=%s",
3012 sum_clientid(res->SETCLIENTID4res_u.resok4.clientid),
3013 tohex(res->SETCLIENTID4res_u.resok4.setclientid_confirm,
3014 NFS4_VERIFIER_SIZE));
3015 break;
3016 case NFS4ERR_CLID_INUSE:
3017 bp = buf + strlen(buf);
3018 snprintf(bp, buflen - (bp - buf), " ID=%s Addr=%s",
3019 res->SETCLIENTID4res_u.client_using.na_r_netid,
3020 res->SETCLIENTID4res_u.client_using.na_r_addr);
3021 break;
3022 }
3023 }
3024
3025 static void
dtlres_setclid(void * obj)3026 dtlres_setclid(void *obj)
3027 {
3028 SETCLIENTID4res *res = (SETCLIENTID4res *)obj;
3029
3030 dtl_nfsstat4(obj);
3031 switch (res->status) {
3032 case NFS_OK:
3033 detail_clientid(res->SETCLIENTID4res_u.resok4.clientid);
3034 sprintf(get_line(0, 0), "Set Client ID Confirm Verifier = %s",
3035 tohex(res->SETCLIENTID4res_u.resok4.setclientid_confirm,
3036 NFS4_VERIFIER_SIZE));
3037 break;
3038 case NFS4ERR_CLID_INUSE:
3039 sprintf(get_line(0, 0), "Used by Net ID = %s",
3040 res->SETCLIENTID4res_u.client_using.na_r_netid);
3041 sprintf(get_line(0, 0), "Used by Addr = %s",
3042 res->SETCLIENTID4res_u.client_using.na_r_addr);
3043 break;
3044 }
3045 }
3046
3047 static void
sumres_write(char * buf,size_t buflen,void * obj)3048 sumres_write(char *buf, size_t buflen, void *obj)
3049 {
3050 char *bp;
3051 WRITE4res *res = (WRITE4res *)obj;
3052
3053 strncpy(buf, status_name(res->status), buflen);
3054 if (res->status == NFS4_OK) {
3055 bp = buf + strlen(buf);
3056 snprintf(bp, buflen - (bp - buf), " %u (%s)",
3057 res->WRITE4res_u.resok4.count,
3058 stable_how4_name(res->WRITE4res_u.resok4.committed));
3059 }
3060 }
3061
3062 static void
dtlres_write(void * obj)3063 dtlres_write(void *obj)
3064 {
3065 WRITE4res *res = (WRITE4res *)obj;
3066
3067 dtl_nfsstat4(obj);
3068 if (res->status == NFS4_OK) {
3069 sprintf(get_line(0, 0), "Count = %u bytes written",
3070 res->WRITE4res_u.resok4.count);
3071 sprintf(get_line(0, 0), "Stable = %s",
3072 stable_how4_name(res->WRITE4res_u.resok4.committed));
3073 sprintf(get_line(0, 0), "Verifier = %s",
3074 tohex(res->WRITE4res_u.resok4.writeverf,
3075 NFS4_VERIFIER_SIZE));
3076 }
3077 }
3078
3079 /*
3080 * Print details about the nfs_resop4 that is next in the XDR stream.
3081 */
3082
3083 static void
detail_nfs_resop4(void)3084 detail_nfs_resop4(void)
3085 {
3086 int numres;
3087 nfs_resop4 one_res;
3088 void (*fmtproc)(void *);
3089
3090 numres = getxdr_long();
3091 (void) sprintf(get_line(0, 0), "Number of results = %d",
3092 numres);
3093
3094 while (numres-- > 0) {
3095 bzero(&one_res, sizeof (one_res));
3096
3097 if (!xdr_nfs_resop4(&xdrm, &one_res)) {
3098 xdr_free(xdr_nfs_resop4, (char *)&one_res);
3099 longjmp(xdr_err, 1);
3100 }
3101
3102 get_line(0, 0); /* blank line to separate ops */
3103 sprintf(get_line(0, 0), "Op = %d (%s)",
3104 one_res.resop, opcode_name(one_res.resop));
3105 if (one_res.resop < num_opcodes)
3106 fmtproc = opcode_info[one_res.resop].dtlres;
3107 else if (one_res.resop == OP_ILLEGAL)
3108 fmtproc = dtl_nfsstat4;
3109 else
3110 fmtproc = NULL;
3111
3112 if (fmtproc != NULL)
3113 fmtproc(&one_res.nfs_resop4_u);
3114
3115 /* nfs4_skip_bytes set by xdr_nfs_resop4()() */
3116 if (nfs4_skip_bytes)
3117 nfs4_xdr_skip(nfs4_skip_bytes);
3118
3119 xdr_free(xdr_nfs_resop4, (char *)&one_res);
3120 }
3121 }
3122
3123
3124 /*
3125 * Print details about the nfs_cb_resop4 that is next in the XDR stream.
3126 */
3127
3128 static void
detail_cb_resop4(void)3129 detail_cb_resop4(void)
3130 {
3131 int numres;
3132 nfs_cb_resop4 one_res;
3133 void (*fmtproc)(void *);
3134
3135 numres = getxdr_long();
3136 (void) sprintf(get_line(0, 0), "Number of results = %d",
3137 numres);
3138
3139 while (numres-- > 0) {
3140 bzero(&one_res, sizeof (one_res));
3141 if (!xdr_nfs_cb_resop4(&xdrm, &one_res))
3142 longjmp(xdr_err, 1);
3143
3144 get_line(0, 0); /* blank line to separate ops */
3145 sprintf(get_line(0, 0), "Op = %d (%s)",
3146 one_res.resop, cb_opcode_name(one_res.resop));
3147 if (one_res.resop < cb_num_opcodes)
3148 fmtproc = cb_opcode_info[one_res.resop].dtlres;
3149 else if (one_res.resop == OP_CB_ILLEGAL)
3150 fmtproc = dtl_nfsstat4;
3151 else
3152 fmtproc = NULL;
3153
3154 if (fmtproc != NULL)
3155 fmtproc(&one_res.nfs_cb_resop4_u);
3156
3157 xdr_free(xdr_nfs_cb_resop4, (char *)&one_res);
3158 }
3159 }
3160
3161
3162 /*
3163 * Return the name of a lock type.
3164 */
3165 static char *
lock_type_name(enum nfs_lock_type4 type)3166 lock_type_name(enum nfs_lock_type4 type)
3167 {
3168 char *result;
3169
3170 switch (type) {
3171 case READ_LT:
3172 result = "READ";
3173 break;
3174 case WRITE_LT:
3175 result = "WRITE";
3176 break;
3177 case READW_LT:
3178 result = "READW";
3179 break;
3180 case WRITEW_LT:
3181 result = "WRITEW";
3182 break;
3183 default:
3184 result = "?";
3185 break;
3186 }
3187
3188 return (result);
3189 }
3190
3191 /*
3192 * Return the name of an opcode.
3193 */
3194
3195 static char *
opcode_name(uint_t opnum)3196 opcode_name(uint_t opnum)
3197 {
3198 static char buf[20];
3199
3200 if (opnum < num_opcodes)
3201 return (opcode_info[opnum].name);
3202
3203 if (opnum == OP_ILLEGAL)
3204 return ("ILLEGAL");
3205
3206 sprintf(buf, "op %d", opnum);
3207 return (buf);
3208 }
3209
3210 /*
3211 * Return the name of an opcode.
3212 */
3213 static char *
cb_opcode_name(uint_t opnum)3214 cb_opcode_name(uint_t opnum)
3215 {
3216 static char buf[20];
3217
3218 if (opnum < cb_num_opcodes)
3219 return (cb_opcode_info[opnum].name);
3220
3221 if (opnum == OP_CB_ILLEGAL)
3222 return ("CB_ILLEGAL");
3223
3224 sprintf(buf, "op %d", opnum);
3225 return (buf);
3226 }
3227
3228
3229 /*
3230 * Fill in a summary string for the given access bitmask.
3231 */
3232
3233 static void
sum_access4(char * buf,size_t buflen,uint32_t bits)3234 sum_access4(char *buf, size_t buflen, uint32_t bits)
3235 {
3236 buf[0] = '\0';
3237
3238 if (bits & ACCESS4_READ)
3239 (void) strncat(buf, "rd,", buflen);
3240 if (bits & ACCESS4_LOOKUP)
3241 (void) strncat(buf, "lk,", buflen);
3242 if (bits & ACCESS4_MODIFY)
3243 (void) strncat(buf, "mo,", buflen);
3244 if (bits & ACCESS4_EXTEND)
3245 (void) strncat(buf, "ext,", buflen);
3246 if (bits & ACCESS4_DELETE)
3247 (void) strncat(buf, "dl,", buflen);
3248 if (bits & ACCESS4_EXECUTE)
3249 (void) strncat(buf, "exc,", buflen);
3250 if (buf[0] != '\0')
3251 buf[strlen(buf) - 1] = '\0';
3252 }
3253
3254 /*
3255 * Print detail information about the given access bitmask.
3256 */
3257
3258 static void
detail_access4(char * descrip,uint32_t bits)3259 detail_access4(char *descrip, uint32_t bits)
3260 {
3261 sprintf(get_line(0, 0), "%s = 0x%08x", descrip, bits);
3262
3263 (void) sprintf(get_line(0, 0), " %s",
3264 getflag(bits, ACCESS4_READ, "Read", "(no read)"));
3265 (void) sprintf(get_line(0, 0), " %s",
3266 getflag(bits, ACCESS4_LOOKUP, "Lookup", "(no lookup)"));
3267 (void) sprintf(get_line(0, 0), " %s",
3268 getflag(bits, ACCESS4_MODIFY, "Modify", "(no modify)"));
3269 (void) sprintf(get_line(0, 0), " %s",
3270 getflag(bits, ACCESS4_EXTEND, "Extend", "(no extend)"));
3271 (void) sprintf(get_line(0, 0), " %s",
3272 getflag(bits, ACCESS4_DELETE, "Delete", "(no delete)"));
3273 (void) sprintf(get_line(0, 0), " %s",
3274 getflag(bits, ACCESS4_EXECUTE, "Execute", "(no execute)"));
3275 }
3276
3277
3278 /*
3279 * Fill in a summary string for the given open_claim4.
3280 */
3281 static void
sum_name(char * buf,size_t buflen,open_claim4 * claim)3282 sum_name(char *buf, size_t buflen, open_claim4 *claim)
3283 {
3284 char *bp = buf;
3285
3286 switch (claim->claim) {
3287 case CLAIM_NULL:
3288 snprintf(bp, buflen, "%s ",
3289 component_name(&claim->open_claim4_u.file));
3290 break;
3291 case CLAIM_PREVIOUS:
3292 break;
3293 case CLAIM_DELEGATE_CUR:
3294 snprintf(bp, buflen, "%s ",
3295 component_name(&claim->open_claim4_u.
3296 delegate_cur_info.file));
3297 break;
3298 case CLAIM_DELEGATE_PREV:
3299 snprintf(bp, buflen, "%s ",
3300 component_name(&claim->open_claim4_u.
3301 file_delegate_prev));
3302 break;
3303 }
3304 }
3305
3306 /*
3307 * Fill in a summary string for the given open_claim4.
3308 */
3309 static void
sum_claim(char * buf,size_t buflen,open_claim4 * claim)3310 sum_claim(char *buf, size_t buflen, open_claim4 *claim)
3311 {
3312 char *bp = buf;
3313
3314 switch (claim->claim) {
3315 case CLAIM_NULL:
3316 snprintf(bp, buflen, " CT=N");
3317 break;
3318 case CLAIM_PREVIOUS:
3319 snprintf(bp, buflen, " CT=P DT=%s",
3320 get_deleg_typestr(claim->open_claim4_u.delegate_type));
3321 break;
3322 case CLAIM_DELEGATE_CUR:
3323 snprintf(bp, buflen, " CT=DC %s",
3324 sum_deleg_stateid(&claim->open_claim4_u.
3325 delegate_cur_info.delegate_stateid));
3326 break;
3327 case CLAIM_DELEGATE_PREV:
3328 snprintf(bp, buflen, " CT=DP");
3329 break;
3330 default:
3331 snprintf(bp, buflen, " CT=?");
3332 break;
3333 }
3334 }
3335
3336 static char *
get_deleg_typestr(open_delegation_type4 dt)3337 get_deleg_typestr(open_delegation_type4 dt)
3338 {
3339 char *str = "";
3340
3341 switch (dt) {
3342 case OPEN_DELEGATE_NONE:
3343 str = "N";
3344 break;
3345 case OPEN_DELEGATE_READ:
3346 str = "R";
3347 break;
3348 case OPEN_DELEGATE_WRITE:
3349 str = "W";
3350 break;
3351 default:
3352 str = "?";
3353 }
3354
3355 return (str);
3356 }
3357
3358 /*
3359 * Print detail information for the given open_claim4.
3360 */
3361
3362 static void
detail_claim(open_claim4 * claim)3363 detail_claim(open_claim4 *claim)
3364 {
3365 sprintf(get_line(0, 0), "Claim Type = %d (%s)",
3366 claim->claim, claim_name(claim->claim));
3367
3368 switch (claim->claim) {
3369 case CLAIM_NULL:
3370 detail_compname4(&claim->open_claim4_u.file);
3371 break;
3372 case CLAIM_PREVIOUS:
3373 sprintf(get_line(0, 0), "Delegate Type = %s (val = %d)",
3374 get_deleg_typestr(claim->open_claim4_u.delegate_type),
3375 claim->open_claim4_u.delegate_type);
3376 break;
3377 case CLAIM_DELEGATE_CUR:
3378 detail_compname4(&claim->open_claim4_u.delegate_cur_info.file);
3379 detail_deleg_stateid(&claim->open_claim4_u.delegate_cur_info.
3380 delegate_stateid);
3381 break;
3382 case CLAIM_DELEGATE_PREV:
3383 detail_compname4(&claim->open_claim4_u.file_delegate_prev);
3384 break;
3385 }
3386 }
3387
3388 /*
3389 * Return a summary string for the given clientid4.
3390 */
3391 static char *
sum_clientid(clientid4 client)3392 sum_clientid(clientid4 client)
3393 {
3394 static char buf[50];
3395
3396 snprintf(buf, sizeof (buf), "CL=%llx", client);
3397
3398 return (buf);
3399 }
3400
3401 /*
3402 * Print a detail string for the given clientid4.
3403 */
3404 static void
detail_clientid(clientid4 client)3405 detail_clientid(clientid4 client)
3406 {
3407 sprintf(get_line(0, 0), "Client ID = %llx", client);
3408 }
3409
3410 /*
3411 * Write a summary string for the given delegation into buf.
3412 */
3413
3414 static void
sum_delegation(char * buf,size_t buflen,open_delegation4 * delp)3415 sum_delegation(char *buf, size_t buflen, open_delegation4 *delp)
3416 {
3417 switch (delp->delegation_type) {
3418 case OPEN_DELEGATE_NONE:
3419 snprintf(buf, buflen, " DT=N");
3420 break;
3421 case OPEN_DELEGATE_READ:
3422 snprintf(buf, buflen, " DT=R %s",
3423 sum_deleg_stateid(&delp->open_delegation4_u.write.
3424 stateid));
3425 break;
3426 case OPEN_DELEGATE_WRITE:
3427 snprintf(buf, buflen, " DT=W %s %s",
3428 sum_deleg_stateid(&delp->open_delegation4_u.write.
3429 stateid),
3430 sum_space_limit(&delp->open_delegation4_u.write.
3431 space_limit));
3432 break;
3433 default:
3434 snprintf(buf, buflen, " DT=?");
3435 break;
3436 }
3437 }
3438
3439 static void
detail_delegation(open_delegation4 * delp)3440 detail_delegation(open_delegation4 *delp)
3441 {
3442 sprintf(get_line(0, 0), "Delegation Type = %d (%s)",
3443 delp->delegation_type,
3444 delegation_type_name(delp->delegation_type));
3445
3446 switch (delp->delegation_type) {
3447 case OPEN_DELEGATE_NONE:
3448 /* no-op */
3449 break;
3450 case OPEN_DELEGATE_READ:
3451 detail_deleg_stateid(&delp->open_delegation4_u.read.stateid);
3452 sprintf(get_line(0, 0), "Recall = %s",
3453 delp->open_delegation4_u.read.recall ?
3454 "TRUE" : "FALSE");
3455 sprintf(get_line(0, 0), "[nfsacl4]");
3456 break;
3457 case OPEN_DELEGATE_WRITE:
3458 detail_deleg_stateid(&delp->open_delegation4_u.write.stateid);
3459 sprintf(get_line(0, 0), "Recall = %s",
3460 delp->open_delegation4_u.write.recall ?
3461 "TRUE" : "FALSE");
3462 detail_space_limit(&delp->open_delegation4_u.write.
3463 space_limit);
3464 sprintf(get_line(0, 0), "[nfsacl4]");
3465 break;
3466 }
3467 }
3468
3469
3470 static void
detail_open_owner(open_owner4 * owner)3471 detail_open_owner(open_owner4 *owner)
3472 {
3473 sprintf(get_line(0, 0), "Open Owner hash = [%04X] ",
3474 owner_hash(&owner->owner));
3475 sprintf(get_line(0, 0), " len = %u val = %s ",
3476 owner->owner.owner_len,
3477 tohex(owner->owner.owner_val, owner->owner.owner_len));
3478 detail_clientid(owner->clientid);
3479 }
3480
3481 static void
detail_lock_owner(lock_owner4 * owner)3482 detail_lock_owner(lock_owner4 *owner)
3483 {
3484 sprintf(get_line(0, 0), "Lock Owner hash = [%04X] ",
3485 owner_hash(&owner->owner));
3486 sprintf(get_line(0, 0), " len = %u val = %s ",
3487 owner->owner.owner_len,
3488 tohex(owner->owner.owner_val, owner->owner.owner_len));
3489 detail_clientid(owner->clientid);
3490 }
3491
3492 static void
sum_openflag(char * bufp,int buflen,openflag4 * flagp)3493 sum_openflag(char *bufp, int buflen, openflag4 *flagp)
3494 {
3495 if (flagp->opentype == OPEN4_CREATE) {
3496 switch (flagp->openflag4_u.how.mode) {
3497 case UNCHECKED4:
3498 snprintf(bufp, buflen, "OT=CR(U)");
3499 break;
3500 case GUARDED4:
3501 snprintf(bufp, buflen, "OT=CR(G)");
3502 break;
3503 case EXCLUSIVE4:
3504 snprintf(bufp, buflen, "OT=CR(E)");
3505 break;
3506 default:
3507 snprintf(bufp, buflen, "OT=CR(?:%d)",
3508 flagp->openflag4_u.how.mode);
3509 break;
3510 }
3511 } else
3512 snprintf(bufp, buflen, "OT=NC");
3513 }
3514
3515 static void
detail_openflag(openflag4 * flagp)3516 detail_openflag(openflag4 *flagp)
3517 {
3518 sprintf(get_line(0, 0), "Open Type = %s",
3519 flagp->opentype == OPEN4_CREATE ? "CREATE" : "NOCREATE");
3520 if (flagp->opentype == OPEN4_CREATE)
3521 detail_createhow4(&flagp->openflag4_u.how);
3522 }
3523
3524 /*
3525 * Fill in buf with the given path.
3526 */
3527 static void
sum_pathname4(char * buf,size_t buflen,pathname4 * pathp)3528 sum_pathname4(char *buf, size_t buflen, pathname4 *pathp)
3529 {
3530 char *bp = buf;
3531 uint_t component;
3532
3533 for (component = 0; component < pathp->pathname4_len;
3534 component++) {
3535 snprintf(bp, buflen - (bp - buf),
3536 component == 0 ? "%s" : "/%s",
3537 component_name(&pathp->pathname4_val[component]));
3538 bp += strlen(bp);
3539 }
3540 }
3541
3542 static void
sum_compname4(char * buf,size_t buflen,component4 * comp)3543 sum_compname4(char *buf, size_t buflen, component4 *comp)
3544 {
3545 snprintf(buf, buflen, "%s", component_name(comp));
3546 }
3547
3548 static void
detail_compname4(component4 * comp)3549 detail_compname4(component4 *comp)
3550 {
3551 sprintf(get_line(0, 0), "%s", component_name(comp));
3552 }
3553
3554 static void
detail_pathname4(pathname4 * pathp,char * what)3555 detail_pathname4(pathname4 *pathp, char *what)
3556 {
3557 char *bp = get_line(0, 0);
3558 uint_t component;
3559
3560 sprintf(bp, what);
3561 bp += strlen(bp);
3562
3563 for (component = 0; component < pathp->pathname4_len; component++) {
3564 sprintf(bp, component == 0 ? "%s" : "/%s",
3565 component_name(&pathp->pathname4_val[component]));
3566 bp += strlen(bp);
3567 }
3568 }
3569
3570 /*
3571 * Print detail information about the rpcsec_gss_info that is XDR-encoded
3572 * at mem.
3573 */
3574
3575 static void
detail_rpcsec_gss(rpcsec_gss_info * info)3576 detail_rpcsec_gss(rpcsec_gss_info *info)
3577 {
3578 sprintf(get_line(0, 0), "OID = %s",
3579 tohex(info->oid.sec_oid4_val, info->oid.sec_oid4_len));
3580 sprintf(get_line(0, 0), "QOP = %u", info->qop);
3581 sprintf(get_line(0, 0), "Service = %d (%s)",
3582 info->service, gss_svc_name(info->service));
3583 }
3584
3585 /*
3586 * Print detail information about the given secinfo4.
3587 */
3588
3589 static void
detail_secinfo4(secinfo4 * infop)3590 detail_secinfo4(secinfo4 *infop)
3591 {
3592 sprintf(get_line(0, 0), "Flavor = %d (%s)",
3593 infop->flavor, flavor_name(infop->flavor));
3594 switch (infop->flavor) {
3595 case RPCSEC_GSS:
3596 detail_rpcsec_gss(&infop->secinfo4_u.flavor_info);
3597 break;
3598 }
3599 }
3600
3601
3602 /*
3603 * Return a summary string corresponding to the given nfs_space_limit4.
3604 */
3605
3606 static char *
sum_space_limit(nfs_space_limit4 * limitp)3607 sum_space_limit(nfs_space_limit4 *limitp)
3608 {
3609 static char buf[64];
3610 int buflen = sizeof (buf);
3611
3612 buf[0] = '\0';
3613 switch (limitp->limitby) {
3614 case NFS_LIMIT_SIZE:
3615 snprintf(buf, buflen, "LB=SZ(%llu)",
3616 limitp->nfs_space_limit4_u.filesize);
3617 break;
3618 case NFS_LIMIT_BLOCKS:
3619 snprintf(buf, buflen, "LB=BL(%u*%u)",
3620 limitp->nfs_space_limit4_u.mod_blocks.num_blocks,
3621 limitp->nfs_space_limit4_u.mod_blocks.bytes_per_block);
3622 break;
3623 default:
3624 snprintf(buf, buflen, "LB=?(%d)", limitp->limitby);
3625 break;
3626 }
3627
3628 return (buf);
3629 }
3630
3631 /*
3632 * Print detail information about the given nfs_space_limit4.
3633 */
3634
3635 static void
detail_space_limit(nfs_space_limit4 * limitp)3636 detail_space_limit(nfs_space_limit4 *limitp)
3637 {
3638 sprintf(get_line(0, 0), "LimitBy = %d (%s)",
3639 limitp->limitby,
3640 limitby_name(limitp->limitby));
3641
3642 switch (limitp->limitby) {
3643 case NFS_LIMIT_SIZE:
3644 sprintf(get_line(0, 0), "Bytes = %llu",
3645 limitp->nfs_space_limit4_u.filesize);
3646 break;
3647 case NFS_LIMIT_BLOCKS:
3648 sprintf(get_line(0, 0), "Blocks = %u",
3649 limitp->nfs_space_limit4_u.mod_blocks.num_blocks);
3650 sprintf(get_line(0, 0), "Bytes Per Block = %u",
3651 limitp->nfs_space_limit4_u.mod_blocks.bytes_per_block);
3652 break;
3653 }
3654 }
3655
3656
3657 /*
3658 * Return the short name of a file type.
3659 */
3660
3661 static char *
sum_type_name(nfs_ftype4 type)3662 sum_type_name(nfs_ftype4 type)
3663 {
3664 static char buf[20];
3665
3666 if (type < num_ftypes)
3667 return (ftype_names[type].short_name);
3668 else {
3669 sprintf(buf, "type %d", type);
3670 return (buf);
3671 }
3672 }
3673
3674
3675 /*
3676 * Return string with long/short flag names
3677 */
3678
3679 static char *
get_flags(uint_t flag,ftype_names_t * names,uint_t num_flags,int shortname,char * prefix)3680 get_flags(uint_t flag, ftype_names_t *names, uint_t num_flags, int shortname,
3681 char *prefix)
3682 {
3683 static char buf[200];
3684 char *bp = buf, *str;
3685 int i, len, blen = sizeof (buf);
3686 ftype_names_t *fn = NULL;
3687
3688 *bp = '\0';
3689
3690 if (prefix) {
3691 snprintf(bp, blen, "%s", prefix);
3692 bp += (len = sizeof (bp));
3693 blen -= len;
3694 }
3695
3696 for (i = 0; i < 32; i++)
3697 if (flag & (1 << i)) {
3698 fn = names + (i < num_flags ? i : num_flags);
3699 str = (shortname ? fn->short_name : fn->long_name);
3700
3701 snprintf(bp, blen, "%s,", str);
3702 bp += (len = strlen(bp));
3703 blen -= len;
3704 }
3705
3706 if (fn)
3707 *(bp - 1) = '\0';
3708 else
3709 *buf = '\0';
3710
3711 return (buf);
3712 }
3713
3714
3715 /*
3716 * Return the long name of a file type.
3717 */
3718
3719 static char *
detail_type_name(nfs_ftype4 type)3720 detail_type_name(nfs_ftype4 type)
3721 {
3722 static char buf[20];
3723
3724 if (type < num_ftypes)
3725 return (ftype_names[type].long_name);
3726 else {
3727 sprintf(buf, "type %d", type);
3728 return (buf);
3729 }
3730 }
3731
3732 /*
3733 * Return the name of an attribute.
3734 */
3735
3736 static char *
attr_name(uint_t attrnum)3737 attr_name(uint_t attrnum)
3738 {
3739 static char buf[20];
3740
3741 if (attrnum < MAX_ATTRIBUTES)
3742 return (attr_info[attrnum].name);
3743 else {
3744 sprintf(buf, "attr #%d", attrnum);
3745 return (buf);
3746 }
3747 }
3748
3749 /*
3750 * Return the name of the given open_claim_type4.
3751 */
3752
3753 static char *
claim_name(enum open_claim_type4 claim_type)3754 claim_name(enum open_claim_type4 claim_type)
3755 {
3756 char *result;
3757
3758 switch (claim_type) {
3759 case CLAIM_NULL:
3760 result = "NULL";
3761 break;
3762 case CLAIM_PREVIOUS:
3763 result = "PREVIOUS";
3764 break;
3765 case CLAIM_DELEGATE_CUR:
3766 result = "DELEGATE CURRENT";
3767 break;
3768 case CLAIM_DELEGATE_PREV:
3769 result = "DELEGATE PREVIOUS";
3770 break;
3771 default:
3772 result = "?";
3773 break;
3774 }
3775
3776 return (result);
3777 }
3778
3779 /*
3780 * Return a string naming the given delegation.
3781 */
3782
3783 static char *
delegation_type_name(enum open_delegation_type4 type)3784 delegation_type_name(enum open_delegation_type4 type)
3785 {
3786 char *result;
3787
3788 switch (type) {
3789 case OPEN_DELEGATE_NONE:
3790 result = "NONE";
3791 break;
3792 case OPEN_DELEGATE_READ:
3793 result = "READ";
3794 break;
3795 case OPEN_DELEGATE_WRITE:
3796 result = "WRITE";
3797 break;
3798 default:
3799 result = "?";
3800 break;
3801 }
3802
3803 return (result);
3804 }
3805
3806 /*
3807 * Return the name of the given authentication flavor.
3808 */
3809
3810 static char *
flavor_name(uint_t flavor)3811 flavor_name(uint_t flavor)
3812 {
3813 char *result;
3814 static char buf[50];
3815
3816 switch (flavor) {
3817 case AUTH_SYS:
3818 result = "AUTH_SYS";
3819 break;
3820 case AUTH_NONE:
3821 result = "AUTH_NONE";
3822 break;
3823 case AUTH_DH:
3824 result = "AUTH_DH";
3825 break;
3826 case RPCSEC_GSS:
3827 result = "RPCSEC_GSS";
3828 break;
3829 default:
3830 sprintf(buf, "[flavor %d]", flavor);
3831 result = buf;
3832 break;
3833 }
3834
3835 return (result);
3836 }
3837
3838 /*
3839 * Return the name of the given rpc_gss_svc_t.
3840 */
3841
3842 static char *
gss_svc_name(rpc_gss_svc_t svc)3843 gss_svc_name(rpc_gss_svc_t svc)
3844 {
3845 char *result;
3846 static char buf[50];
3847
3848 switch (svc) {
3849 case RPC_GSS_SVC_NONE:
3850 result = "NONE";
3851 break;
3852 case RPC_GSS_SVC_INTEGRITY:
3853 result = "INTEGRITY";
3854 break;
3855 case RPC_GSS_SVC_PRIVACY:
3856 result = "PRIVACY";
3857 break;
3858 default:
3859 sprintf(buf, "Service %d", svc);
3860 result = buf;
3861 break;
3862 }
3863
3864 return (result);
3865 }
3866
3867 /*
3868 * Return a string name for the given limit_by4.
3869 */
3870
3871 static char *
limitby_name(enum limit_by4 limitby)3872 limitby_name(enum limit_by4 limitby)
3873 {
3874 char *result;
3875
3876 switch (limitby) {
3877 case NFS_LIMIT_SIZE:
3878 result = "SIZE";
3879 break;
3880 case NFS_LIMIT_BLOCKS:
3881 result = "BLOCKS";
3882 break;
3883 default:
3884 result = "?";
3885 break;
3886 }
3887
3888 return (result);
3889 }
3890
3891 static char *
status_name(int status)3892 status_name(int status)
3893 {
3894 char *p;
3895
3896 switch (status) {
3897 case NFS4_OK: p = "NFS4_OK"; break;
3898 case NFS4ERR_PERM: p = "NFS4ERR_PERM"; break;
3899 case NFS4ERR_NOENT: p = "NFS4ERR_NOENT"; break;
3900 case NFS4ERR_IO: p = "NFS4ERR_IO"; break;
3901 case NFS4ERR_NXIO: p = "NFS4ERR_NXIO"; break;
3902 case NFS4ERR_ACCESS: p = "NFS4ERR_ACCESS"; break;
3903 case NFS4ERR_EXIST: p = "NFS4ERR_EXIST"; break;
3904 case NFS4ERR_XDEV: p = "NFS4ERR_XDEV"; break;
3905 case NFS4ERR_NOTDIR: p = "NFS4ERR_NOTDIR"; break;
3906 case NFS4ERR_ISDIR: p = "NFS4ERR_ISDIR"; break;
3907 case NFS4ERR_INVAL: p = "NFS4ERR_INVAL"; break;
3908 case NFS4ERR_FBIG: p = "NFS4ERR_FBIG"; break;
3909 case NFS4ERR_NOSPC: p = "NFS4ERR_NOSPC"; break;
3910 case NFS4ERR_ROFS: p = "NFS4ERR_ROFS"; break;
3911 case NFS4ERR_MLINK: p = "NFS4ERR_MLINK"; break;
3912 case NFS4ERR_NAMETOOLONG:p = "NFS4ERR_NAMETOOLONG"; break;
3913 case NFS4ERR_NOTEMPTY: p = "NFS4ERR_NOTEMPTY"; break;
3914 case NFS4ERR_DQUOT: p = "NFS4ERR_DQUOT"; break;
3915 case NFS4ERR_STALE: p = "NFS4ERR_STALE"; break;
3916 case NFS4ERR_BADHANDLE: p = "NFS4ERR_BADHANDLE"; break;
3917 case NFS4ERR_BAD_COOKIE:p = "NFS4ERR_BAD_COOKIE"; break;
3918 case NFS4ERR_NOTSUPP: p = "NFS4ERR_NOTSUPP"; break;
3919 case NFS4ERR_TOOSMALL: p = "NFS4ERR_TOOSMALL"; break;
3920 case NFS4ERR_SERVERFAULT:p = "NFS4ERR_SERVERFAULT"; break;
3921 case NFS4ERR_BADTYPE: p = "NFS4ERR_BADTYPE"; break;
3922 case NFS4ERR_DELAY: p = "NFS4ERR_DELAY"; break;
3923 case NFS4ERR_SAME: p = "NFS4ERR_SAME"; break;
3924 case NFS4ERR_DENIED: p = "NFS4ERR_DENIED"; break;
3925 case NFS4ERR_EXPIRED: p = "NFS4ERR_EXPIRED"; break;
3926 case NFS4ERR_LOCKED: p = "NFS4ERR_LOCKED"; break;
3927 case NFS4ERR_GRACE: p = "NFS4ERR_GRACE"; break;
3928 case NFS4ERR_FHEXPIRED: p = "NFS4ERR_FHEXPIRED"; break;
3929 case NFS4ERR_SHARE_DENIED: p = "NFS4ERR_SHARE_DENIED"; break;
3930 case NFS4ERR_WRONGSEC: p = "NFS4ERR_WRONGSEC"; break;
3931 case NFS4ERR_CLID_INUSE: p = "NFS4ERR_CLID_INUSE"; break;
3932 case NFS4ERR_RESOURCE: p = "NFS4ERR_RESOURCE"; break;
3933 case NFS4ERR_MOVED: p = "NFS4ERR_MOVED"; break;
3934 case NFS4ERR_NOFILEHANDLE: p = "NFS4ERR_NOFILEHANDLE"; break;
3935 case NFS4ERR_MINOR_VERS_MISMATCH: p = "NFS4ERR_MINOR_VERS_MISMATCH";
3936 break;
3937 case NFS4ERR_STALE_CLIENTID: p = "NFS4ERR_STALE_CLIENTID"; break;
3938 case NFS4ERR_STALE_STATEID: p = "NFS4ERR_STALE_STATEID"; break;
3939 case NFS4ERR_OLD_STATEID: p = "NFS4ERR_OLD_STATEID"; break;
3940 case NFS4ERR_BAD_STATEID: p = "NFS4ERR_BAD_STATEID"; break;
3941 case NFS4ERR_BAD_SEQID: p = "NFS4ERR_BAD_SEQID"; break;
3942 case NFS4ERR_NOT_SAME: p = "NFS4ERR_NOT_SAME"; break;
3943 case NFS4ERR_LOCK_RANGE: p = "NFS4ERR_LOCK_RANGE"; break;
3944 case NFS4ERR_SYMLINK: p = "NFS4ERR_SYMLINK"; break;
3945 case NFS4ERR_RESTOREFH: p = "NFS4ERR_RESTOREFH"; break;
3946 case NFS4ERR_LEASE_MOVED: p = "NFS4ERR_LEASE_MOVED"; break;
3947 case NFS4ERR_ATTRNOTSUPP: p = "NFS4ERR_ATTRNOTSUPP"; break;
3948 case NFS4ERR_NO_GRACE: p = "NFS4ERR_NO_GRACE"; break;
3949 case NFS4ERR_RECLAIM_BAD: p = "NFS4ERR_RECLAIM_BAD"; break;
3950 case NFS4ERR_RECLAIM_CONFLICT: p = "NFS4ERR_RECLAIM_CONFLICT"; break;
3951 case NFS4ERR_BADXDR: p = "NFS4ERR_BADXDR"; break;
3952 case NFS4ERR_LOCKS_HELD: p = "NFS4ERR_LOCKS_HELD"; break;
3953 case NFS4ERR_OPENMODE: p = "NFS4ERR_OPENMODE"; break;
3954 case NFS4ERR_BADOWNER: p = "NFS4ERR_BADOWNER"; break;
3955 case NFS4ERR_BADCHAR: p = "NFS4ERR_BADCHAR"; break;
3956 case NFS4ERR_BADNAME: p = "NFS4ERR_BADNAME"; break;
3957 case NFS4ERR_BAD_RANGE: p = "NFS4ERR_BAD_RANGE"; break;
3958 case NFS4ERR_LOCK_NOTSUPP: p = "NFS4ERR_LOCK_NOTSUPP"; break;
3959 case NFS4ERR_OP_ILLEGAL: p = "NFS4ERR_OP_ILLEGAL"; break;
3960 case NFS4ERR_DEADLOCK: p = "NFS4ERR_DEADLOCK"; break;
3961 case NFS4ERR_FILE_OPEN: p = "NFS4ERR_FILE_OPEN"; break;
3962 case NFS4ERR_ADMIN_REVOKED: p = "NFS4ERR_ADMIN_REVOKED"; break;
3963 case NFS4ERR_CB_PATH_DOWN: p = "NFS4ERR_CB_PATH_DOWN"; break;
3964 default: p = "(unknown error)"; break;
3965 }
3966
3967 return (p);
3968 }
3969
3970 char *
nfsstat4_to_name(int status)3971 nfsstat4_to_name(int status)
3972 {
3973 return (status_name(status));
3974 }
3975
3976 /*
3977 * Attribute print functions. See attr_info_t.
3978 */
3979
3980 static void
prt_supported_attrs(XDR * xdr)3981 prt_supported_attrs(XDR *xdr)
3982 {
3983 static bitmap4 val;
3984
3985 if (!xdr_bitmap4(xdr, &val))
3986 longjmp(xdr_err, 1);
3987 sprintf(get_line(0, 0), "Supported Attributes:");
3988 detail_attr_bitmap("\t", &val, NULL);
3989 xdr_free(xdr_bitmap4, (char *)&val);
3990 }
3991
3992 static void
prt_type(XDR * xdr)3993 prt_type(XDR *xdr)
3994 {
3995 nfs_ftype4 val;
3996
3997 if (!xdr_nfs_ftype4(xdr, &val))
3998 longjmp(xdr_err, 1);
3999 sprintf(get_line(0, 0), "Type = %s", sum_type_name(val));
4000 }
4001
4002 static void
prt_fh_expire_type(XDR * xdr)4003 prt_fh_expire_type(XDR *xdr)
4004 {
4005 fattr4_fh_expire_type val;
4006 char *buf;
4007 bool_t first = TRUE;
4008
4009 if (!xdr_fattr4_fh_expire_type(xdr, &val))
4010 longjmp(xdr_err, 1);
4011 buf = get_line(0, 0);
4012
4013 sprintf(buf, "Filehandle expire type = ");
4014 if ((val & (FH4_NOEXPIRE_WITH_OPEN | FH4_VOLATILE_ANY |
4015 FH4_VOL_MIGRATION | FH4_VOL_RENAME)) == 0) {
4016 strcat(buf, "Persistent");
4017 return;
4018 }
4019 if (val & FH4_NOEXPIRE_WITH_OPEN) {
4020 strcat(buf, "No Expire With OPEN");
4021 first = FALSE;
4022 }
4023 if (val & FH4_VOLATILE_ANY) {
4024 if (first)
4025 first = FALSE;
4026 else
4027 strcat(buf, ", ");
4028 strcat(buf, "Volatile at any time");
4029 }
4030 if (val & FH4_VOL_MIGRATION) {
4031 if (first)
4032 first = FALSE;
4033 else
4034 strcat(buf, ", ");
4035 strcat(buf, "Volatile at Migration");
4036 }
4037 if (val & FH4_VOL_RENAME) {
4038 if (first)
4039 first = FALSE;
4040 else
4041 strcat(buf, ", ");
4042 strcat(buf, "Volatile at Rename");
4043 }
4044 }
4045
4046 static void
prt_change(XDR * xdr)4047 prt_change(XDR *xdr)
4048 {
4049 changeid4 val;
4050
4051 if (!xdr_changeid4(xdr, &val))
4052 longjmp(xdr_err, 1);
4053 sprintf(get_line(0, 0), "Change ID = 0x%llx", val);
4054 /* XXX print as time_t, too? */
4055 }
4056
4057 static void
prt_size(XDR * xdr)4058 prt_size(XDR *xdr)
4059 {
4060 uint64_t val;
4061
4062 if (!xdr_uint64_t(xdr, &val))
4063 longjmp(xdr_err, 1);
4064 sprintf(get_line(0, 0), "Size = %llu", val);
4065 }
4066
4067 static void
prt_link_support(XDR * xdr)4068 prt_link_support(XDR *xdr)
4069 {
4070 bool_t val;
4071
4072 if (!xdr_bool(xdr, &val))
4073 longjmp(xdr_err, 1);
4074 sprintf(get_line(0, 0), "Link Support = %s",
4075 val ? "TRUE" : "FALSE");
4076 }
4077
4078 static void
prt_symlink_support(XDR * xdr)4079 prt_symlink_support(XDR *xdr)
4080 {
4081 bool_t val;
4082
4083 if (!xdr_bool(xdr, &val))
4084 longjmp(xdr_err, 1);
4085 sprintf(get_line(0, 0), "Symlink Support = %s",
4086 val ? "TRUE" : "FALSE");
4087 }
4088
4089 static void
prt_named_attr(XDR * xdr)4090 prt_named_attr(XDR *xdr)
4091 {
4092 bool_t val;
4093
4094 if (!xdr_bool(xdr, &val))
4095 longjmp(xdr_err, 1);
4096 sprintf(get_line(0, 0), "Has Named Attributes = %s",
4097 val ? "TRUE" : "FALSE");
4098 }
4099
4100 static void
prt_fsid(XDR * xdr)4101 prt_fsid(XDR *xdr)
4102 {
4103 fsid4 val;
4104
4105 if (!xdr_fsid4(xdr, &val))
4106 longjmp(xdr_err, 1);
4107 sprintf(get_line(0, 0), "FS ID: Major = %llx, Minor = %llx",
4108 val.major, val.minor);
4109 }
4110
4111 static void
prt_unique_handles(XDR * xdr)4112 prt_unique_handles(XDR *xdr)
4113 {
4114 bool_t val;
4115
4116 if (!xdr_bool(xdr, &val))
4117 longjmp(xdr_err, 1);
4118 sprintf(get_line(0, 0), "Unique Handles = %s",
4119 val ? "TRUE" : "FALSE");
4120 }
4121
4122 static void
prt_lease_time(XDR * xdr)4123 prt_lease_time(XDR *xdr)
4124 {
4125 uint32_t val;
4126
4127 if (!xdr_uint32_t(xdr, &val))
4128 longjmp(xdr_err, 1);
4129 sprintf(get_line(0, 0), "Lease Time = %u", val);
4130 }
4131
4132 static void
prt_rdattr_error(XDR * xdr)4133 prt_rdattr_error(XDR *xdr)
4134 {
4135 nfsstat4 val;
4136
4137 if (!xdr_nfsstat4(xdr, &val))
4138 longjmp(xdr_err, 1);
4139 sprintf(get_line(0, 0), "Rdattr Error = %u (%s)",
4140 val, status_name(val));
4141 }
4142
4143 static void
prt_acl(XDR * xdr)4144 prt_acl(XDR *xdr)
4145 {
4146 static fattr4_acl val;
4147 char buffy[NFS4_OPAQUE_LIMIT];
4148 int i, len;
4149
4150 if (!xdr_fattr4_acl(xdr, &val))
4151 longjmp(xdr_err, 1);
4152 sprintf(get_line(0, 0), "ACL of %d entries", val.fattr4_acl_len);
4153 for (i = 0; i < val.fattr4_acl_len; i++) {
4154 sprintf(get_line(0, 0), "nfsace4[%d]", i);
4155
4156 sprintf(get_line(0, 0), " type = %x",
4157 val.fattr4_acl_val[i].type);
4158 detail_acetype4(val.fattr4_acl_val[i].type);
4159
4160 sprintf(get_line(0, 0), " flags = %x",
4161 val.fattr4_acl_val[i].flag);
4162 detail_aceflag4(val.fattr4_acl_val[i].flag);
4163
4164 sprintf(get_line(0, 0), " mask = %x",
4165 val.fattr4_acl_val[i].access_mask);
4166 detail_acemask4(val.fattr4_acl_val[i].access_mask);
4167
4168 len = val.fattr4_acl_val[i].who.utf8string_len;
4169 if (len >= NFS4_OPAQUE_LIMIT)
4170 len = NFS4_OPAQUE_LIMIT - 1;
4171 (void) strncpy(buffy, val.fattr4_acl_val[i].who.utf8string_val,
4172 len);
4173 buffy[len] = '\0';
4174 sprintf(get_line(0, 0), " who = %s", buffy);
4175 }
4176 xdr_free(xdr_fattr4_acl, (char *)&val);
4177 }
4178
4179 static void
detail_acetype4(acetype4 type)4180 detail_acetype4(acetype4 type)
4181 {
4182 if (type >= ACETYPE4_NAMES_MAX) {
4183 sprintf(get_line(0, 0), " unknown type");
4184 } else {
4185 sprintf(get_line(0, 0), " %s", acetype4_names[type]);
4186 }
4187 }
4188
4189 static void
detail_uint32_bitmap(uint32_t mask,char * mask_names[],int names_max)4190 detail_uint32_bitmap(uint32_t mask, char *mask_names[], int names_max)
4191 {
4192 char buffy[BUFSIZ], *name;
4193 char *indent = " ";
4194 char *spacer = " ";
4195 int pending = 0;
4196 int bit;
4197 int len, namelen, spacelen;
4198
4199 strcpy(buffy, indent);
4200 len = strlen(buffy);
4201 spacelen = strlen(spacer);
4202
4203 for (bit = 0; bit < names_max; bit++) {
4204 if (mask & (1 << bit)) {
4205 name = mask_names[bit];
4206 namelen = strlen(name);
4207 /* 80 - 6 for "NFS: " = 74 */
4208 if ((len + spacelen + namelen) >= 74) {
4209 sprintf(get_line(0, 0), "%s", buffy);
4210 strcpy(buffy, indent);
4211 len = strlen(buffy);
4212 pending = 0;
4213 }
4214 (void) strlcat(buffy, spacer, sizeof (buffy));
4215 (void) strlcat(buffy, name, sizeof (buffy));
4216 pending = 1;
4217 len += spacelen + namelen;
4218 }
4219 }
4220 if (pending)
4221 sprintf(get_line(0, 0), "%s", buffy);
4222 }
4223
4224 static void
detail_aceflag4(aceflag4 flag)4225 detail_aceflag4(aceflag4 flag)
4226 {
4227 detail_uint32_bitmap(flag, aceflag4_names, ACEFLAG4_NAMES_MAX);
4228 }
4229
4230 static void
detail_acemask4(acemask4 mask)4231 detail_acemask4(acemask4 mask)
4232 {
4233 detail_uint32_bitmap(mask, acemask4_names, ACEMASK4_NAMES_MAX);
4234 }
4235
4236 static void
prt_aclsupport(XDR * xdr)4237 prt_aclsupport(XDR *xdr)
4238 {
4239 fattr4_aclsupport val;
4240
4241 if (!xdr_fattr4_aclsupport(xdr, &val))
4242 longjmp(xdr_err, 1);
4243 if (val & ACL4_SUPPORT_ALLOW_ACL)
4244 sprintf(get_line(0, 0), "ALLOW ACL Supported");
4245 if (val & ACL4_SUPPORT_DENY_ACL)
4246 sprintf(get_line(0, 0), "DENY ACL Supported");
4247 if (val & ACL4_SUPPORT_AUDIT_ACL)
4248 sprintf(get_line(0, 0), "AUDIT ACL Supported");
4249 if (val & ACL4_SUPPORT_ALARM_ACL)
4250 sprintf(get_line(0, 0), "ALARM ACL Supported");
4251 }
4252
4253 static void
prt_archive(XDR * xdr)4254 prt_archive(XDR *xdr)
4255 {
4256 bool_t val;
4257
4258 if (!xdr_bool(xdr, &val))
4259 longjmp(xdr_err, 1);
4260 sprintf(get_line(0, 0), "Archived = %s",
4261 val ? "TRUE" : "FALSE");
4262 }
4263
4264 static void
prt_cansettime(XDR * xdr)4265 prt_cansettime(XDR *xdr)
4266 {
4267 bool_t val;
4268
4269 if (!xdr_bool(xdr, &val))
4270 longjmp(xdr_err, 1);
4271 sprintf(get_line(0, 0), "Server Can Set Time = %s",
4272 val ? "TRUE" : "FALSE");
4273 }
4274
4275 static void
prt_case_insensitive(XDR * xdr)4276 prt_case_insensitive(XDR *xdr)
4277 {
4278 bool_t val;
4279
4280 if (!xdr_bool(xdr, &val))
4281 longjmp(xdr_err, 1);
4282 sprintf(get_line(0, 0), "Case Insensitive Lookups = %s",
4283 val ? "TRUE" : "FALSE");
4284 }
4285
4286 static void
prt_case_preserving(XDR * xdr)4287 prt_case_preserving(XDR *xdr)
4288 {
4289 bool_t val;
4290
4291 if (!xdr_bool(xdr, &val))
4292 longjmp(xdr_err, 1);
4293 sprintf(get_line(0, 0), "Case Preserving = %s",
4294 val ? "TRUE" : "FALSE");
4295 }
4296
4297 static void
prt_chown_restricted(XDR * xdr)4298 prt_chown_restricted(XDR *xdr)
4299 {
4300 bool_t val;
4301
4302 if (!xdr_bool(xdr, &val))
4303 longjmp(xdr_err, 1);
4304 sprintf(get_line(0, 0), "Chown Is Restricted = %s",
4305 val ? "TRUE" : "FALSE");
4306 }
4307
4308 static void
prt_filehandle(XDR * xdr)4309 prt_filehandle(XDR *xdr)
4310 {
4311 static nfs_fh4 val;
4312
4313 if (!xdr_nfs_fh4(xdr, &val))
4314 longjmp(xdr_err, 1);
4315 detail_fh4(&val);
4316 xdr_free(xdr_nfs_fh4, (char *)&val);
4317 }
4318
4319 static void
prt_fileid(XDR * xdr)4320 prt_fileid(XDR *xdr)
4321 {
4322 uint64_t val;
4323
4324 if (!xdr_uint64_t(xdr, &val))
4325 longjmp(xdr_err, 1);
4326 sprintf(get_line(0, 0), "File ID = %llu", val);
4327 }
4328
4329 static void
prt_mounted_on_fileid(XDR * xdr)4330 prt_mounted_on_fileid(XDR *xdr)
4331 {
4332 uint64_t val;
4333
4334 if (!xdr_uint64_t(xdr, &val))
4335 longjmp(xdr_err, 1);
4336 sprintf(get_line(0, 0), "Mounted On File ID = %llu", val);
4337 }
4338
4339 static void
prt_files_avail(XDR * xdr)4340 prt_files_avail(XDR *xdr)
4341 {
4342 uint64_t val;
4343
4344 if (!xdr_uint64_t(xdr, &val))
4345 longjmp(xdr_err, 1);
4346 sprintf(get_line(0, 0), "Files Available = %llu", val);
4347 }
4348
4349 static void
prt_files_free(XDR * xdr)4350 prt_files_free(XDR *xdr)
4351 {
4352 uint64_t val;
4353
4354 if (!xdr_uint64_t(xdr, &val))
4355 longjmp(xdr_err, 1);
4356 sprintf(get_line(0, 0), "Files Free = %llu", val);
4357 }
4358
4359 static void
prt_files_total(XDR * xdr)4360 prt_files_total(XDR *xdr)
4361 {
4362 uint64_t val;
4363
4364 if (!xdr_uint64_t(xdr, &val))
4365 longjmp(xdr_err, 1);
4366 sprintf(get_line(0, 0), "Files Total = %llu", val);
4367 }
4368
4369 static void
prt_fs_location(fs_location4 * fsl)4370 prt_fs_location(fs_location4 *fsl)
4371 {
4372 int i;
4373
4374 for (i = 0; i < fsl->server.server_len; i++)
4375 sprintf(get_line(0, 0), "server: %s",
4376 utf8localize(&fsl->server.server_val[i]));
4377
4378 detail_pathname4(&fsl->rootpath, "rootpath: ");
4379 }
4380
4381 static void
prt_fs_locations(XDR * xdr)4382 prt_fs_locations(XDR *xdr)
4383 {
4384 static fs_locations4 val;
4385 int i;
4386
4387 if (!xdr_fs_locations4(xdr, &val))
4388 longjmp(xdr_err, 1);
4389 sprintf(get_line(0, 0), "[fs_locations]");
4390 detail_pathname4(&val.fs_root, "fs_root: ");
4391 for (i = 0; i < val.locations.locations_len; i++)
4392 prt_fs_location(&val.locations.locations_val[i]);
4393 xdr_free(xdr_fs_locations4, (char *)&val);
4394 }
4395
4396 static void
prt_hidden(XDR * xdr)4397 prt_hidden(XDR *xdr)
4398 {
4399 bool_t val;
4400
4401 if (!xdr_bool(xdr, &val))
4402 longjmp(xdr_err, 1);
4403 sprintf(get_line(0, 0), "Hidden = %s",
4404 val ? "TRUE" : "FALSE");
4405 }
4406
4407 static void
prt_homogeneous(XDR * xdr)4408 prt_homogeneous(XDR *xdr)
4409 {
4410 bool_t val;
4411
4412 if (!xdr_bool(xdr, &val))
4413 longjmp(xdr_err, 1);
4414 sprintf(get_line(0, 0), "FS Is Homogeneous = %s",
4415 val ? "TRUE" : "FALSE");
4416 }
4417
4418 static void
prt_maxfilesize(XDR * xdr)4419 prt_maxfilesize(XDR *xdr)
4420 {
4421 uint64_t val;
4422
4423 if (!xdr_uint64_t(xdr, &val))
4424 longjmp(xdr_err, 1);
4425 sprintf(get_line(0, 0), "Maximum File Size = %llu", val);
4426 }
4427
4428 static void
prt_maxlink(XDR * xdr)4429 prt_maxlink(XDR *xdr)
4430 {
4431 uint32_t val;
4432
4433 if (!xdr_uint32_t(xdr, &val))
4434 longjmp(xdr_err, 1);
4435 sprintf(get_line(0, 0), "Maximum Number of Links = %u", val);
4436 }
4437
4438 static void
prt_maxname(XDR * xdr)4439 prt_maxname(XDR *xdr)
4440 {
4441 uint32_t val;
4442
4443 if (!xdr_uint32_t(xdr, &val))
4444 longjmp(xdr_err, 1);
4445 sprintf(get_line(0, 0), "Maximum File Name Length = %u", val);
4446 }
4447
4448 static void
prt_maxread(XDR * xdr)4449 prt_maxread(XDR *xdr)
4450 {
4451 uint64_t val;
4452
4453 if (!xdr_uint64_t(xdr, &val))
4454 longjmp(xdr_err, 1);
4455 sprintf(get_line(0, 0), "Maximum Read Size = %llu", val);
4456 }
4457
4458 static void
prt_maxwrite(XDR * xdr)4459 prt_maxwrite(XDR *xdr)
4460 {
4461 uint64_t val;
4462
4463 if (!xdr_uint64_t(xdr, &val))
4464 longjmp(xdr_err, 1);
4465
4466 sprintf(get_line(0, 0), "Maximum Write Size = %llu", val);
4467 }
4468
4469 static void
prt_mimetype(XDR * xdr)4470 prt_mimetype(XDR *xdr)
4471 {
4472 static utf8string val;
4473
4474 if (!xdr_utf8string(xdr, &val))
4475 longjmp(xdr_err, 1);
4476 sprintf(get_line(0, 0), "MIME Type = %s", utf8localize(&val));
4477 xdr_free(xdr_utf8string, (char *)&val);
4478 }
4479
4480 static void
prt_mode(XDR * xdr)4481 prt_mode(XDR *xdr)
4482 {
4483 mode4 val;
4484
4485 if (!xdr_mode4(xdr, &val))
4486 longjmp(xdr_err, 1);
4487 sprintf(get_line(0, 0), "Mode = 0%03o", val);
4488 }
4489
4490 static void
prt_no_trunc(XDR * xdr)4491 prt_no_trunc(XDR *xdr)
4492 {
4493 bool_t val;
4494
4495 if (!xdr_bool(xdr, &val))
4496 longjmp(xdr_err, 1);
4497 sprintf(get_line(0, 0), "Long Names Are Error (no_trunc) = %s",
4498 val ? "TRUE" : "FALSE");
4499 }
4500
4501 static void
prt_numlinks(XDR * xdr)4502 prt_numlinks(XDR *xdr)
4503 {
4504 uint32_t val;
4505
4506 if (!xdr_uint32_t(xdr, &val))
4507 longjmp(xdr_err, 1);
4508 sprintf(get_line(0, 0), "Number of Links = %u", val);
4509 }
4510
4511 static void
prt_owner(XDR * xdr)4512 prt_owner(XDR *xdr)
4513 {
4514 static utf8string val;
4515
4516 if (!xdr_utf8string(xdr, &val))
4517 longjmp(xdr_err, 1);
4518 sprintf(get_line(0, 0), "Owner = %s", utf8localize(&val));
4519 xdr_free(xdr_utf8string, (char *)&val);
4520 }
4521
4522 static void
prt_owner_group(XDR * xdr)4523 prt_owner_group(XDR *xdr)
4524 {
4525 static utf8string val;
4526
4527 if (!xdr_utf8string(xdr, &val))
4528 longjmp(xdr_err, 1);
4529 sprintf(get_line(0, 0), "Group = %s", utf8localize(&val));
4530 xdr_free(xdr_utf8string, (char *)&val);
4531 }
4532
4533 static void
prt_quota_avail_hard(XDR * xdr)4534 prt_quota_avail_hard(XDR *xdr)
4535 {
4536 uint64_t val;
4537
4538 if (!xdr_uint64_t(xdr, &val))
4539 longjmp(xdr_err, 1);
4540 sprintf(get_line(0, 0), "Quota Hard Limit = %llu", val);
4541 }
4542
4543 static void
prt_quota_avail_soft(XDR * xdr)4544 prt_quota_avail_soft(XDR *xdr)
4545 {
4546 uint64_t val;
4547
4548 if (!xdr_uint64_t(xdr, &val))
4549 longjmp(xdr_err, 1);
4550 sprintf(get_line(0, 0), "Quota Soft Limit = %llu", val);
4551 }
4552
4553 static void
prt_quota_used(XDR * xdr)4554 prt_quota_used(XDR *xdr)
4555 {
4556 uint64_t val;
4557
4558 if (!xdr_uint64_t(xdr, &val))
4559 longjmp(xdr_err, 1);
4560 sprintf(get_line(0, 0), "Quota Used = %llu", val);
4561 }
4562
4563 static void
prt_rawdev(XDR * xdr)4564 prt_rawdev(XDR *xdr)
4565 {
4566 specdata4 val;
4567
4568 if (!xdr_specdata4(xdr, &val))
4569 longjmp(xdr_err, 1);
4570 sprintf(get_line(0, 0), "Raw Device ID = %u, %u",
4571 val.specdata1, val.specdata2);
4572 }
4573
4574 static void
prt_space_avail(XDR * xdr)4575 prt_space_avail(XDR *xdr)
4576 {
4577 uint64_t val;
4578
4579 if (!xdr_uint64_t(xdr, &val))
4580 longjmp(xdr_err, 1);
4581 sprintf(get_line(0, 0), "Space Available = %llu", val);
4582 }
4583
4584 static void
prt_space_free(XDR * xdr)4585 prt_space_free(XDR *xdr)
4586 {
4587 uint64_t val;
4588
4589 if (!xdr_uint64_t(xdr, &val))
4590 longjmp(xdr_err, 1);
4591 sprintf(get_line(0, 0), "Space Free = %llu", val);
4592 }
4593
4594 static void
prt_space_total(XDR * xdr)4595 prt_space_total(XDR *xdr)
4596 {
4597 uint64_t val;
4598
4599 if (!xdr_uint64_t(xdr, &val))
4600 longjmp(xdr_err, 1);
4601 sprintf(get_line(0, 0), "Total Disk Space = %llu", val);
4602 }
4603
4604 static void
prt_space_used(XDR * xdr)4605 prt_space_used(XDR *xdr)
4606 {
4607 uint64_t val;
4608
4609 if (!xdr_uint64_t(xdr, &val))
4610 longjmp(xdr_err, 1);
4611 sprintf(get_line(0, 0), "Space Used (this object) = %llu", val);
4612 }
4613
4614 static void
prt_system(XDR * xdr)4615 prt_system(XDR *xdr)
4616 {
4617 bool_t val;
4618
4619 if (!xdr_bool(xdr, &val))
4620 longjmp(xdr_err, 1);
4621 sprintf(get_line(0, 0), "System File = %s",
4622 val ? "TRUE" : "FALSE");
4623 }
4624
4625 static void
prt_time_access(XDR * xdr)4626 prt_time_access(XDR *xdr)
4627 {
4628 nfstime4 val;
4629
4630 if (!xdr_nfstime4(xdr, &val))
4631 longjmp(xdr_err, 1);
4632 sprintf(get_line(0, 0), "Last Access Time = %s",
4633 format_time(val.seconds, val.nseconds));
4634 }
4635
4636 static void
prt_time_access_set(XDR * xdr)4637 prt_time_access_set(XDR *xdr)
4638 {
4639 settime4 val;
4640
4641 if (!xdr_settime4(xdr, &val))
4642 longjmp(xdr_err, 1);
4643 if (val.set_it == SET_TO_CLIENT_TIME4) {
4644 sprintf(get_line(0, 0), "Access Time = %s (set to client time)",
4645 format_time(val.settime4_u.time.seconds,
4646 val.settime4_u.time.nseconds));
4647 } else if (val.set_it == SET_TO_SERVER_TIME4) {
4648 sprintf(get_line(0, 0), "Access Time (set to server time)");
4649 } else
4650 longjmp(xdr_err, 1);
4651 }
4652
4653 static void
prt_time_backup(XDR * xdr)4654 prt_time_backup(XDR *xdr)
4655 {
4656 nfstime4 val;
4657
4658 if (!xdr_nfstime4(xdr, &val))
4659 longjmp(xdr_err, 1);
4660 sprintf(get_line(0, 0), "Last Backup Time = %s",
4661 format_time(val.seconds, val.nseconds));
4662 }
4663
4664 static void
prt_time_create(XDR * xdr)4665 prt_time_create(XDR *xdr)
4666 {
4667 nfstime4 val;
4668
4669 if (!xdr_nfstime4(xdr, &val))
4670 longjmp(xdr_err, 1);
4671 sprintf(get_line(0, 0), "Creation Time = %s",
4672 format_time(val.seconds, val.nseconds));
4673 }
4674
4675 static void
prt_time_delta(XDR * xdr)4676 prt_time_delta(XDR *xdr)
4677 {
4678 nfstime4 val;
4679
4680 if (!xdr_nfstime4(xdr, &val))
4681 longjmp(xdr_err, 1);
4682 sprintf(get_line(0, 0), "Server Time Granularity = %lld.%09d sec",
4683 val.seconds, val.nseconds);
4684 }
4685
4686 static void
prt_time_metadata(XDR * xdr)4687 prt_time_metadata(XDR *xdr)
4688 {
4689 nfstime4 val;
4690
4691 if (!xdr_nfstime4(xdr, &val))
4692 longjmp(xdr_err, 1);
4693 sprintf(get_line(0, 0), "Last Metadata Change Time = %s",
4694 format_time(val.seconds, val.nseconds));
4695 }
4696
4697 static void
prt_time_modify(XDR * xdr)4698 prt_time_modify(XDR *xdr)
4699 {
4700 nfstime4 val;
4701
4702 if (!xdr_nfstime4(xdr, &val))
4703 longjmp(xdr_err, 1);
4704 sprintf(get_line(0, 0), "Last Modification Time = %s",
4705 format_time(val.seconds, val.nseconds));
4706 }
4707
4708 static void
prt_time_modify_set(XDR * xdr)4709 prt_time_modify_set(XDR *xdr)
4710 {
4711 settime4 val;
4712
4713 if (!xdr_settime4(xdr, &val))
4714 longjmp(xdr_err, 1);
4715 if (val.set_it == SET_TO_CLIENT_TIME4) {
4716 sprintf(get_line(0, 0),
4717 "Modification Time = %s (set to client time)",
4718 format_time(val.settime4_u.time.seconds,
4719 val.settime4_u.time.nseconds));
4720 } else if (val.set_it == SET_TO_SERVER_TIME4) {
4721 sprintf(get_line(0, 0),
4722 "Modification Time (set to server time)");
4723 } else
4724 longjmp(xdr_err, 1);
4725 }
4726
4727 /*
4728 * Display the UTF8 string that is next in the XDR stream.
4729 */
4730
4731 static void
showxdr_utf8string(char * fmt)4732 showxdr_utf8string(char *fmt)
4733 {
4734 static utf8string string;
4735
4736 if (!xdr_utf8string(&xdrm, &string))
4737 longjmp(xdr_err, 1);
4738 sprintf(get_line(0, 0), fmt, utf8localize(&string));
4739 xdr_free(xdr_utf8string, (char *)&string);
4740 }
4741
4742 /*
4743 * utf8string is defined in nfs4_prot.x as an opaque array, which means
4744 * when it is decoded into a string, the string might not have a trailing
4745 * null. Also, the string will still be encoded in UTF-8, rather than
4746 * whatever character encoding is associated with the current locale. This
4747 * routine converts a utf8string into a (null-terminated) C string. One day
4748 * it will convert into the current character encoding, too. To avoid
4749 * dealing with storage management issues, it allocates storage for each
4750 * new string, then this storage is "freed" when the packet has been
4751 * processed.
4752 */
4753
4754 #define MAX_UTF8_STRINGS 512
4755
4756 static char *utf_buf[MAX_UTF8_STRINGS];
4757 static size_t utf_buflen[MAX_UTF8_STRINGS];
4758 static uint_t cur_utf_buf = 0;
4759
4760 static char *
utf8localize(utf8string * utf8str)4761 utf8localize(utf8string *utf8str)
4762 {
4763 size_t newsize, oldsize, len;
4764 char *result, *cp;
4765
4766 len = utf8str->utf8string_len;
4767 if (len == 0)
4768 return ("");
4769 if (cur_utf_buf >= MAX_UTF8_STRINGS)
4770 return ("[Too Many UTF-8 Strings]");
4771
4772 newsize = oldsize = utf_buflen[cur_utf_buf];
4773
4774
4775 if (oldsize < len + 1) {
4776 /* truncate opaques at NFS4_OPAQUE_LIMIT */
4777 if (len > NFS4_OPAQUE_LIMIT)
4778 len = NFS4_OPAQUE_LIMIT;
4779 newsize = len + 1;
4780 }
4781 if (newsize != oldsize) {
4782 utf_buf[cur_utf_buf] = realloc(utf_buf[cur_utf_buf],
4783 newsize);
4784 if (utf_buf[cur_utf_buf] == NULL) {
4785 pr_err("out of memory\n");
4786 utf_buflen[cur_utf_buf] = 0;
4787 return ("");
4788 }
4789 utf_buflen[cur_utf_buf] = newsize;
4790 }
4791
4792 result = utf_buf[cur_utf_buf];
4793 strncpy(result, utf8str->utf8string_val, len);
4794 result[len] = '\0';
4795 for (cp = result; cp < result + len; cp++) {
4796 if (!isprint(*cp)) {
4797 *cp = '.';
4798 }
4799 }
4800
4801 cur_utf_buf++;
4802
4803 return (result);
4804 }
4805
4806 static void
utf8free()4807 utf8free()
4808 {
4809 cur_utf_buf = 0;
4810 }
4811
4812
4813 /*
4814 * adler16(): adler32 hash code shamelessly copied and mutiliated from
4815 * usr/src/uts/common/io/ppp/spppcomp/zlib.[ch]
4816 *
4817 * The alg was originally created to provide a running
4818 * checksum, but we don't need that -- we just want to
4819 * chksum data described by buf,len; therefore, the first
4820 * parameter was removed (held the running checksum),
4821 * and s1/s2 are always set to their required initial
4822 * values (1 and 0). I also ripped out code which only
4823 * applied to large data sets (bufs larger than 5k). All
4824 * I wanted was their core checksum alg (which is supposed
4825 * to do really well). The v2/v3 hash alg didn't work well
4826 * at all for v4 stuff -- it produced too many collisions.
4827 *
4828 * The copyright info from uts/common/io/ppp/spppcomp/zlib.[ch]
4829 * is included below.
4830 */
4831
4832 /* -----zlib.c copyright info below */
4833 /*
4834 * Copyright 2000 Sun Microsystems, Inc.
4835 * All rights reserved.
4836 *
4837 * Updated from zlib-1.0.4 to zlib-1.1.3 by James Carlson.
4838 *
4839 * This file is derived from various .h and .c files from the zlib-1.0.4
4840 * distribution by Jean-loup Gailly and Mark Adler, with some additions
4841 * by Paul Mackerras to aid in implementing Deflate compression and
4842 * decompression for PPP packets. See zlib.h for conditions of
4843 * distribution and use.
4844 *
4845 * Changes that have been made include:
4846 * - added Z_PACKET_FLUSH (see zlib.h for details)
4847 * - added inflateIncomp and deflateOutputPending
4848 * - allow strm->next_out to be NULL, meaning discard the output
4849 *
4850 * $Id: zlib.c,v 1.11 1998/09/13 23:37:12 paulus Exp $
4851 */
4852 /* +++ adler32.c */
4853 /*
4854 * adler32.c -- compute the Adler-32 checksum of a data stream
4855 * Copyright (C) 1995-1998 Mark Adler
4856 * For conditions of distribution and use, see copyright notice in zlib.h
4857 */
4858 /* From: adler32.c,v 1.10 1996/05/22 11:52:18 me Exp $ */
4859 /* -----zlib.c copyright info above */
4860
4861 /* -----zlib.h copyright info below */
4862 /*
4863 * Copyright 2000 Sun Microsystems, Inc.
4864 * All rights reserved.
4865 *
4866 * Permission to use, copy, modify, and distribute this software and
4867 * its documentation is hereby granted, provided that the above
4868 * copyright notice appears in all copies.
4869 *
4870 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
4871 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
4872 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
4873 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE
4874 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
4875 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
4876 *
4877 * This file has been altered from its original by Sun Microsystems to
4878 * fit local coding style.
4879 */
4880 /* -----zlib.h copyright info above */
4881
4882 #define DO1(buf, i) {s1 += buf[i]; s2 += s1; }
4883 #define DO2(buf, i) DO1(buf, i); DO1(buf, i+1);
4884 #define DO4(buf, i) DO2(buf, i); DO2(buf, i+2);
4885 #define DO8(buf, i) DO4(buf, i); DO4(buf, i+4);
4886 #define DO16(buf) DO8(buf, 0); DO8(buf, 8);
4887
4888 static uint32_t
adler16(void * p,int len)4889 adler16(void *p, int len)
4890 {
4891 uint32_t s1 = 1;
4892 uint32_t s2 = 0;
4893 uchar_t *buf = p;
4894
4895 while (len >= 16) {
4896 DO16(buf);
4897 buf += 16;
4898 len -= 16;
4899 }
4900
4901 while (len > 0) {
4902 s1 += *buf++;
4903 s2 += s1;
4904 len--;
4905 }
4906
4907 return ((uint32_t)(s2 ^ s1) & 0xFFFFU);
4908 }
4909