예제 #1
0
static const uint32_t *
parsev3rddirres(netdissect_options *ndo,
                const uint32_t *dp, int verbose)
{
	u_int er;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT(" POST:");
	if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
		return (0);
	if (er)
		return dp;
	if (ndo->ndo_vflag) {
		ND_TCHECK_4(dp + 1);
		/*
		 * This displays the 8 bytes of the verifier in order,
		 * from the low-order byte to the high-order byte.
		 */
		ND_PRINT(" verf %08x%08x",
			  EXTRACT_BE_U_4(dp), EXTRACT_BE_U_4(dp + 1));
		dp += 2;
	}
	return dp;
trunc:
	return (NULL);
}
예제 #2
0
static int
parsepathconf(const u_int32_t *dp)
{
	int er;
	struct nfsv3_pathconf *spp;

	if (!(dp = parsestatus(dp, &er)))
		return (0);
	if (vflag)
		printf(" POST:");
	if (!(dp = parse_post_op_attr(dp, vflag)))
		return (0);
	if (er)
		return (1);

	spp = (struct nfsv3_pathconf *)dp;
	TCHECK(*spp);

	printf(" linkmax %u namemax %u %s %s %s %s",
	       EXTRACT_32BITS(&spp->pc_linkmax),
	       EXTRACT_32BITS(&spp->pc_namemax),
	       EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "",
	       EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "",
	       EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "",
	       EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : "");
	return (1);
trunc:
	return (0);
}
예제 #3
0
static const uint32_t *
parsecreateopres(netdissect_options *ndo,
                 const uint32_t *dp, int verbose)
{
	u_int er;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (er)
		dp = parse_wcc_data(ndo, dp, verbose);
	else {
		ND_TCHECK_4(dp);
		if (!EXTRACT_BE_U_4(dp))
			return (dp + 1);
		dp++;
		if (!(dp = parsefh(ndo, dp, 1)))
			return (0);
		if (verbose) {
			if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
				return (0);
			if (ndo->ndo_vflag > 1) {
				ND_PRINT(" dir attr:");
				dp = parse_wcc_data(ndo, dp, verbose);
			}
		}
	}
	return (dp);
trunc:
	return (NULL);
}
예제 #4
0
static const u_int32_t *
parsecreateopres(const u_int32_t *dp, int verbose)
{
	int er;

	if (!(dp = parsestatus(dp, &er)))
		return (0);
	if (er)
		dp = parse_wcc_data(dp, verbose);
	else {
		TCHECK(dp[0]);
		if (!EXTRACT_32BITS(&dp[0]))
			return (dp + 1);
		dp++;
		if (!(dp = parsefh(dp, 1)))
			return (0);
		if (verbose) {
			if (!(dp = parse_post_op_attr(dp, verbose)))
				return (0);
			if (vflag > 1) {
				printf(" dir attr:");
				dp = parse_wcc_data(dp, verbose);
			}
		}
	}
	return (dp);
trunc:
	return (NULL);
}
예제 #5
0
static int
parsepathconf(netdissect_options *ndo,
              const uint32_t *dp)
{
	u_int er;
	const struct nfsv3_pathconf *spp;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT(" POST:");
	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
		return (0);
	if (er)
		return (1);

	spp = (const struct nfsv3_pathconf *)dp;
	ND_TCHECK_SIZE(spp);

	ND_PRINT(" linkmax %u namemax %u %s %s %s %s",
	       EXTRACT_BE_U_4(&spp->pc_linkmax),
	       EXTRACT_BE_U_4(&spp->pc_namemax),
	       EXTRACT_BE_U_4(&spp->pc_notrunc) ? "notrunc" : "",
	       EXTRACT_BE_U_4(&spp->pc_chownrestricted) ? "chownres" : "",
	       EXTRACT_BE_U_4(&spp->pc_caseinsensitive) ? "igncase" : "",
	       EXTRACT_BE_U_4(&spp->pc_casepreserving) ? "keepcase" : "");
	return (1);
trunc:
	return (0);
}
예제 #6
0
static const u_int32_t *
parse_wcc_data(const u_int32_t *dp, int verbose)
{
	if (verbose > 1)
		printf(" PRE:");
	if (!(dp = parse_pre_op_attr(dp, verbose)))
		return (0);

	if (verbose)
		printf(" POST:");
	return parse_post_op_attr(dp, verbose);
}
예제 #7
0
static int
parsestatfs(netdissect_options *ndo,
            const uint32_t *dp, int v3)
{
	const struct nfs_statfs *sfsp;
	u_int er;

	dp = parsestatus(ndo, dp, &er);
	if (dp == NULL)
		return (0);
	if (!v3 && er)
		return (1);

	if (ndo->ndo_qflag)
		return(1);

	if (v3) {
		if (ndo->ndo_vflag)
			ND_PRINT(" POST:");
		if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
			return (0);
	}

	ND_TCHECK_LEN(dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));

	sfsp = (const struct nfs_statfs *)dp;

	if (v3) {
		ND_PRINT(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
			EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_tbytes),
			EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_fbytes),
			EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_abytes));
		if (ndo->ndo_vflag) {
			ND_PRINT(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
			       EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_tfiles),
			       EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_ffiles),
			       EXTRACT_BE_U_8((const uint32_t *)&sfsp->sf_afiles),
			       EXTRACT_BE_U_4(&sfsp->sf_invarsec));
		}
	} else {
		ND_PRINT(" tsize %u bsize %u blocks %u bfree %u bavail %u",
			EXTRACT_BE_U_4(&sfsp->sf_tsize),
			EXTRACT_BE_U_4(&sfsp->sf_bsize),
			EXTRACT_BE_U_4(&sfsp->sf_blocks),
			EXTRACT_BE_U_4(&sfsp->sf_bfree),
			EXTRACT_BE_U_4(&sfsp->sf_bavail));
	}

	return (1);
