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