2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #define NETDISSECT_REWORKED
29 #include <tcpdump-stdinc.h>
34 #include "interface.h"
35 #include "addrtoname.h"
48 static const char tstr[] = " [|nfs]";
50 static void nfs_printfh(netdissect_options *, const uint32_t *, const u_int);
51 static int xid_map_enter(netdissect_options *, const struct sunrpc_msg *, const u_char *);
52 static int xid_map_find(const struct sunrpc_msg *, const u_char *,
53 uint32_t *, uint32_t *);
54 static void interp_reply(netdissect_options *, const struct sunrpc_msg *, uint32_t, uint32_t, int);
55 static const uint32_t *parse_post_op_attr(netdissect_options *, const uint32_t *, int);
58 * Mapping of old NFS Version 2 RPC numbers to generic numbers.
60 uint32_t nfsv3_procid[NFS_NPROCS] = {
89 static const struct tok nfsproc_str[] = {
90 { NFSPROC_NOOP, "nop" },
91 { NFSPROC_NULL, "null" },
92 { NFSPROC_GETATTR, "getattr" },
93 { NFSPROC_SETATTR, "setattr" },
94 { NFSPROC_LOOKUP, "lookup" },
95 { NFSPROC_ACCESS, "access" },
96 { NFSPROC_READLINK, "readlink" },
97 { NFSPROC_READ, "read" },
98 { NFSPROC_WRITE, "write" },
99 { NFSPROC_CREATE, "create" },
100 { NFSPROC_MKDIR, "mkdir" },
101 { NFSPROC_SYMLINK, "symlink" },
102 { NFSPROC_MKNOD, "mknod" },
103 { NFSPROC_REMOVE, "remove" },
104 { NFSPROC_RMDIR, "rmdir" },
105 { NFSPROC_RENAME, "rename" },
106 { NFSPROC_LINK, "link" },
107 { NFSPROC_READDIR, "readdir" },
108 { NFSPROC_READDIRPLUS, "readdirplus" },
109 { NFSPROC_FSSTAT, "fsstat" },
110 { NFSPROC_FSINFO, "fsinfo" },
111 { NFSPROC_PATHCONF, "pathconf" },
112 { NFSPROC_COMMIT, "commit" },
117 * NFS V2 and V3 status values.
119 * Some of these come from the RFCs for NFS V2 and V3, with the message
120 * strings taken from the FreeBSD C library "errlst.c".
122 * Others are errors that are not in the RFC but that I suspect some
123 * NFS servers could return; the values are FreeBSD errno values, as
124 * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS
125 * was primarily BSD-derived.
127 static const struct tok status2str[] = {
128 { 1, "Operation not permitted" }, /* EPERM */
129 { 2, "No such file or directory" }, /* ENOENT */
130 { 5, "Input/output error" }, /* EIO */
131 { 6, "Device not configured" }, /* ENXIO */
132 { 11, "Resource deadlock avoided" }, /* EDEADLK */
133 { 12, "Cannot allocate memory" }, /* ENOMEM */
134 { 13, "Permission denied" }, /* EACCES */
135 { 17, "File exists" }, /* EEXIST */
136 { 18, "Cross-device link" }, /* EXDEV */
137 { 19, "Operation not supported by device" }, /* ENODEV */
138 { 20, "Not a directory" }, /* ENOTDIR */
139 { 21, "Is a directory" }, /* EISDIR */
140 { 22, "Invalid argument" }, /* EINVAL */
141 { 26, "Text file busy" }, /* ETXTBSY */
142 { 27, "File too large" }, /* EFBIG */
143 { 28, "No space left on device" }, /* ENOSPC */
144 { 30, "Read-only file system" }, /* EROFS */
145 { 31, "Too many links" }, /* EMLINK */
146 { 45, "Operation not supported" }, /* EOPNOTSUPP */
147 { 62, "Too many levels of symbolic links" }, /* ELOOP */
148 { 63, "File name too long" }, /* ENAMETOOLONG */
149 { 66, "Directory not empty" }, /* ENOTEMPTY */
150 { 69, "Disc quota exceeded" }, /* EDQUOT */
151 { 70, "Stale NFS file handle" }, /* ESTALE */
152 { 71, "Too many levels of remote in path" }, /* EREMOTE */
153 { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */
154 { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */
155 { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */
156 { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */
157 { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */
158 { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */
159 { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */
160 { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */
161 { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */
165 static const struct tok nfsv3_writemodes[] = {
172 static const struct tok type2str[] = {
183 static const struct tok sunrpc_auth_str[] = {
184 { SUNRPC_AUTH_OK, "OK" },
185 { SUNRPC_AUTH_BADCRED, "Bogus Credentials (seal broken)" },
186 { SUNRPC_AUTH_REJECTEDCRED, "Rejected Credentials (client should begin new session)" },
187 { SUNRPC_AUTH_BADVERF, "Bogus Verifier (seal broken)" },
188 { SUNRPC_AUTH_REJECTEDVERF, "Verifier expired or was replayed" },
189 { SUNRPC_AUTH_TOOWEAK, "Credentials are too weak" },
190 { SUNRPC_AUTH_INVALIDRESP, "Bogus response verifier" },
191 { SUNRPC_AUTH_FAILED, "Unknown failure" },
195 static const struct tok sunrpc_str[] = {
196 { SUNRPC_PROG_UNAVAIL, "PROG_UNAVAIL" },
197 { SUNRPC_PROG_MISMATCH, "PROG_MISMATCH" },
198 { SUNRPC_PROC_UNAVAIL, "PROC_UNAVAIL" },
199 { SUNRPC_GARBAGE_ARGS, "GARBAGE_ARGS" },
200 { SUNRPC_SYSTEM_ERR, "SYSTEM_ERR" },
205 print_nfsaddr(netdissect_options *ndo,
206 const u_char *bp, const char *s, const char *d)
211 char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN];
213 #ifndef INET_ADDRSTRLEN
214 #define INET_ADDRSTRLEN 16
216 char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN];
219 srcaddr[0] = dstaddr[0] = '\0';
220 switch (IP_V((struct ip *)bp)) {
222 ip = (struct ip *)bp;
223 strlcpy(srcaddr, ipaddr_string(ndo, &ip->ip_src), sizeof(srcaddr));
224 strlcpy(dstaddr, ipaddr_string(ndo, &ip->ip_dst), sizeof(dstaddr));
228 ip6 = (struct ip6_hdr *)bp;
229 strlcpy(srcaddr, ip6addr_string(ndo, &ip6->ip6_src),
231 strlcpy(dstaddr, ip6addr_string(ndo, &ip6->ip6_dst),
236 strlcpy(srcaddr, "?", sizeof(srcaddr));
237 strlcpy(dstaddr, "?", sizeof(dstaddr));
241 ND_PRINT((ndo, "%s.%s > %s.%s: ", srcaddr, s, dstaddr, d));
244 static const uint32_t *
245 parse_sattr3(netdissect_options *ndo,
246 const uint32_t *dp, struct nfsv3_sattr *sa3)
249 sa3->sa_modeset = EXTRACT_32BITS(dp);
251 if (sa3->sa_modeset) {
253 sa3->sa_mode = EXTRACT_32BITS(dp);
258 sa3->sa_uidset = EXTRACT_32BITS(dp);
260 if (sa3->sa_uidset) {
262 sa3->sa_uid = EXTRACT_32BITS(dp);
267 sa3->sa_gidset = EXTRACT_32BITS(dp);
269 if (sa3->sa_gidset) {
271 sa3->sa_gid = EXTRACT_32BITS(dp);
276 sa3->sa_sizeset = EXTRACT_32BITS(dp);
278 if (sa3->sa_sizeset) {
280 sa3->sa_size = EXTRACT_32BITS(dp);
285 sa3->sa_atimetype = EXTRACT_32BITS(dp);
287 if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) {
289 sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp);
291 sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp);
296 sa3->sa_mtimetype = EXTRACT_32BITS(dp);
298 if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) {
300 sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp);
302 sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp);
311 static int nfserr; /* true if we error rather than trunc */
314 print_sattr3(netdissect_options *ndo,
315 const struct nfsv3_sattr *sa3, int verbose)
318 ND_PRINT((ndo, " mode %o", sa3->sa_mode));
320 ND_PRINT((ndo, " uid %u", sa3->sa_uid));
322 ND_PRINT((ndo, " gid %u", sa3->sa_gid));
324 if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT)
325 ND_PRINT((ndo, " atime %u.%06u", sa3->sa_atime.nfsv3_sec,
326 sa3->sa_atime.nfsv3_nsec));
327 if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT)
328 ND_PRINT((ndo, " mtime %u.%06u", sa3->sa_mtime.nfsv3_sec,
329 sa3->sa_mtime.nfsv3_nsec));
334 nfsreply_print(netdissect_options *ndo,
335 register const u_char *bp, u_int length,
336 register const u_char *bp2)
338 register const struct sunrpc_msg *rp;
339 char srcid[20], dstid[20]; /*fits 32bit*/
341 nfserr = 0; /* assume no error */
342 rp = (const struct sunrpc_msg *)bp;
344 ND_TCHECK(rp->rm_xid);
345 if (!ndo->ndo_nflag) {
346 strlcpy(srcid, "nfs", sizeof(srcid));
347 snprintf(dstid, sizeof(dstid), "%u",
348 EXTRACT_32BITS(&rp->rm_xid));
350 snprintf(srcid, sizeof(srcid), "%u", NFS_PORT);
351 snprintf(dstid, sizeof(dstid), "%u",
352 EXTRACT_32BITS(&rp->rm_xid));
354 print_nfsaddr(ndo, bp2, srcid, dstid);
356 nfsreply_print_noaddr(ndo, bp, length, bp2);
361 ND_PRINT((ndo, "%s", tstr));
365 nfsreply_print_noaddr(netdissect_options *ndo,
366 register const u_char *bp, u_int length,
367 register const u_char *bp2)
369 register const struct sunrpc_msg *rp;
370 uint32_t proc, vers, reply_stat;
371 enum sunrpc_reject_stat rstat;
374 enum sunrpc_auth_stat rwhy;
376 nfserr = 0; /* assume no error */
377 rp = (const struct sunrpc_msg *)bp;
379 ND_TCHECK(rp->rm_reply.rp_stat);
380 reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat);
381 switch (reply_stat) {
383 case SUNRPC_MSG_ACCEPTED:
384 ND_PRINT((ndo, "reply ok %u", length));
385 if (xid_map_find(rp, bp2, &proc, &vers) >= 0)
386 interp_reply(ndo, rp, proc, vers, length);
389 case SUNRPC_MSG_DENIED:
390 ND_PRINT((ndo, "reply ERR %u: ", length));
391 ND_TCHECK(rp->rm_reply.rp_reject.rj_stat);
392 rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat);
395 case SUNRPC_RPC_MISMATCH:
396 ND_TCHECK(rp->rm_reply.rp_reject.rj_vers.high);
397 rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low);
398 rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high);
399 ND_PRINT((ndo, "RPC Version mismatch (%u-%u)", rlow, rhigh));
402 case SUNRPC_AUTH_ERROR:
403 ND_TCHECK(rp->rm_reply.rp_reject.rj_why);
404 rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why);
405 ND_PRINT((ndo, "Auth %s", tok2str(sunrpc_auth_str, "Invalid failure code %u", rwhy)));
409 ND_PRINT((ndo, "Unknown reason for rejecting rpc message %u", (unsigned int)rstat));
415 ND_PRINT((ndo, "reply Unknown rpc response code=%u %u", reply_stat, length));
422 ND_PRINT((ndo, "%s", tstr));
426 * Return a pointer to the first file handle in the packet.
427 * If the packet was truncated, return 0.
429 static const uint32_t *
430 parsereq(netdissect_options *ndo,
431 register const struct sunrpc_msg *rp, register u_int length)
433 register const uint32_t *dp;
437 * find the start of the req data (if we captured it)
439 dp = (uint32_t *)&rp->rm_call.cb_cred;
441 len = EXTRACT_32BITS(&dp[1]);
443 dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
445 len = EXTRACT_32BITS(&dp[1]);
447 dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
448 ND_TCHECK2(dp[0], 0);
457 * Print out an NFS file handle and return a pointer to following word.
458 * If packet was truncated, return 0.
460 static const uint32_t *
461 parsefh(netdissect_options *ndo,
462 register const uint32_t *dp, int v3)
468 len = EXTRACT_32BITS(dp) / 4;
473 if (ND_TTEST2(*dp, len * sizeof(*dp))) {
474 nfs_printfh(ndo, dp, len);
482 * Print out a file name and return pointer to 32-bit word past it.
483 * If packet was truncated, return 0.
485 static const uint32_t *
486 parsefn(netdissect_options *ndo,
487 register const uint32_t *dp)
489 register uint32_t len;
490 register const u_char *cp;
492 /* Bail if we don't have the string length */
495 /* Fetch string length; convert to host order */
499 ND_TCHECK2(*dp, ((len + 3) & ~3));
502 /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
503 dp += ((len + 3) & ~3) / sizeof(*dp);
504 ND_PRINT((ndo, "\""));
505 if (fn_printn(ndo, cp, len, ndo->ndo_snapend)) {
506 ND_PRINT((ndo, "\""));
509 ND_PRINT((ndo, "\""));
517 * Print out file handle and file name.
518 * Return pointer to 32-bit word past file name.
519 * If packet was truncated (or there was some other error), return 0.
521 static const uint32_t *
522 parsefhn(netdissect_options *ndo,
523 register const uint32_t *dp, int v3)
525 dp = parsefh(ndo, dp, v3);
528 ND_PRINT((ndo, " "));
529 return (parsefn(ndo, dp));
533 nfsreq_print_noaddr(netdissect_options *ndo,
534 register const u_char *bp, u_int length,
535 register const u_char *bp2)
537 register const struct sunrpc_msg *rp;
538 register const uint32_t *dp;
542 uint32_t access_flags;
543 struct nfsv3_sattr sa3;
545 ND_PRINT((ndo, "%d", length));
546 nfserr = 0; /* assume no error */
547 rp = (const struct sunrpc_msg *)bp;
549 if (!xid_map_enter(ndo, rp, bp2)) /* record proc number for later on */
552 v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3);
553 proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
555 if (!v3 && proc < NFS_NPROCS)
556 proc = nfsv3_procid[proc];
558 ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
561 case NFSPROC_GETATTR:
562 case NFSPROC_SETATTR:
563 case NFSPROC_READLINK:
566 case NFSPROC_PATHCONF:
567 if ((dp = parsereq(ndo, rp, length)) != NULL &&
568 parsefh(ndo, dp, v3) != NULL)
577 if ((dp = parsereq(ndo, rp, length)) != NULL &&
578 parsefhn(ndo, dp, v3) != NULL)
583 if ((dp = parsereq(ndo, rp, length)) != NULL &&
584 (dp = parsefh(ndo, dp, v3)) != NULL) {
586 access_flags = EXTRACT_32BITS(&dp[0]);
587 if (access_flags & ~NFSV3ACCESS_FULL) {
588 /* NFSV3ACCESS definitions aren't up to date */
589 ND_PRINT((ndo, " %04x", access_flags));
590 } else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) {
591 ND_PRINT((ndo, " NFS_ACCESS_FULL"));
593 char separator = ' ';
594 if (access_flags & NFSV3ACCESS_READ) {
595 ND_PRINT((ndo, " NFS_ACCESS_READ"));
598 if (access_flags & NFSV3ACCESS_LOOKUP) {
599 ND_PRINT((ndo, "%cNFS_ACCESS_LOOKUP", separator));
602 if (access_flags & NFSV3ACCESS_MODIFY) {
603 ND_PRINT((ndo, "%cNFS_ACCESS_MODIFY", separator));
606 if (access_flags & NFSV3ACCESS_EXTEND) {
607 ND_PRINT((ndo, "%cNFS_ACCESS_EXTEND", separator));
610 if (access_flags & NFSV3ACCESS_DELETE) {
611 ND_PRINT((ndo, "%cNFS_ACCESS_DELETE", separator));
614 if (access_flags & NFSV3ACCESS_EXECUTE)
615 ND_PRINT((ndo, "%cNFS_ACCESS_EXECUTE", separator));
622 if ((dp = parsereq(ndo, rp, length)) != NULL &&
623 (dp = parsefh(ndo, dp, v3)) != NULL) {
626 ND_PRINT((ndo, " %u bytes @ %" PRIu64,
627 EXTRACT_32BITS(&dp[2]),
628 EXTRACT_64BITS(&dp[0])));
631 ND_PRINT((ndo, " %u bytes @ %u",
632 EXTRACT_32BITS(&dp[1]),
633 EXTRACT_32BITS(&dp[0])));
640 if ((dp = parsereq(ndo, rp, length)) != NULL &&
641 (dp = parsefh(ndo, dp, v3)) != NULL) {
644 ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64,
645 EXTRACT_32BITS(&dp[4]),
646 EXTRACT_32BITS(&dp[2]),
647 EXTRACT_64BITS(&dp[0])));
648 if (ndo->ndo_vflag) {
651 ND_PRINT((ndo, " <%s>",
652 tok2str(nfsv3_writemodes,
653 NULL, EXTRACT_32BITS(dp))));
657 ND_PRINT((ndo, " %u (%u) bytes @ %u (%u)",
658 EXTRACT_32BITS(&dp[3]),
659 EXTRACT_32BITS(&dp[2]),
660 EXTRACT_32BITS(&dp[1]),
661 EXTRACT_32BITS(&dp[0])));
667 case NFSPROC_SYMLINK:
668 if ((dp = parsereq(ndo, rp, length)) != 0 &&
669 (dp = parsefhn(ndo, dp, v3)) != 0) {
670 ND_PRINT((ndo, " ->"));
671 if (v3 && (dp = parse_sattr3(ndo, dp, &sa3)) == 0)
673 if (parsefn(ndo, dp) == 0)
675 if (v3 && ndo->ndo_vflag)
676 print_sattr3(ndo, &sa3, ndo->ndo_vflag);
682 if ((dp = parsereq(ndo, rp, length)) != 0 &&
683 (dp = parsefhn(ndo, dp, v3)) != 0) {
685 type = (nfs_type)EXTRACT_32BITS(dp);
687 if ((dp = parse_sattr3(ndo, dp, &sa3)) == 0)
689 ND_PRINT((ndo, " %s", tok2str(type2str, "unk-ft %d", type)));
690 if (ndo->ndo_vflag && (type == NFCHR || type == NFBLK)) {
692 ND_PRINT((ndo, " %u/%u",
693 EXTRACT_32BITS(&dp[0]),
694 EXTRACT_32BITS(&dp[1])));
698 print_sattr3(ndo, &sa3, ndo->ndo_vflag);
704 if ((dp = parsereq(ndo, rp, length)) != NULL &&
705 (dp = parsefhn(ndo, dp, v3)) != NULL) {
706 ND_PRINT((ndo, " ->"));
707 if (parsefhn(ndo, dp, v3) != NULL)
713 if ((dp = parsereq(ndo, rp, length)) != NULL &&
714 (dp = parsefh(ndo, dp, v3)) != NULL) {
715 ND_PRINT((ndo, " ->"));
716 if (parsefhn(ndo, dp, v3) != NULL)
721 case NFSPROC_READDIR:
722 if ((dp = parsereq(ndo, rp, length)) != NULL &&
723 (dp = parsefh(ndo, dp, v3)) != NULL) {
727 * We shouldn't really try to interpret the
728 * offset cookie here.
730 ND_PRINT((ndo, " %u bytes @ %" PRId64,
731 EXTRACT_32BITS(&dp[4]),
732 EXTRACT_64BITS(&dp[0])));
734 ND_PRINT((ndo, " verf %08x%08x", dp[2], dp[3]));
738 * Print the offset as signed, since -1 is
739 * common, but offsets > 2^31 aren't.
741 ND_PRINT((ndo, " %u bytes @ %d",
742 EXTRACT_32BITS(&dp[1]),
743 EXTRACT_32BITS(&dp[0])));
749 case NFSPROC_READDIRPLUS:
750 if ((dp = parsereq(ndo, rp, length)) != NULL &&
751 (dp = parsefh(ndo, dp, v3)) != NULL) {
754 * We don't try to interpret the offset
757 ND_PRINT((ndo, " %u bytes @ %" PRId64,
758 EXTRACT_32BITS(&dp[4]),
759 EXTRACT_64BITS(&dp[0])));
760 if (ndo->ndo_vflag) {
762 ND_PRINT((ndo, " max %u verf %08x%08x",
763 EXTRACT_32BITS(&dp[5]), dp[2], dp[3]));
770 if ((dp = parsereq(ndo, rp, length)) != NULL &&
771 (dp = parsefh(ndo, dp, v3)) != NULL) {
773 ND_PRINT((ndo, " %u bytes @ %" PRIu64,
774 EXTRACT_32BITS(&dp[2]),
775 EXTRACT_64BITS(&dp[0])));
786 ND_PRINT((ndo, "%s", tstr));
790 * Print out an NFS file handle.
791 * We assume packet was not truncated before the end of the
792 * file handle pointed to by dp.
794 * Note: new version (using portable file-handle parser) doesn't produce
795 * generation number. It probably could be made to do that, with some
796 * additional hacking on the parser code.
799 nfs_printfh(netdissect_options *ndo,
800 register const uint32_t *dp, const u_int len)
804 const char *sfsname = NULL;
807 if (ndo->ndo_uflag) {
809 char const *sep = "";
811 ND_PRINT((ndo, " fh["));
812 for (i=0; i<len; i++) {
813 ND_PRINT((ndo, "%s%x", sep, dp[i]));
816 ND_PRINT((ndo, "]"));
820 Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0);
823 /* file system ID is ASCII, not numeric, for this server OS */
824 static char temp[NFSX_V3FHMAX+1];
826 /* Make sure string is null-terminated */
827 strncpy(temp, sfsname, NFSX_V3FHMAX);
828 temp[sizeof(temp) - 1] = '\0';
829 /* Remove trailing spaces */
830 spacep = strchr(temp, ' ');
834 ND_PRINT((ndo, " fh %s/", temp));
836 ND_PRINT((ndo, " fh %d,%d/",
837 fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor));
840 if(fsid.Fsid_dev.Minor == 257)
841 /* Print the undecoded handle */
842 ND_PRINT((ndo, "%s", fsid.Opaque_Handle));
844 ND_PRINT((ndo, "%ld", (long) ino));
848 * Maintain a small cache of recent client.XID.server/proc pairs, to allow
849 * us to match up replies with requests and thus to know how to parse
853 struct xid_map_entry {
854 uint32_t xid; /* transaction ID (net order) */
855 int ipver; /* IP version (4 or 6) */
857 struct in6_addr client; /* client IP address (net order) */
858 struct in6_addr server; /* server IP address (net order) */
860 struct in_addr client; /* client IP address (net order) */
861 struct in_addr server; /* server IP address (net order) */
863 uint32_t proc; /* call proc number (host order) */
864 uint32_t vers; /* program version (host order) */
868 * Map entries are kept in an array that we manage as a ring;
869 * new entries are always added at the tail of the ring. Initially,
870 * all the entries are zero and hence don't match anything.
873 #define XIDMAPSIZE 64
875 struct xid_map_entry xid_map[XIDMAPSIZE];
877 int xid_map_next = 0;
878 int xid_map_hint = 0;
881 xid_map_enter(netdissect_options *ndo,
882 const struct sunrpc_msg *rp, const u_char *bp)
884 struct ip *ip = NULL;
886 struct ip6_hdr *ip6 = NULL;
888 struct xid_map_entry *xmep;
890 if (!ND_TTEST(rp->rm_call.cb_vers))
892 switch (IP_V((struct ip *)bp)) {
894 ip = (struct ip *)bp;
898 ip6 = (struct ip6_hdr *)bp;
905 xmep = &xid_map[xid_map_next];
907 if (++xid_map_next >= XIDMAPSIZE)
910 UNALIGNED_MEMCPY(&xmep->xid, &rp->rm_xid, sizeof(xmep->xid));
913 UNALIGNED_MEMCPY(&xmep->client, &ip->ip_src, sizeof(ip->ip_src));
914 UNALIGNED_MEMCPY(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst));
919 UNALIGNED_MEMCPY(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src));
920 UNALIGNED_MEMCPY(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
923 xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
924 xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers);
929 * Returns 0 and puts NFSPROC_xxx in proc return and
930 * version in vers return, or returns -1 on failure
933 xid_map_find(const struct sunrpc_msg *rp, const u_char *bp, uint32_t *proc,
937 struct xid_map_entry *xmep;
938 uint32_t xid = rp->rm_xid;
939 struct ip *ip = (struct ip *)bp;
941 struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
945 /* Start searching from where we last left off */
950 if (xmep->ipver != IP_V(ip) || xmep->xid != xid)
952 switch (xmep->ipver) {
954 if (UNALIGNED_MEMCMP(&ip->ip_src, &xmep->server,
955 sizeof(ip->ip_src)) != 0 ||
956 UNALIGNED_MEMCMP(&ip->ip_dst, &xmep->client,
957 sizeof(ip->ip_dst)) != 0) {
963 if (UNALIGNED_MEMCMP(&ip6->ip6_src, &xmep->server,
964 sizeof(ip6->ip6_src)) != 0 ||
965 UNALIGNED_MEMCMP(&ip6->ip6_dst, &xmep->client,
966 sizeof(ip6->ip6_dst)) != 0) {
983 if (++i >= XIDMAPSIZE)
985 } while (i != xid_map_hint);
992 * Routines for parsing reply packets
996 * Return a pointer to the beginning of the actual results.
997 * If the packet was truncated, return 0.
999 static const uint32_t *
1000 parserep(netdissect_options *ndo,
1001 register const struct sunrpc_msg *rp, register u_int length)
1003 register const uint32_t *dp;
1005 enum sunrpc_accept_stat astat;
1009 * Here we find the address of the ar_verf credentials.
1010 * Originally, this calculation was
1011 * dp = (uint32_t *)&rp->rm_reply.rp_acpt.ar_verf
1012 * On the wire, the rp_acpt field starts immediately after
1013 * the (32 bit) rp_stat field. However, rp_acpt (which is a
1014 * "struct accepted_reply") contains a "struct opaque_auth",
1015 * whose internal representation contains a pointer, so on a
1016 * 64-bit machine the compiler inserts 32 bits of padding
1017 * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use
1018 * the internal representation to parse the on-the-wire
1019 * representation. Instead, we skip past the rp_stat field,
1020 * which is an "enum" and so occupies one 32-bit word.
1022 dp = ((const uint32_t *)&rp->rm_reply) + 1;
1024 len = EXTRACT_32BITS(&dp[1]);
1028 * skip past the ar_verf credentials.
1030 dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t);
1031 ND_TCHECK2(dp[0], 0);
1034 * now we can check the ar_stat field
1036 astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp);
1037 if (astat != SUNRPC_SUCCESS) {
1038 ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat)));
1039 nfserr = 1; /* suppress trunc string */
1042 /* successful return */
1043 ND_TCHECK2(*dp, sizeof(astat));
1044 return ((uint32_t *) (sizeof(astat) + ((char *)dp)));
1049 static const uint32_t *
1050 parsestatus(netdissect_options *ndo,
1051 const uint32_t *dp, int *er)
1057 errnum = EXTRACT_32BITS(&dp[0]);
1061 if (!ndo->ndo_qflag)
1062 ND_PRINT((ndo, " ERROR: %s",
1063 tok2str(status2str, "unk %d", errnum)));
1071 static const uint32_t *
1072 parsefattr(netdissect_options *ndo,
1073 const uint32_t *dp, int verbose, int v3)
1075 const struct nfs_fattr *fap;
1077 fap = (const struct nfs_fattr *)dp;
1078 ND_TCHECK(fap->fa_gid);
1080 ND_PRINT((ndo, " %s %o ids %d/%d",
1081 tok2str(type2str, "unk-ft %d ",
1082 EXTRACT_32BITS(&fap->fa_type)),
1083 EXTRACT_32BITS(&fap->fa_mode),
1084 EXTRACT_32BITS(&fap->fa_uid),
1085 EXTRACT_32BITS(&fap->fa_gid)));
1087 ND_TCHECK(fap->fa3_size);
1088 ND_PRINT((ndo, " sz %" PRIu64,
1089 EXTRACT_64BITS((uint32_t *)&fap->fa3_size)));
1091 ND_TCHECK(fap->fa2_size);
1092 ND_PRINT((ndo, " sz %d", EXTRACT_32BITS(&fap->fa2_size)));
1095 /* print lots more stuff */
1098 ND_TCHECK(fap->fa3_ctime);
1099 ND_PRINT((ndo, " nlink %d rdev %d/%d",
1100 EXTRACT_32BITS(&fap->fa_nlink),
1101 EXTRACT_32BITS(&fap->fa3_rdev.specdata1),
1102 EXTRACT_32BITS(&fap->fa3_rdev.specdata2)));
1103 ND_PRINT((ndo, " fsid %" PRIx64,
1104 EXTRACT_64BITS((uint32_t *)&fap->fa3_fsid)));
1105 ND_PRINT((ndo, " fileid %" PRIx64,
1106 EXTRACT_64BITS((uint32_t *)&fap->fa3_fileid)));
1107 ND_PRINT((ndo, " a/m/ctime %u.%06u",
1108 EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec),
1109 EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)));
1110 ND_PRINT((ndo, " %u.%06u",
1111 EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec),
1112 EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)));
1113 ND_PRINT((ndo, " %u.%06u",
1114 EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec),
1115 EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)));
1117 ND_TCHECK(fap->fa2_ctime);
1118 ND_PRINT((ndo, " nlink %d rdev 0x%x fsid 0x%x nodeid 0x%x a/m/ctime",
1119 EXTRACT_32BITS(&fap->fa_nlink),
1120 EXTRACT_32BITS(&fap->fa2_rdev),
1121 EXTRACT_32BITS(&fap->fa2_fsid),
1122 EXTRACT_32BITS(&fap->fa2_fileid)));
1123 ND_PRINT((ndo, " %u.%06u",
1124 EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec),
1125 EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)));
1126 ND_PRINT((ndo, " %u.%06u",
1127 EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec),
1128 EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)));
1129 ND_PRINT((ndo, " %u.%06u",
1130 EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec),
1131 EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)));
1134 return ((const uint32_t *)((unsigned char *)dp +
1135 (v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
1141 parseattrstat(netdissect_options *ndo,
1142 const uint32_t *dp, int verbose, int v3)
1146 dp = parsestatus(ndo, dp, &er);
1152 return (parsefattr(ndo, dp, verbose, v3) != NULL);
1156 parsediropres(netdissect_options *ndo,
1161 if (!(dp = parsestatus(ndo, dp, &er)))
1166 dp = parsefh(ndo, dp, 0);
1170 return (parsefattr(ndo, dp, ndo->ndo_vflag, 0) != NULL);
1174 parselinkres(netdissect_options *ndo,
1175 const uint32_t *dp, int v3)
1179 dp = parsestatus(ndo, dp, &er);
1184 if (v3 && !(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1186 ND_PRINT((ndo, " "));
1187 return (parsefn(ndo, dp) != NULL);
1191 parsestatfs(netdissect_options *ndo,
1192 const uint32_t *dp, int v3)
1194 const struct nfs_statfs *sfsp;
1197 dp = parsestatus(ndo, dp, &er);
1208 ND_PRINT((ndo, " POST:"));
1209 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1213 ND_TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));
1215 sfsp = (const struct nfs_statfs *)dp;
1218 ND_PRINT((ndo, " tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
1219 EXTRACT_64BITS((uint32_t *)&sfsp->sf_tbytes),
1220 EXTRACT_64BITS((uint32_t *)&sfsp->sf_fbytes),
1221 EXTRACT_64BITS((uint32_t *)&sfsp->sf_abytes)));
1222 if (ndo->ndo_vflag) {
1223 ND_PRINT((ndo, " tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
1224 EXTRACT_64BITS((uint32_t *)&sfsp->sf_tfiles),
1225 EXTRACT_64BITS((uint32_t *)&sfsp->sf_ffiles),
1226 EXTRACT_64BITS((uint32_t *)&sfsp->sf_afiles),
1227 EXTRACT_32BITS(&sfsp->sf_invarsec)));
1230 ND_PRINT((ndo, " tsize %d bsize %d blocks %d bfree %d bavail %d",
1231 EXTRACT_32BITS(&sfsp->sf_tsize),
1232 EXTRACT_32BITS(&sfsp->sf_bsize),
1233 EXTRACT_32BITS(&sfsp->sf_blocks),
1234 EXTRACT_32BITS(&sfsp->sf_bfree),
1235 EXTRACT_32BITS(&sfsp->sf_bavail)));
1244 parserddires(netdissect_options *ndo,
1249 dp = parsestatus(ndo, dp, &er);
1258 ND_PRINT((ndo, " offset 0x%x size %d ",
1259 EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])));
1261 ND_PRINT((ndo, " eof"));
1268 static const uint32_t *
1269 parse_wcc_attr(netdissect_options *ndo,
1272 ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0])));
1273 ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u",
1274 EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]),
1275 EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])));
1280 * Pre operation attributes. Print only if vflag > 1.
1282 static const uint32_t *
1283 parse_pre_op_attr(netdissect_options *ndo,
1284 const uint32_t *dp, int verbose)
1287 if (!EXTRACT_32BITS(&dp[0]))
1290 ND_TCHECK2(*dp, 24);
1292 return parse_wcc_attr(ndo, dp);
1294 /* If not verbose enough, just skip over wcc_attr */
1302 * Post operation attributes are printed if vflag >= 1
1304 static const uint32_t *
1305 parse_post_op_attr(netdissect_options *ndo,
1306 const uint32_t *dp, int verbose)
1309 if (!EXTRACT_32BITS(&dp[0]))
1313 return parsefattr(ndo, dp, verbose, 1);
1315 return (dp + (NFSX_V3FATTR / sizeof (uint32_t)));
1320 static const uint32_t *
1321 parse_wcc_data(netdissect_options *ndo,
1322 const uint32_t *dp, int verbose)
1325 ND_PRINT((ndo, " PRE:"));
1326 if (!(dp = parse_pre_op_attr(ndo, dp, verbose)))
1330 ND_PRINT((ndo, " POST:"));
1331 return parse_post_op_attr(ndo, dp, verbose);
1334 static const uint32_t *
1335 parsecreateopres(netdissect_options *ndo,
1336 const uint32_t *dp, int verbose)
1340 if (!(dp = parsestatus(ndo, dp, &er)))
1343 dp = parse_wcc_data(ndo, dp, verbose);
1346 if (!EXTRACT_32BITS(&dp[0]))
1349 if (!(dp = parsefh(ndo, dp, 1)))
1352 if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
1354 if (ndo->ndo_vflag > 1) {
1355 ND_PRINT((ndo, " dir attr:"));
1356 dp = parse_wcc_data(ndo, dp, verbose);
1366 parsewccres(netdissect_options *ndo,
1367 const uint32_t *dp, int verbose)
1371 if (!(dp = parsestatus(ndo, dp, &er)))
1373 return parse_wcc_data(ndo, dp, verbose) != 0;
1376 static const uint32_t *
1377 parsev3rddirres(netdissect_options *ndo,
1378 const uint32_t *dp, int verbose)
1382 if (!(dp = parsestatus(ndo, dp, &er)))
1385 ND_PRINT((ndo, " POST:"));
1386 if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
1390 if (ndo->ndo_vflag) {
1392 ND_PRINT((ndo, " verf %08x%08x", dp[0], dp[1]));
1401 parsefsinfo(netdissect_options *ndo,
1404 struct nfsv3_fsinfo *sfp;
1407 if (!(dp = parsestatus(ndo, dp, &er)))
1410 ND_PRINT((ndo, " POST:"));
1411 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1416 sfp = (struct nfsv3_fsinfo *)dp;
1418 ND_PRINT((ndo, " rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
1419 EXTRACT_32BITS(&sfp->fs_rtmax),
1420 EXTRACT_32BITS(&sfp->fs_rtpref),
1421 EXTRACT_32BITS(&sfp->fs_wtmax),
1422 EXTRACT_32BITS(&sfp->fs_wtpref),
1423 EXTRACT_32BITS(&sfp->fs_dtpref)));
1424 if (ndo->ndo_vflag) {
1425 ND_PRINT((ndo, " rtmult %u wtmult %u maxfsz %" PRIu64,
1426 EXTRACT_32BITS(&sfp->fs_rtmult),
1427 EXTRACT_32BITS(&sfp->fs_wtmult),
1428 EXTRACT_64BITS((uint32_t *)&sfp->fs_maxfilesize)));
1429 ND_PRINT((ndo, " delta %u.%06u ",
1430 EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec),
1431 EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)));
1439 parsepathconf(netdissect_options *ndo,
1443 struct nfsv3_pathconf *spp;
1445 if (!(dp = parsestatus(ndo, dp, &er)))
1448 ND_PRINT((ndo, " POST:"));
1449 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1454 spp = (struct nfsv3_pathconf *)dp;
1457 ND_PRINT((ndo, " linkmax %u namemax %u %s %s %s %s",
1458 EXTRACT_32BITS(&spp->pc_linkmax),
1459 EXTRACT_32BITS(&spp->pc_namemax),
1460 EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "",
1461 EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "",
1462 EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "",
1463 EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""));
1470 interp_reply(netdissect_options *ndo,
1471 const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers, int length)
1473 register const uint32_t *dp;
1477 v3 = (vers == NFS_VER3);
1479 if (!v3 && proc < NFS_NPROCS)
1480 proc = nfsv3_procid[proc];
1482 ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
1485 case NFSPROC_GETATTR:
1486 dp = parserep(ndo, rp, length);
1487 if (dp != NULL && parseattrstat(ndo, dp, !ndo->ndo_qflag, v3) != 0)
1491 case NFSPROC_SETATTR:
1492 if (!(dp = parserep(ndo, rp, length)))
1495 if (parsewccres(ndo, dp, ndo->ndo_vflag))
1498 if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0) != 0)
1503 case NFSPROC_LOOKUP:
1504 if (!(dp = parserep(ndo, rp, length)))
1507 if (!(dp = parsestatus(ndo, dp, &er)))
1510 if (ndo->ndo_vflag > 1) {
1511 ND_PRINT((ndo, " post dattr:"));
1512 dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
1515 if (!(dp = parsefh(ndo, dp, v3)))
1517 if ((dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)) &&
1518 ndo->ndo_vflag > 1) {
1519 ND_PRINT((ndo, " post dattr:"));
1520 dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
1526 if (parsediropres(ndo, dp) != 0)
1531 case NFSPROC_ACCESS:
1532 if (!(dp = parserep(ndo, rp, length)))
1534 if (!(dp = parsestatus(ndo, dp, &er)))
1537 ND_PRINT((ndo, " attr:"));
1538 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1541 ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0])));
1544 case NFSPROC_READLINK:
1545 dp = parserep(ndo, rp, length);
1546 if (dp != NULL && parselinkres(ndo, dp, v3) != 0)
1551 if (!(dp = parserep(ndo, rp, length)))
1554 if (!(dp = parsestatus(ndo, dp, &er)))
1556 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1560 if (ndo->ndo_vflag) {
1562 ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
1563 if (EXTRACT_32BITS(&dp[1]))
1564 ND_PRINT((ndo, " EOF"));
1568 if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0) != 0)
1574 if (!(dp = parserep(ndo, rp, length)))
1577 if (!(dp = parsestatus(ndo, dp, &er)))
1579 if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1583 if (ndo->ndo_vflag) {
1585 ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
1586 if (ndo->ndo_vflag > 1) {
1588 ND_PRINT((ndo, " <%s>",
1589 tok2str(nfsv3_writemodes,
1590 NULL, EXTRACT_32BITS(&dp[1]))));
1595 if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3) != 0)
1600 case NFSPROC_CREATE:
1602 if (!(dp = parserep(ndo, rp, length)))
1605 if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1608 if (parsediropres(ndo, dp) != 0)
1613 case NFSPROC_SYMLINK:
1614 if (!(dp = parserep(ndo, rp, length)))
1617 if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1620 if (parsestatus(ndo, dp, &er) != 0)
1626 if (!(dp = parserep(ndo, rp, length)))
1628 if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1632 case NFSPROC_REMOVE:
1634 if (!(dp = parserep(ndo, rp, length)))
1637 if (parsewccres(ndo, dp, ndo->ndo_vflag))
1640 if (parsestatus(ndo, dp, &er) != 0)
1645 case NFSPROC_RENAME:
1646 if (!(dp = parserep(ndo, rp, length)))
1649 if (!(dp = parsestatus(ndo, dp, &er)))
1651 if (ndo->ndo_vflag) {
1652 ND_PRINT((ndo, " from:"));
1653 if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1655 ND_PRINT((ndo, " to:"));
1656 if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1661 if (parsestatus(ndo, dp, &er) != 0)
1667 if (!(dp = parserep(ndo, rp, length)))
1670 if (!(dp = parsestatus(ndo, dp, &er)))
1672 if (ndo->ndo_vflag) {
1673 ND_PRINT((ndo, " file POST:"));
1674 if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1676 ND_PRINT((ndo, " dir:"));
1677 if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1682 if (parsestatus(ndo, dp, &er) != 0)
1687 case NFSPROC_READDIR:
1688 if (!(dp = parserep(ndo, rp, length)))
1691 if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
1694 if (parserddires(ndo, dp) != 0)
1699 case NFSPROC_READDIRPLUS:
1700 if (!(dp = parserep(ndo, rp, length)))
1702 if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
1706 case NFSPROC_FSSTAT:
1707 dp = parserep(ndo, rp, length);
1708 if (dp != NULL && parsestatfs(ndo, dp, v3) != 0)
1712 case NFSPROC_FSINFO:
1713 dp = parserep(ndo, rp, length);
1714 if (dp != NULL && parsefsinfo(ndo, dp) != 0)
1718 case NFSPROC_PATHCONF:
1719 dp = parserep(ndo, rp, length);
1720 if (dp != NULL && parsepathconf(ndo, dp) != 0)
1724 case NFSPROC_COMMIT:
1725 dp = parserep(ndo, rp, length);
1726 if (dp != NULL && parsewccres(ndo, dp, ndo->ndo_vflag) != 0)
1735 ND_PRINT((ndo, "%s", tstr));