trunc:
	return (0);
}
예제 #8
0
static const uint32_t *
parse_wcc_data(netdissect_options *ndo,
               const uint32_t *dp, int verbose)
{
	if (verbose > 1)
		ND_PRINT(" PRE:");
	if (!(dp = parse_pre_op_attr(ndo, dp, verbose)))
		return (0);

	if (verbose)
		ND_PRINT(" POST:");
	return parse_post_op_attr(ndo, dp, verbose);
}
예제 #9
0
static int
parsestatfs(const u_int32_t *dp, int v3)
{
	const struct nfs_statfs *sfsp;
	int er;

	dp = parsestatus(dp, &er);
	if (dp == NULL)
		return (0);
	if (!v3 && er)
		return (1);

	if (qflag)
		return(1);

	if (v3) {
		if (vflag)
			printf(" POST:");
		if (!(dp = parse_post_op_attr(dp, vflag)))
			return (0);
	}

	TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));

	sfsp = (const struct nfs_statfs *)dp;

	if (v3) {
		printf(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
			EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tbytes),
			EXTRACT_64BITS((u_int32_t *)&sfsp->sf_fbytes),
			EXTRACT_64BITS((u_int32_t *)&sfsp->sf_abytes));
		if (vflag) {
			printf(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
			       EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tfiles),
			       EXTRACT_64BITS((u_int32_t *)&sfsp->sf_ffiles),
			       EXTRACT_64BITS((u_int32_t *)&sfsp->sf_afiles),
			       EXTRACT_32BITS(&sfsp->sf_invarsec));
		}
	} else {
		printf(" tsize %d bsize %d blocks %d bfree %d bavail %d",
			EXTRACT_32BITS(&sfsp->sf_tsize),
			EXTRACT_32BITS(&sfsp->sf_bsize),
			EXTRACT_32BITS(&sfsp->sf_blocks),
			EXTRACT_32BITS(&sfsp->sf_bfree),
			EXTRACT_32BITS(&sfsp->sf_bavail));
	}

	return (1);
