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