trunc:
	return (0);
}
예제 #10
0
static int
parselinkres(const u_int32_t *dp, int v3)
{
	int er;

	dp = parsestatus(dp, &er);
	if (dp == NULL)
		return(0);
	if (er)
		return(1);
	if (v3 && !(dp = parse_post_op_attr(dp, vflag)))
		return (0);
	putchar(' ');
	return (parsefn(dp) != NULL);
}
예제 #11
0
static int
parselinkres(netdissect_options *ndo,
             const uint32_t *dp, int v3)
{
	u_int er;

	dp = parsestatus(ndo, dp, &er);
	if (dp == NULL)
		return(0);
	if (er)
		return(1);
	if (v3 && !(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
		return (0);
	ND_PRINT(" ");
	return (parsefn(ndo, dp) != NULL);
}
예제 #12
0
static const u_int32_t *
parsev3rddirres(const u_int32_t *dp, int verbose)
{
	int er;

	if (!(dp = parsestatus(dp, &er)))
		return (0);
	if (vflag)
		printf(" POST:");
	if (!(dp = parse_post_op_attr(dp, verbose)))
		return (0);
	if (er)
		return dp;
	if (vflag) {
		TCHECK(dp[1]);
		printf(" verf %08x%08x", dp[0], dp[1]);
		dp += 2;
	}
	return dp;
trunc:
	return (NULL);
}
예제 #13
0
static const uint32_t *
parsev3rddirres(netdissect_options *ndo,
                const uint32_t *dp, int verbose)
{
	int er;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT((ndo, " POST:"));
	if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
		return (0);
	if (er)
		return dp;
	if (ndo->ndo_vflag) {
		ND_TCHECK(dp[1]);
		ND_PRINT((ndo, " verf %08x%08x", dp[0], dp[1]));
		dp += 2;
	}
	return dp;
trunc:
	return (NULL);
}
예제 #14
0
static int
parsefsinfo(netdissect_options *ndo,
            const uint32_t *dp)
{
	const struct nfsv3_fsinfo *sfp;
	u_int er;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT(" POST:");
	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
		return (0);
	if (er)
		return (1);

	sfp = (const struct nfsv3_fsinfo *)dp;
	ND_TCHECK_SIZE(sfp);
	ND_PRINT(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
	       EXTRACT_BE_U_4(&sfp->fs_rtmax),
	       EXTRACT_BE_U_4(&sfp->fs_rtpref),
	       EXTRACT_BE_U_4(&sfp->fs_wtmax),
	       EXTRACT_BE_U_4(&sfp->fs_wtpref),
	       EXTRACT_BE_U_4(&sfp->fs_dtpref));
	if (ndo->ndo_vflag) {
		ND_PRINT(" rtmult %u wtmult %u maxfsz %" PRIu64,
		       EXTRACT_BE_U_4(&sfp->fs_rtmult),
		       EXTRACT_BE_U_4(&sfp->fs_wtmult),
		       EXTRACT_BE_U_8((const uint32_t *)&sfp->fs_maxfilesize));
		ND_PRINT(" delta %u.%06u ",
		       EXTRACT_BE_U_4(&sfp->fs_timedelta.nfsv3_sec),
		       EXTRACT_BE_U_4(&sfp->fs_timedelta.nfsv3_nsec));
	}
	return (1);
trunc:
	return (0);
}
예제 #15
0
static int
parsefsinfo(const u_int32_t *dp)
{
	struct nfsv3_fsinfo *sfp;
	int er;

	if (!(dp = parsestatus(dp, &er)))
		return (0);
	if (vflag)
		printf(" POST:");
	if (!(dp = parse_post_op_attr(dp, vflag)))
		return (0);
	if (er)
		return (1);

	sfp = (struct nfsv3_fsinfo *)dp;
	TCHECK(*sfp);
	printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
	       EXTRACT_32BITS(&sfp->fs_rtmax),
	       EXTRACT_32BITS(&sfp->fs_rtpref),
	       EXTRACT_32BITS(&sfp->fs_wtmax),
	       EXTRACT_32BITS(&sfp->fs_wtpref),
	       EXTRACT_32BITS(&sfp->fs_dtpref));
	if (vflag) {
		printf(" rtmult %u wtmult %u maxfsz %" PRIu64,
		       EXTRACT_32BITS(&sfp->fs_rtmult),
		       EXTRACT_32BITS(&sfp->fs_wtmult),
		       EXTRACT_64BITS((u_int32_t *)&sfp->fs_maxfilesize));
		printf(" delta %u.%06u ",
		       EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec),
		       EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec));
	}
	return (1);
trunc:
	return (0);
}
예제 #16
0
static void
interp_reply(netdissect_options *ndo,
             const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers, int length)
{
	const uint32_t *dp;
	int v3;
	u_int er;

	v3 = (vers == NFS_VER3);

	if (!v3 && proc < NFS_NPROCS)
		proc = nfsv3_procid[proc];

	ND_PRINT(" %s", tok2str(nfsproc_str, "proc-%u", proc));
	switch (proc) {

	case NFSPROC_GETATTR:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parseattrstat(ndo, dp, !ndo->ndo_qflag, v3) != 0)
			return;
		break;

	case NFSPROC_SETATTR:
		if (!(dp = parserep(ndo, rp, length)))
			return;
		if (v3) {
			if (parsewccres(ndo, dp, ndo->ndo_vflag))
				return;
		} else {
			if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0) != 0)
				return;
		}
		break;

	case NFSPROC_LOOKUP:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(ndo, dp, &er)))
				break;
			if (er) {
				if (ndo->ndo_vflag > 1) {
					ND_PRINT(" post dattr:");
					dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
				}
			} else {
				if (!(dp = parsefh(ndo, dp, v3)))
					break;
				if ((dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)) &&
				    ndo->ndo_vflag > 1) {
					ND_PRINT(" post dattr:");
					dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
				}
			}
			if (dp)
				return;
		} else {
			if (parsediropres(ndo, dp) != 0)
				return;
		}
		break;

	case NFSPROC_ACCESS:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (!(dp = parsestatus(ndo, dp, &er)))
			break;
		if (ndo->ndo_vflag)
			ND_PRINT(" attr:");
		if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
			break;
		if (!er) {
			ND_TCHECK_4(dp);
			ND_PRINT(" c %04x", EXTRACT_BE_U_4(dp));
		}
		return;

	case NFSPROC_READLINK:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parselinkres(ndo, dp, v3) != 0)
			return;
		break;

	case NFSPROC_READ:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(ndo, dp, &er)))
				break;
			if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
				break;
			if (er)
				return;
			if (ndo->ndo_vflag) {
				ND_TCHECK_4(dp + 1);
				ND_PRINT(" %u bytes", EXTRACT_BE_U_4(dp));
				if (EXTRACT_BE_U_4(dp + 1))
					ND_PRINT(" EOF");
			}
			return;
		} else {
			if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0) != 0)
				return;
		}
		break;

	case NFSPROC_WRITE:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(ndo, dp, &er)))
				break;
			if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
				break;
			if (er)
				return;
			if (ndo->ndo_vflag) {
				ND_TCHECK_4(dp);
				ND_PRINT(" %u bytes", EXTRACT_BE_U_4(dp));
				if (ndo->ndo_vflag > 1) {
					ND_TCHECK_4(dp + 1);
					ND_PRINT(" <%s>",
						tok2str(nfsv3_writemodes,
							NULL, EXTRACT_BE_U_4(dp + 1)));
				}
				return;
			}
		} else {
			if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3) != 0)
				return;
		}
		break;

	case NFSPROC_CREATE:
	case NFSPROC_MKDIR:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != NULL)
				return;
		} else {
			if (parsediropres(ndo, dp) != 0)
				return;
		}
		break;

	case NFSPROC_SYMLINK:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != NULL)
				return;
		} else {
			if (parsestatus(ndo, dp, &er) != NULL)
				return;
		}
		break;

	case NFSPROC_MKNOD:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != NULL)
			return;
		break;

	case NFSPROC_REMOVE:
	case NFSPROC_RMDIR:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (parsewccres(ndo, dp, ndo->ndo_vflag))
				return;
		} else {
			if (parsestatus(ndo, dp, &er) != NULL)
				return;
		}
		break;

	case NFSPROC_RENAME:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(ndo, dp, &er)))
				break;
			if (ndo->ndo_vflag) {
				ND_PRINT(" from:");
				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
					break;
				ND_PRINT(" to:");
				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
					break;
			}
			return;
		} else {
			if (parsestatus(ndo, dp, &er) != NULL)
				return;
		}
		break;

	case NFSPROC_LINK:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(ndo, dp, &er)))
				break;
			if (ndo->ndo_vflag) {
				ND_PRINT(" file POST:");
				if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
					break;
				ND_PRINT(" dir:");
				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
					break;
				return;
			}
		} else {
			if (parsestatus(ndo, dp, &er) != NULL)
				return;
		}
		break;

	case NFSPROC_READDIR:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (v3) {
			if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
				return;
		} else {
			if (parserddires(ndo, dp) != 0)
				return;
		}
		break;

	case NFSPROC_READDIRPLUS:
		if (!(dp = parserep(ndo, rp, length)))
			break;
		if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
			return;
		break;

	case NFSPROC_FSSTAT:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parsestatfs(ndo, dp, v3) != 0)
			return;
		break;

	case NFSPROC_FSINFO:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parsefsinfo(ndo, dp) != 0)
			return;
		break;

	case NFSPROC_PATHCONF:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parsepathconf(ndo, dp) != 0)
			return;
		break;

	case NFSPROC_COMMIT:
		dp = parserep(ndo, rp, length);
		if (dp != NULL && parsewccres(ndo, dp, ndo->ndo_vflag) != 0)
			return;
		break;

	default:
		return;
	}
trunc:
	if (!nfserr)
		ND_PRINT("%s", tstr);
}
예제 #17
0
static void
interp_reply(const struct sunrpc_msg *rp, u_int32_t proc, u_int32_t vers, int length)
{
	register const u_int32_t *dp;
	register int v3;
	int er;

	v3 = (vers == NFS_VER3);

	if (!v3 && proc < NFS_NPROCS)
		proc = nfsv3_procid[proc];

	switch (proc) {

	case NFSPROC_NOOP:
		printf(" nop");
		return;

	case NFSPROC_NULL:
		printf(" null");
		return;

	case NFSPROC_GETATTR:
		printf(" getattr");
		dp = parserep(rp, length);
		if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0)
			return;
		break;

	case NFSPROC_SETATTR:
		printf(" setattr");
		if (!(dp = parserep(rp, length)))
			return;
		if (v3) {
			if (parsewccres(dp, vflag))
				return;
		} else {
			if (parseattrstat(dp, !qflag, 0) != 0)
				return;
		}
		break;

	case NFSPROC_LOOKUP:
		printf(" lookup");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(dp, &er)))
				break;
			if (er) {
				if (vflag > 1) {
					printf(" post dattr:");
					dp = parse_post_op_attr(dp, vflag);
				}
			} else {
				if (!(dp = parsefh(dp, v3)))
					break;
				if ((dp = parse_post_op_attr(dp, vflag)) &&
				    vflag > 1) {
					printf(" post dattr:");
					dp = parse_post_op_attr(dp, vflag);
				}
			}
			if (dp)
				return;
		} else {
			if (parsediropres(dp) != 0)
				return;
		}
		break;

	case NFSPROC_ACCESS:
		printf(" access");
		if (!(dp = parserep(rp, length)))
			break;
		if (!(dp = parsestatus(dp, &er)))
			break;
		if (vflag)
			printf(" attr:");
		if (!(dp = parse_post_op_attr(dp, vflag)))
			break;
		if (!er)
			printf(" c %04x", EXTRACT_32BITS(&dp[0]));
		return;

	case NFSPROC_READLINK:
		printf(" readlink");
		dp = parserep(rp, length);
		if (dp != NULL && parselinkres(dp, v3) != 0)
			return;
		break;

	case NFSPROC_READ:
		printf(" read");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(dp, &er)))
				break;
			if (!(dp = parse_post_op_attr(dp, vflag)))
				break;
			if (er)
				return;
			if (vflag) {
				TCHECK(dp[1]);
				printf(" %u bytes", EXTRACT_32BITS(&dp[0]));
				if (EXTRACT_32BITS(&dp[1]))
					printf(" EOF");
			}
			return;
		} else {
			if (parseattrstat(dp, vflag, 0) != 0)
				return;
		}
		break;

	case NFSPROC_WRITE:
		printf(" write");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(dp, &er)))
				break;
			if (!(dp = parse_wcc_data(dp, vflag)))
				break;
			if (er)
				return;
			if (vflag) {
				TCHECK(dp[0]);
				printf(" %u bytes", EXTRACT_32BITS(&dp[0]));
				if (vflag > 1) {
					TCHECK(dp[1]);
					printf(" <%s>",
						tok2str(nfsv3_writemodes,
							NULL, EXTRACT_32BITS(&dp[1])));
				}
				return;
			}
		} else {
			if (parseattrstat(dp, vflag, v3) != 0)
				return;
		}
		break;

	case NFSPROC_CREATE:
		printf(" create");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsecreateopres(dp, vflag) != 0)
				return;
		} else {
			if (parsediropres(dp) != 0)
				return;
		}
		break;

	case NFSPROC_MKDIR:
		printf(" mkdir");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsecreateopres(dp, vflag) != 0)
				return;
		} else {
			if (parsediropres(dp) != 0)
				return;
		}
		break;

	case NFSPROC_SYMLINK:
		printf(" symlink");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsecreateopres(dp, vflag) != 0)
				return;
		} else {
			if (parsestatus(dp, &er) != 0)
				return;
		}
		break;

	case NFSPROC_MKNOD:
		printf(" mknod");
		if (!(dp = parserep(rp, length)))
			break;
		if (parsecreateopres(dp, vflag) != 0)
			return;
		break;

	case NFSPROC_REMOVE:
		printf(" remove");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsewccres(dp, vflag))
				return;
		} else {
			if (parsestatus(dp, &er) != 0)
				return;
		}
		break;

	case NFSPROC_RMDIR:
		printf(" rmdir");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsewccres(dp, vflag))
				return;
		} else {
			if (parsestatus(dp, &er) != 0)
				return;
		}
		break;

	case NFSPROC_RENAME:
		printf(" rename");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(dp, &er)))
				break;
			if (vflag) {
				printf(" from:");
				if (!(dp = parse_wcc_data(dp, vflag)))
					break;
				printf(" to:");
				if (!(dp = parse_wcc_data(dp, vflag)))
					break;
			}
			return;
		} else {
			if (parsestatus(dp, &er) != 0)
				return;
		}
		break;

	case NFSPROC_LINK:
		printf(" link");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (!(dp = parsestatus(dp, &er)))
				break;
			if (vflag) {
				printf(" file POST:");
				if (!(dp = parse_post_op_attr(dp, vflag)))
					break;
				printf(" dir:");
				if (!(dp = parse_wcc_data(dp, vflag)))
					break;
				return;
			}
		} else {
			if (parsestatus(dp, &er) != 0)
				return;
		}
		break;

	case NFSPROC_READDIR:
		printf(" readdir");
		if (!(dp = parserep(rp, length)))
			break;
		if (v3) {
			if (parsev3rddirres(dp, vflag))
				return;
		} else {
			if (parserddires(dp) != 0)
				return;
		}
		break;

	case NFSPROC_READDIRPLUS:
		printf(" readdirplus");
		if (!(dp = parserep(rp, length)))
			break;
		if (parsev3rddirres(dp, vflag))
			return;
		break;

	case NFSPROC_FSSTAT:
		printf(" fsstat");
		dp = parserep(rp, length);
		if (dp != NULL && parsestatfs(dp, v3) != 0)
			return;
		break;

	case NFSPROC_FSINFO:
		printf(" fsinfo");
		dp = parserep(rp, length);
		if (dp != NULL && parsefsinfo(dp) != 0)
			return;
		break;

	case NFSPROC_PATHCONF:
		printf(" pathconf");
		dp = parserep(rp, length);
		if (dp != NULL && parsepathconf(dp) != 0)
			return;
		break;

	case NFSPROC_COMMIT:
		printf(" commit");
		dp = parserep(rp, length);
		if (dp != NULL && parsewccres(dp, vflag) != 0)
			return;
		break;

	default:
		printf(" proc-%u", proc);
		return;
	}
trunc:
	if (!nfserr)
		printf("%s", tstr);
}