print-nfs.c revision 75118
117680Spst/* 239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2075118Sfenner * 2175118Sfenner * $FreeBSD: head/contrib/tcpdump/print-nfs.c 75118 2001-04-03 07:50:46Z fenner $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 2526183Sfennerstatic const char rcsid[] = 2675118Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.87 2000/10/07 05:53:12 itojun Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2975118Sfenner#ifdef HAVE_CONFIG_H 3075118Sfenner#include "config.h" 3175118Sfenner#endif 3275118Sfenner 3317680Spst#include <sys/param.h> 3417680Spst#include <sys/time.h> 3517680Spst#include <sys/socket.h> 3617680Spst 3775118Sfennerstruct mbuf; 3875118Sfennerstruct rtentry; 3917680Spst 4017680Spst#include <netinet/in.h> 4117680Spst 4217680Spst#include <rpc/rpc.h> 4317680Spst 4417680Spst#include <ctype.h> 4526183Sfenner#include <pcap.h> 4617680Spst#include <stdio.h> 4717680Spst#include <string.h> 4817680Spst 4917680Spst#include "interface.h" 5017680Spst#include "addrtoname.h" 5117680Spst 5218976Sdfr#include "nfs.h" 5317680Spst#include "nfsfh.h" 5417680Spst 5575118Sfenner#include "ip.h" 5675118Sfenner#ifdef INET6 5775118Sfenner#include "ip6.h" 5875118Sfenner#endif 5975118Sfenner 6075118Sfennerstatic void nfs_printfh(const u_int32_t *, const u_int); 6175118Sfennerstatic void xid_map_enter(const struct rpc_msg *, const u_char *); 6275118Sfennerstatic int32_t xid_map_find(const struct rpc_msg *, const u_char *, 6375118Sfenner u_int32_t *, u_int32_t *); 6418976Sdfrstatic void interp_reply(const struct rpc_msg *, u_int32_t, u_int32_t, int); 6518976Sdfrstatic const u_int32_t *parse_post_op_attr(const u_int32_t *, int); 6675118Sfennerstatic void print_sattr3(const struct nfsv3_sattr *sa3, int verbose); 6775118Sfennerstatic int print_int64(const u_int32_t *dp, int how); 6875118Sfennerstatic void print_nfsaddr(const u_char *, const char *, const char *); 6917680Spst 7018976Sdfr/* 7118976Sdfr * Mapping of old NFS Version 2 RPC numbers to generic numbers. 7218976Sdfr */ 7318976Sdfru_int32_t nfsv3_procid[NFS_NPROCS] = { 7418976Sdfr NFSPROC_NULL, 7518976Sdfr NFSPROC_GETATTR, 7618976Sdfr NFSPROC_SETATTR, 7718976Sdfr NFSPROC_NOOP, 7818976Sdfr NFSPROC_LOOKUP, 7918976Sdfr NFSPROC_READLINK, 8018976Sdfr NFSPROC_READ, 8118976Sdfr NFSPROC_NOOP, 8218976Sdfr NFSPROC_WRITE, 8318976Sdfr NFSPROC_CREATE, 8418976Sdfr NFSPROC_REMOVE, 8518976Sdfr NFSPROC_RENAME, 8618976Sdfr NFSPROC_LINK, 8718976Sdfr NFSPROC_SYMLINK, 8818976Sdfr NFSPROC_MKDIR, 8918976Sdfr NFSPROC_RMDIR, 9018976Sdfr NFSPROC_READDIR, 9118976Sdfr NFSPROC_FSSTAT, 9218976Sdfr NFSPROC_NOOP, 9318976Sdfr NFSPROC_NOOP, 9418976Sdfr NFSPROC_NOOP, 9518976Sdfr NFSPROC_NOOP, 9618976Sdfr NFSPROC_NOOP, 9718976Sdfr NFSPROC_NOOP, 9818976Sdfr NFSPROC_NOOP, 9918976Sdfr NFSPROC_NOOP 10018976Sdfr}; 10118976Sdfr 10275118Sfenner/* 10375118Sfenner * NFS V2 and V3 status values. 10475118Sfenner * 10575118Sfenner * Some of these come from the RFCs for NFS V2 and V3, with the message 10675118Sfenner * strings taken from the FreeBSD C library "errlst.c". 10775118Sfenner * 10875118Sfenner * Others are errors that are not in the RFC but that I suspect some 10975118Sfenner * NFS servers could return; the values are FreeBSD errno values, as 11075118Sfenner * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS 11175118Sfenner * was primarily BSD-derived. 11275118Sfenner */ 11375118Sfennerstatic struct tok status2str[] = { 11475118Sfenner { 1, "Operation not permitted" }, /* EPERM */ 11575118Sfenner { 2, "No such file or directory" }, /* ENOENT */ 11675118Sfenner { 5, "Input/output error" }, /* EIO */ 11775118Sfenner { 6, "Device not configured" }, /* ENXIO */ 11875118Sfenner { 11, "Resource deadlock avoided" }, /* EDEADLK */ 11975118Sfenner { 12, "Cannot allocate memory" }, /* ENOMEM */ 12075118Sfenner { 13, "Permission denied" }, /* EACCES */ 12175118Sfenner { 17, "File exists" }, /* EEXIST */ 12275118Sfenner { 18, "Cross-device link" }, /* EXDEV */ 12375118Sfenner { 19, "Operation not supported by device" }, /* ENODEV */ 12475118Sfenner { 20, "Not a directory" }, /* ENOTDIR */ 12575118Sfenner { 21, "Is a directory" }, /* EISDIR */ 12675118Sfenner { 22, "Invalid argument" }, /* EINVAL */ 12775118Sfenner { 26, "Text file busy" }, /* ETXTBSY */ 12875118Sfenner { 27, "File too large" }, /* EFBIG */ 12975118Sfenner { 28, "No space left on device" }, /* ENOSPC */ 13075118Sfenner { 30, "Read-only file system" }, /* EROFS */ 13175118Sfenner { 31, "Too many links" }, /* EMLINK */ 13275118Sfenner { 45, "Operation not supported" }, /* EOPNOTSUPP */ 13375118Sfenner { 62, "Too many levels of symbolic links" }, /* ELOOP */ 13475118Sfenner { 63, "File name too long" }, /* ENAMETOOLONG */ 13575118Sfenner { 66, "Directory not empty" }, /* ENOTEMPTY */ 13675118Sfenner { 69, "Disc quota exceeded" }, /* EDQUOT */ 13775118Sfenner { 70, "Stale NFS file handle" }, /* ESTALE */ 13875118Sfenner { 71, "Too many levels of remote in path" }, /* EREMOTE */ 13975118Sfenner { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */ 14075118Sfenner { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */ 14175118Sfenner { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */ 14275118Sfenner { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */ 14375118Sfenner { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */ 14475118Sfenner { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */ 14575118Sfenner { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */ 14675118Sfenner { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */ 14775118Sfenner { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */ 14875118Sfenner { 0, NULL } 14918976Sdfr}; 15018976Sdfr 15175118Sfennerstatic struct tok nfsv3_writemodes[] = { 15275118Sfenner { 0, "unstable" }, 15375118Sfenner { 1, "datasync" }, 15475118Sfenner { 2, "filesync" }, 15575118Sfenner { 0, NULL } 15675118Sfenner}; 15775118Sfenner 15818976Sdfrstatic struct tok type2str[] = { 15918976Sdfr { NFNON, "NON" }, 16018976Sdfr { NFREG, "REG" }, 16118976Sdfr { NFDIR, "DIR" }, 16218976Sdfr { NFBLK, "BLK" }, 16318976Sdfr { NFCHR, "CHR" }, 16418976Sdfr { NFLNK, "LNK" }, 16518976Sdfr { NFFIFO, "FIFO" }, 16618976Sdfr { 0, NULL } 16718976Sdfr}; 16818976Sdfr 16918976Sdfr/* 17018976Sdfr * Print out a 64-bit integer. This appears to be different on each system, 17118976Sdfr * try to make the best of it. The integer stored as 2 consecutive XDR 17218976Sdfr * encoded 32-bit integers, to which a pointer is passed. 17318976Sdfr * 17418976Sdfr * Assume that a system that has INT64_FORMAT defined, has a 64-bit 17518976Sdfr * integer datatype and can print it. 17618976Sdfr */ 17718976Sdfr 17818976Sdfr#define UNSIGNED 0 17918976Sdfr#define SIGNED 1 18018976Sdfr#define HEX 2 18118976Sdfr 18275118Sfennerstatic int print_int64(const u_int32_t *dp, int how) 18318976Sdfr{ 18418976Sdfr#ifdef INT64_FORMAT 18518976Sdfr u_int64_t res; 18618976Sdfr 18718976Sdfr res = ((u_int64_t)ntohl(dp[0]) << 32) | (u_int64_t)ntohl(dp[1]); 18818976Sdfr switch (how) { 18918976Sdfr case SIGNED: 19018976Sdfr printf(INT64_FORMAT, res); 19118976Sdfr break; 19218976Sdfr case UNSIGNED: 19318976Sdfr printf(U_INT64_FORMAT, res); 19418976Sdfr break; 19518976Sdfr case HEX: 19618976Sdfr printf(HEX_INT64_FORMAT, res); 19718976Sdfr break; 19818976Sdfr default: 19918976Sdfr return (0); 20018976Sdfr } 20118976Sdfr#else 20275118Sfenner switch (how) { 20375118Sfenner case SIGNED: 20475118Sfenner case UNSIGNED: 20575118Sfenner case HEX: 20675118Sfenner printf("0x%x%08x", (u_int32_t)ntohl(dp[0]), 20775118Sfenner (u_int32_t)ntohl(dp[1])); 20875118Sfenner break; 20975118Sfenner default: 21075118Sfenner return (0); 21175118Sfenner } 21218976Sdfr#endif 21318976Sdfr return 1; 21418976Sdfr} 21518976Sdfr 21675118Sfennerstatic void 21775118Sfennerprint_nfsaddr(const u_char *bp, const char *s, const char *d) 21875118Sfenner{ 21975118Sfenner struct ip *ip; 22075118Sfenner#ifdef INET6 22175118Sfenner struct ip6_hdr *ip6; 22275118Sfenner char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; 22375118Sfenner#else 22475118Sfenner#ifndef INET_ADDRSTRLEN 22575118Sfenner#define INET_ADDRSTRLEN 16 22675118Sfenner#endif 22775118Sfenner char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN]; 22875118Sfenner#endif 22975118Sfenner 23075118Sfenner srcaddr[0] = dstaddr[0] = '\0'; 23175118Sfenner switch (IP_V((struct ip *)bp)) { 23275118Sfenner case 4: 23375118Sfenner ip = (struct ip *)bp; 23475118Sfenner strlcpy(srcaddr, ipaddr_string(&ip->ip_src), sizeof(srcaddr)); 23575118Sfenner strlcpy(dstaddr, ipaddr_string(&ip->ip_dst), sizeof(dstaddr)); 23675118Sfenner break; 23775118Sfenner#ifdef INET6 23875118Sfenner case 6: 23975118Sfenner ip6 = (struct ip6_hdr *)bp; 24075118Sfenner strlcpy(srcaddr, ip6addr_string(&ip6->ip6_src), 24175118Sfenner sizeof(srcaddr)); 24275118Sfenner strlcpy(dstaddr, ip6addr_string(&ip6->ip6_dst), 24375118Sfenner sizeof(dstaddr)); 24475118Sfenner break; 24575118Sfenner#endif 24675118Sfenner default: 24775118Sfenner strlcpy(srcaddr, "?", sizeof(srcaddr)); 24875118Sfenner strlcpy(dstaddr, "?", sizeof(dstaddr)); 24975118Sfenner break; 25075118Sfenner } 25175118Sfenner 25275118Sfenner (void)printf("%s.%s > %s.%s: ", srcaddr, s, dstaddr, d); 25375118Sfenner} 25475118Sfenner 25518976Sdfrstatic const u_int32_t * 25618976Sdfrparse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3) 25718976Sdfr{ 25875118Sfenner TCHECK(dp[0]); 25918976Sdfr if ((sa3->sa_modeset = ntohl(*dp++))) { 26075118Sfenner TCHECK(dp[0]); 26118976Sdfr sa3->sa_mode = ntohl(*dp++); 26218976Sdfr } 26318976Sdfr 26475118Sfenner TCHECK(dp[0]); 26518976Sdfr if ((sa3->sa_uidset = ntohl(*dp++))) { 26675118Sfenner TCHECK(dp[0]); 26718976Sdfr sa3->sa_uid = ntohl(*dp++); 26818976Sdfr } 26918976Sdfr 27075118Sfenner TCHECK(dp[0]); 27118976Sdfr if ((sa3->sa_gidset = ntohl(*dp++))) { 27275118Sfenner TCHECK(dp[0]); 27318976Sdfr sa3->sa_gid = ntohl(*dp++); 27418976Sdfr } 27518976Sdfr 27675118Sfenner TCHECK(dp[0]); 27718976Sdfr if ((sa3->sa_sizeset = ntohl(*dp++))) { 27875118Sfenner TCHECK(dp[0]); 27918976Sdfr sa3->sa_size = ntohl(*dp++); 28018976Sdfr } 28118976Sdfr 28275118Sfenner TCHECK(dp[0]); 28318976Sdfr if ((sa3->sa_atimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 28475118Sfenner TCHECK(dp[1]); 28518976Sdfr sa3->sa_atime.nfsv3_sec = ntohl(*dp++); 28618976Sdfr sa3->sa_atime.nfsv3_nsec = ntohl(*dp++); 28718976Sdfr } 28818976Sdfr 28975118Sfenner TCHECK(dp[0]); 29018976Sdfr if ((sa3->sa_mtimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 29175118Sfenner TCHECK(dp[1]); 29218976Sdfr sa3->sa_mtime.nfsv3_sec = ntohl(*dp++); 29318976Sdfr sa3->sa_mtime.nfsv3_nsec = ntohl(*dp++); 29418976Sdfr } 29518976Sdfr 29618976Sdfr return dp; 29775118Sfennertrunc: 29875118Sfenner return NULL; 29918976Sdfr} 30018976Sdfr 30175118Sfennerstatic int nfserr; /* true if we error rather than trunc */ 30275118Sfenner 30375118Sfennerstatic void 30418976Sdfrprint_sattr3(const struct nfsv3_sattr *sa3, int verbose) 30518976Sdfr{ 30618976Sdfr if (sa3->sa_modeset) 30718976Sdfr printf(" mode %o", sa3->sa_mode); 30818976Sdfr if (sa3->sa_uidset) 30918976Sdfr printf(" uid %u", sa3->sa_uid); 31018976Sdfr if (sa3->sa_gidset) 31118976Sdfr printf(" gid %u", sa3->sa_gid); 31218976Sdfr if (verbose > 1) { 31318976Sdfr if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 31418976Sdfr printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec, 31518976Sdfr sa3->sa_atime.nfsv3_nsec); 31618976Sdfr if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 31718976Sdfr printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 31818976Sdfr sa3->sa_mtime.nfsv3_nsec); 31918976Sdfr } 32018976Sdfr} 32118976Sdfr 32218976Sdfrvoid 32317680Spstnfsreply_print(register const u_char *bp, u_int length, 32417680Spst register const u_char *bp2) 32517680Spst{ 32617680Spst register const struct rpc_msg *rp; 32718976Sdfr u_int32_t proc, vers; 32875118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 32917680Spst 33026183Sfenner nfserr = 0; /* assume no error */ 33117680Spst rp = (const struct rpc_msg *)bp; 33217680Spst 33375118Sfenner if (!nflag) { 33475118Sfenner strlcpy(srcid, "nfs", sizeof(srcid)); 33575118Sfenner snprintf(dstid, sizeof(dstid), "%u", 33675118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 33775118Sfenner } else { 33875118Sfenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 33975118Sfenner snprintf(dstid, sizeof(dstid), "%u", 34075118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 34175118Sfenner } 34275118Sfenner print_nfsaddr(bp2, srcid, dstid); 34375118Sfenner (void)printf("reply %s %d", 34475118Sfenner ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 34575118Sfenner "ok":"ERR", 34617680Spst length); 34717680Spst 34875118Sfenner if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 34918976Sdfr interp_reply(rp, proc, vers, length); 35017680Spst} 35117680Spst 35217680Spst/* 35317680Spst * Return a pointer to the first file handle in the packet. 35475118Sfenner * If the packet was truncated, return 0. 35517680Spst */ 35617680Spststatic const u_int32_t * 35775118Sfennerparsereq(register const struct rpc_msg *rp, register u_int length) 35817680Spst{ 35926183Sfenner register const u_int32_t *dp; 36017680Spst register u_int len; 36117680Spst 36217680Spst /* 36317680Spst * find the start of the req data (if we captured it) 36417680Spst */ 36526183Sfenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 36626183Sfenner TCHECK(dp[1]); 36726183Sfenner len = ntohl(dp[1]); 36826183Sfenner if (len < length) { 36926183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 37026183Sfenner TCHECK(dp[1]); 37117680Spst len = ntohl(dp[1]); 37226183Sfenner if (len < length) { 37326183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 37426183Sfenner TCHECK2(dp[0], 0); 37526183Sfenner return (dp); 37617680Spst } 37717680Spst } 37826183Sfennertrunc: 37926183Sfenner return (NULL); 38017680Spst} 38117680Spst 38217680Spst/* 38317680Spst * Print out an NFS file handle and return a pointer to following word. 38475118Sfenner * If packet was truncated, return 0. 38517680Spst */ 38617680Spststatic const u_int32_t * 38718976Sdfrparsefh(register const u_int32_t *dp, int v3) 38817680Spst{ 38918976Sdfr int len; 39018976Sdfr 39118976Sdfr if (v3) { 39226183Sfenner TCHECK(dp[0]); 39318976Sdfr len = (int)ntohl(*dp) / 4; 39418976Sdfr dp++; 39518976Sdfr } else 39618976Sdfr len = NFSX_V2FH / 4; 39718976Sdfr 39826183Sfenner if (TTEST2(*dp, len * sizeof(*dp))) { 39918976Sdfr nfs_printfh(dp, len); 40018976Sdfr return (dp + len); 40117680Spst } 40226183Sfennertrunc: 40326183Sfenner return (NULL); 40417680Spst} 40517680Spst 40617680Spst/* 40717680Spst * Print out a file name and return pointer to 32-bit word past it. 40875118Sfenner * If packet was truncated, return 0. 40917680Spst */ 41017680Spststatic const u_int32_t * 41117680Spstparsefn(register const u_int32_t *dp) 41217680Spst{ 41317680Spst register u_int32_t len; 41417680Spst register const u_char *cp; 41517680Spst 41617680Spst /* Bail if we don't have the string length */ 41775118Sfenner TCHECK(*dp); 41817680Spst 41917680Spst /* Fetch string length; convert to host order */ 42017680Spst len = *dp++; 42117680Spst NTOHL(len); 42217680Spst 42375118Sfenner TCHECK2(*dp, ((len + 3) & ~3)); 42475118Sfenner 42517680Spst cp = (u_char *)dp; 42617680Spst /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 42717680Spst dp += ((len + 3) & ~3) / sizeof(*dp); 42817680Spst /* XXX seems like we should be checking the length */ 42926183Sfenner putchar('"'); 43017680Spst (void) fn_printn(cp, len, NULL); 43126183Sfenner putchar('"'); 43217680Spst 43317680Spst return (dp); 43475118Sfennertrunc: 43575118Sfenner return NULL; 43617680Spst} 43717680Spst 43817680Spst/* 43917680Spst * Print out file handle and file name. 44017680Spst * Return pointer to 32-bit word past file name. 44175118Sfenner * If packet was truncated (or there was some other error), return 0. 44217680Spst */ 44317680Spststatic const u_int32_t * 44418976Sdfrparsefhn(register const u_int32_t *dp, int v3) 44517680Spst{ 44618976Sdfr dp = parsefh(dp, v3); 44726183Sfenner if (dp == NULL) 44826183Sfenner return (NULL); 44917680Spst putchar(' '); 45017680Spst return (parsefn(dp)); 45117680Spst} 45217680Spst 45317680Spstvoid 45417680Spstnfsreq_print(register const u_char *bp, u_int length, 45517680Spst register const u_char *bp2) 45617680Spst{ 45717680Spst register const struct rpc_msg *rp; 45817680Spst register const u_int32_t *dp; 45975118Sfenner nfs_type type; 46075118Sfenner int v3; 46175118Sfenner u_int32_t proc; 46218976Sdfr struct nfsv3_sattr sa3; 46375118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 46417680Spst 46526183Sfenner nfserr = 0; /* assume no error */ 46617680Spst rp = (const struct rpc_msg *)bp; 46775118Sfenner if (!nflag) { 46875118Sfenner snprintf(srcid, sizeof(srcid), "%u", 46975118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 47075118Sfenner strlcpy(dstid, "nfs", sizeof(dstid)); 47175118Sfenner } else { 47275118Sfenner snprintf(srcid, sizeof(srcid), "%u", 47375118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 47475118Sfenner snprintf(dstid, sizeof(dstid), "%u", NFS_PORT); 47575118Sfenner } 47675118Sfenner print_nfsaddr(bp2, srcid, dstid); 47775118Sfenner (void)printf("%d", length); 47817680Spst 47975118Sfenner xid_map_enter(rp, bp2); /* record proc number for later on */ 48017680Spst 48118976Sdfr v3 = (ntohl(rp->rm_call.cb_vers) == NFS_VER3); 48218976Sdfr proc = ntohl(rp->rm_call.cb_proc); 48318976Sdfr 48418976Sdfr if (!v3 && proc < NFS_NPROCS) 48518976Sdfr proc = nfsv3_procid[proc]; 48618976Sdfr 48718976Sdfr switch (proc) { 48817680Spst case NFSPROC_NOOP: 48917680Spst printf(" nop"); 49017680Spst return; 49117680Spst case NFSPROC_NULL: 49217680Spst printf(" null"); 49317680Spst return; 49417680Spst 49517680Spst case NFSPROC_GETATTR: 49617680Spst printf(" getattr"); 49775118Sfenner if ((dp = parsereq(rp, length)) != NULL && 49875118Sfenner parsefh(dp, v3) != NULL) 49917680Spst return; 50017680Spst break; 50117680Spst 50217680Spst case NFSPROC_SETATTR: 50317680Spst printf(" setattr"); 50475118Sfenner if ((dp = parsereq(rp, length)) != NULL && 50575118Sfenner parsefh(dp, v3) != NULL) 50617680Spst return; 50717680Spst break; 50817680Spst 50917680Spst case NFSPROC_LOOKUP: 51017680Spst printf(" lookup"); 51175118Sfenner if ((dp = parsereq(rp, length)) != NULL && 51275118Sfenner parsefhn(dp, v3) != NULL) 51317680Spst return; 51417680Spst break; 51517680Spst 51618976Sdfr case NFSPROC_ACCESS: 51718976Sdfr printf(" access"); 51826183Sfenner if ((dp = parsereq(rp, length)) != NULL && 51926183Sfenner (dp = parsefh(dp, v3)) != NULL) { 52075118Sfenner TCHECK(dp[0]); 52175118Sfenner printf(" %04x", (u_int32_t)ntohl(dp[0])); 52218976Sdfr return; 52318976Sdfr } 52418976Sdfr break; 52518976Sdfr 52617680Spst case NFSPROC_READLINK: 52717680Spst printf(" readlink"); 52875118Sfenner if ((dp = parsereq(rp, length)) != NULL && 52975118Sfenner parsefh(dp, v3) != NULL) 53017680Spst return; 53117680Spst break; 53217680Spst 53317680Spst case NFSPROC_READ: 53417680Spst printf(" read"); 53526183Sfenner if ((dp = parsereq(rp, length)) != NULL && 53626183Sfenner (dp = parsefh(dp, v3)) != NULL) { 53718976Sdfr if (v3) { 53875118Sfenner TCHECK(dp[2]); 53975118Sfenner printf(" %u bytes @ ", 54075118Sfenner (u_int32_t) ntohl(dp[2])); 54118976Sdfr print_int64(dp, UNSIGNED); 54218976Sdfr } else { 54375118Sfenner TCHECK(dp[1]); 54475118Sfenner printf(" %u bytes @ %u", 54575118Sfenner (u_int32_t)ntohl(dp[1]), 54675118Sfenner (u_int32_t)ntohl(dp[0])); 54718976Sdfr } 54817680Spst return; 54917680Spst } 55017680Spst break; 55117680Spst 55217680Spst case NFSPROC_WRITE: 55317680Spst printf(" write"); 55426183Sfenner if ((dp = parsereq(rp, length)) != NULL && 55526183Sfenner (dp = parsefh(dp, v3)) != NULL) { 55618976Sdfr if (v3) { 55775118Sfenner TCHECK(dp[4]); 55875118Sfenner printf(" %u bytes @ ", 55975118Sfenner (u_int32_t) ntohl(dp[4])); 56018976Sdfr print_int64(dp, UNSIGNED); 56118976Sdfr if (vflag) { 56218976Sdfr dp += 3; 56375118Sfenner TCHECK(dp[0]); 56418976Sdfr printf(" <%s>", 56575118Sfenner tok2str(nfsv3_writemodes, 56675118Sfenner NULL, ntohl(*dp))); 56718976Sdfr } 56818976Sdfr } else { 56975118Sfenner TCHECK(dp[3]); 57075118Sfenner printf(" %u (%u) bytes @ %u (%u)", 57175118Sfenner (u_int32_t)ntohl(dp[3]), 57275118Sfenner (u_int32_t)ntohl(dp[2]), 57375118Sfenner (u_int32_t)ntohl(dp[1]), 57475118Sfenner (u_int32_t)ntohl(dp[0])); 57518976Sdfr } 57617680Spst return; 57717680Spst } 57817680Spst break; 57917680Spst 58017680Spst case NFSPROC_CREATE: 58117680Spst printf(" create"); 58275118Sfenner if ((dp = parsereq(rp, length)) != NULL && 58375118Sfenner parsefhn(dp, v3) != NULL) 58417680Spst return; 58517680Spst break; 58617680Spst 58718976Sdfr case NFSPROC_MKDIR: 58818976Sdfr printf(" mkdir"); 58975118Sfenner if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) 59018976Sdfr return; 59118976Sdfr break; 59218976Sdfr 59318976Sdfr case NFSPROC_SYMLINK: 59418976Sdfr printf(" symlink"); 59575118Sfenner if ((dp = parsereq(rp, length)) != 0 && 59675118Sfenner (dp = parsefhn(dp, v3)) != 0) { 59775118Sfenner fputs(" ->", stdout); 59875118Sfenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) 59918976Sdfr break; 60075118Sfenner if (parsefn(dp) == 0) 60118976Sdfr break; 60218976Sdfr if (v3 && vflag) 60318976Sdfr print_sattr3(&sa3, vflag); 60418976Sdfr return; 60518976Sdfr } 60618976Sdfr break; 60718976Sdfr 60818976Sdfr case NFSPROC_MKNOD: 60918976Sdfr printf(" mknod"); 61075118Sfenner if ((dp = parsereq(rp, length)) != 0 && 61175118Sfenner (dp = parsefhn(dp, v3)) != 0) { 61275118Sfenner TCHECK(*dp); 61375118Sfenner type = (nfs_type)ntohl(*dp++); 61475118Sfenner if ((dp = parse_sattr3(dp, &sa3)) == 0) 61518976Sdfr break; 61618976Sdfr printf(" %s", tok2str(type2str, "unk-ft %d", type)); 61718976Sdfr if (vflag && (type == NFCHR || type == NFBLK)) { 61875118Sfenner TCHECK(dp[1]); 61975118Sfenner printf(" %u/%u", 62075118Sfenner (u_int32_t)ntohl(dp[0]), 62175118Sfenner (u_int32_t)ntohl(dp[1])); 62218976Sdfr dp += 2; 62318976Sdfr } 62418976Sdfr if (vflag) 62518976Sdfr print_sattr3(&sa3, vflag); 62618976Sdfr return; 62718976Sdfr } 62818976Sdfr break; 62918976Sdfr 63017680Spst case NFSPROC_REMOVE: 63117680Spst printf(" remove"); 63275118Sfenner if ((dp = parsereq(rp, length)) != NULL && 63375118Sfenner parsefhn(dp, v3) != NULL) 63417680Spst return; 63517680Spst break; 63617680Spst 63718976Sdfr case NFSPROC_RMDIR: 63818976Sdfr printf(" rmdir"); 63975118Sfenner if ((dp = parsereq(rp, length)) != NULL && 64075118Sfenner parsefhn(dp, v3) != NULL) 64118976Sdfr return; 64218976Sdfr break; 64318976Sdfr 64417680Spst case NFSPROC_RENAME: 64517680Spst printf(" rename"); 64626183Sfenner if ((dp = parsereq(rp, length)) != NULL && 64726183Sfenner (dp = parsefhn(dp, v3)) != NULL) { 64817680Spst fputs(" ->", stdout); 64926183Sfenner if (parsefhn(dp, v3) != NULL) 65017680Spst return; 65117680Spst } 65217680Spst break; 65317680Spst 65417680Spst case NFSPROC_LINK: 65517680Spst printf(" link"); 65626183Sfenner if ((dp = parsereq(rp, length)) != NULL && 65726183Sfenner (dp = parsefh(dp, v3)) != NULL) { 65817680Spst fputs(" ->", stdout); 65926183Sfenner if (parsefhn(dp, v3) != NULL) 66017680Spst return; 66117680Spst } 66217680Spst break; 66317680Spst 66418976Sdfr case NFSPROC_READDIR: 66518976Sdfr printf(" readdir"); 66626183Sfenner if ((dp = parsereq(rp, length)) != NULL && 66726183Sfenner (dp = parsefh(dp, v3)) != NULL) { 66818976Sdfr if (v3) { 66975118Sfenner TCHECK(dp[4]); 67018976Sdfr /* 67118976Sdfr * We shouldn't really try to interpret the 67218976Sdfr * offset cookie here. 67318976Sdfr */ 67475118Sfenner printf(" %u bytes @ ", 67575118Sfenner (u_int32_t) ntohl(dp[4])); 67618976Sdfr print_int64(dp, SIGNED); 67718976Sdfr if (vflag) 67826183Sfenner printf(" verf %08x%08x", dp[2], 67918976Sdfr dp[3]); 68018976Sdfr } else { 68175118Sfenner TCHECK(dp[1]); 68218976Sdfr /* 68318976Sdfr * Print the offset as signed, since -1 is 68418976Sdfr * common, but offsets > 2^31 aren't. 68518976Sdfr */ 68675118Sfenner printf(" %u bytes @ %d", 68775118Sfenner (u_int32_t)ntohl(dp[1]), 68875118Sfenner (u_int32_t)ntohl(dp[0])); 68918976Sdfr } 69018976Sdfr return; 69117680Spst } 69217680Spst break; 69317680Spst 69418976Sdfr case NFSPROC_READDIRPLUS: 69518976Sdfr printf(" readdirplus"); 69626183Sfenner if ((dp = parsereq(rp, length)) != NULL && 69726183Sfenner (dp = parsefh(dp, v3)) != NULL) { 69875118Sfenner TCHECK(dp[4]); 69918976Sdfr /* 70018976Sdfr * We don't try to interpret the offset 70118976Sdfr * cookie here. 70218976Sdfr */ 70375118Sfenner printf(" %u bytes @ ", (u_int32_t) ntohl(dp[4])); 70418976Sdfr print_int64(dp, SIGNED); 70518976Sdfr if (vflag) 70675118Sfenner printf(" max %u verf %08x%08x", 70775118Sfenner (u_int32_t) ntohl(dp[5]), dp[2], dp[3]); 70817680Spst return; 70918976Sdfr } 71017680Spst break; 71117680Spst 71218976Sdfr case NFSPROC_FSSTAT: 71318976Sdfr printf(" fsstat"); 71475118Sfenner if ((dp = parsereq(rp, length)) != NULL && 71575118Sfenner parsefh(dp, v3) != NULL) 71617680Spst return; 71717680Spst break; 71817680Spst 71918976Sdfr case NFSPROC_FSINFO: 72018976Sdfr printf(" fsinfo"); 72118976Sdfr break; 72218976Sdfr 72318976Sdfr case NFSPROC_PATHCONF: 72418976Sdfr printf(" pathconf"); 72518976Sdfr break; 72618976Sdfr 72718976Sdfr case NFSPROC_COMMIT: 72818976Sdfr printf(" commit"); 72926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 73026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 73175118Sfenner printf(" %u bytes @ ", (u_int32_t) ntohl(dp[2])); 73218976Sdfr print_int64(dp, UNSIGNED); 73317680Spst return; 73417680Spst } 73517680Spst break; 73617680Spst 73717680Spst default: 73875118Sfenner printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc)); 73917680Spst return; 74017680Spst } 74175118Sfenner 74217680Spsttrunc: 74326183Sfenner if (!nfserr) 74426183Sfenner fputs(" [|nfs]", stdout); 74517680Spst} 74617680Spst 74717680Spst/* 74817680Spst * Print out an NFS file handle. 74917680Spst * We assume packet was not truncated before the end of the 75017680Spst * file handle pointed to by dp. 75117680Spst * 75217680Spst * Note: new version (using portable file-handle parser) doesn't produce 75317680Spst * generation number. It probably could be made to do that, with some 75417680Spst * additional hacking on the parser code. 75517680Spst */ 75617680Spststatic void 75775118Sfennernfs_printfh(register const u_int32_t *dp, const u_int len) 75817680Spst{ 75917680Spst my_fsid fsid; 76017680Spst ino_t ino; 76117680Spst char *sfsname = NULL; 76217680Spst 76375118Sfenner Parse_fh((caddr_t*)dp, len, &fsid, &ino, NULL, &sfsname, 0); 76417680Spst 76517680Spst if (sfsname) { 76626183Sfenner /* file system ID is ASCII, not numeric, for this server OS */ 76726183Sfenner static char temp[NFSX_V3FHMAX+1]; 76817680Spst 76926183Sfenner /* Make sure string is null-terminated */ 77026183Sfenner strncpy(temp, sfsname, NFSX_V3FHMAX); 77175118Sfenner temp[sizeof(temp) - 1] = '\0'; 77226183Sfenner /* Remove trailing spaces */ 77326183Sfenner sfsname = strchr(temp, ' '); 77426183Sfenner if (sfsname) 77526183Sfenner *sfsname = 0; 77617680Spst 77775118Sfenner (void)printf(" fh %s/", temp); 77826183Sfenner } else { 77975118Sfenner (void)printf(" fh %d,%d/", 78075118Sfenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); 78117680Spst } 78275118Sfenner 78375118Sfenner if(fsid.Fsid_dev.Minor == 257 && uflag) 78475118Sfenner /* Print the undecoded handle */ 78575118Sfenner (void)printf("%s", fsid.Opaque_Handle); 78675118Sfenner else 78775118Sfenner (void)printf("%ld", (long) ino); 78817680Spst} 78917680Spst 79017680Spst/* 79117680Spst * Maintain a small cache of recent client.XID.server/proc pairs, to allow 79217680Spst * us to match up replies with requests and thus to know how to parse 79317680Spst * the reply. 79417680Spst */ 79517680Spst 79617680Spststruct xid_map_entry { 79775118Sfenner u_int32_t xid; /* transaction ID (net order) */ 79875118Sfenner int ipver; /* IP version (4 or 6) */ 79975118Sfenner#ifdef INET6 80075118Sfenner struct in6_addr client; /* client IP address (net order) */ 80175118Sfenner struct in6_addr server; /* server IP address (net order) */ 80275118Sfenner#else 80317680Spst struct in_addr client; /* client IP address (net order) */ 80417680Spst struct in_addr server; /* server IP address (net order) */ 80575118Sfenner#endif 80675118Sfenner u_int32_t proc; /* call proc number (host order) */ 80775118Sfenner u_int32_t vers; /* program version (host order) */ 80817680Spst}; 80917680Spst 81017680Spst/* 81117680Spst * Map entries are kept in an array that we manage as a ring; 81217680Spst * new entries are always added at the tail of the ring. Initially, 81317680Spst * all the entries are zero and hence don't match anything. 81417680Spst */ 81517680Spst 81617680Spst#define XIDMAPSIZE 64 81717680Spst 81817680Spststruct xid_map_entry xid_map[XIDMAPSIZE]; 81917680Spst 82017680Spstint xid_map_next = 0; 82117680Spstint xid_map_hint = 0; 82217680Spst 82317680Spststatic void 82475118Sfennerxid_map_enter(const struct rpc_msg *rp, const u_char *bp) 82517680Spst{ 82675118Sfenner struct ip *ip = NULL; 82775118Sfenner#ifdef INET6 82875118Sfenner struct ip6_hdr *ip6 = NULL; 82975118Sfenner#endif 83017680Spst struct xid_map_entry *xmep; 83117680Spst 83275118Sfenner switch (IP_V((struct ip *)bp)) { 83375118Sfenner case 4: 83475118Sfenner ip = (struct ip *)bp; 83575118Sfenner break; 83675118Sfenner#ifdef INET6 83775118Sfenner case 6: 83875118Sfenner ip6 = (struct ip6_hdr *)bp; 83975118Sfenner break; 84075118Sfenner#endif 84175118Sfenner default: 84275118Sfenner return; 84375118Sfenner } 84475118Sfenner 84517680Spst xmep = &xid_map[xid_map_next]; 84617680Spst 84717680Spst if (++xid_map_next >= XIDMAPSIZE) 84817680Spst xid_map_next = 0; 84917680Spst 85017680Spst xmep->xid = rp->rm_xid; 85175118Sfenner if (ip) { 85275118Sfenner xmep->ipver = 4; 85375118Sfenner memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 85475118Sfenner memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 85575118Sfenner } 85675118Sfenner#ifdef INET6 85775118Sfenner else if (ip6) { 85875118Sfenner xmep->ipver = 6; 85975118Sfenner memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 86075118Sfenner memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 86175118Sfenner } 86275118Sfenner#endif 86317680Spst xmep->proc = ntohl(rp->rm_call.cb_proc); 86418976Sdfr xmep->vers = ntohl(rp->rm_call.cb_vers); 86517680Spst} 86617680Spst 86726183Sfenner/* 86826183Sfenner * Returns 0 and puts NFSPROC_xxx in proc return and 86926183Sfenner * version in vers return, or returns -1 on failure 87026183Sfenner */ 87118976Sdfrstatic int 87275118Sfennerxid_map_find(const struct rpc_msg *rp, const u_char *bp, u_int32_t *proc, 87318976Sdfr u_int32_t *vers) 87417680Spst{ 87517680Spst int i; 87617680Spst struct xid_map_entry *xmep; 87717680Spst u_int32_t xid = rp->rm_xid; 87875118Sfenner struct ip *ip = (struct ip *)bp; 87975118Sfenner#ifdef INET6 88075118Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 88175118Sfenner#endif 88275118Sfenner int cmp; 88317680Spst 88417680Spst /* Start searching from where we last left off */ 88575118Sfenner i = xid_map_hint; 88617680Spst do { 88717680Spst xmep = &xid_map[i]; 88875118Sfenner cmp = 1; 88975118Sfenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 89075118Sfenner goto nextitem; 89175118Sfenner switch (xmep->ipver) { 89275118Sfenner case 4: 89375118Sfenner if (memcmp(&ip->ip_src, &xmep->server, 89475118Sfenner sizeof(ip->ip_src)) != 0 || 89575118Sfenner memcmp(&ip->ip_dst, &xmep->client, 89675118Sfenner sizeof(ip->ip_dst)) != 0) { 89775118Sfenner cmp = 0; 89875118Sfenner } 89975118Sfenner break; 90075118Sfenner#ifdef INET6 90175118Sfenner case 6: 90275118Sfenner if (memcmp(&ip6->ip6_src, &xmep->server, 90375118Sfenner sizeof(ip6->ip6_src)) != 0 || 90475118Sfenner memcmp(&ip6->ip6_dst, &xmep->client, 90575118Sfenner sizeof(ip6->ip6_dst)) != 0) { 90675118Sfenner cmp = 0; 90775118Sfenner } 90875118Sfenner break; 90975118Sfenner#endif 91075118Sfenner default: 91175118Sfenner cmp = 0; 91275118Sfenner break; 91375118Sfenner } 91475118Sfenner if (cmp) { 91517680Spst /* match */ 91617680Spst xid_map_hint = i; 91718976Sdfr *proc = xmep->proc; 91818976Sdfr *vers = xmep->vers; 91918976Sdfr return 0; 92017680Spst } 92175118Sfenner nextitem: 92217680Spst if (++i >= XIDMAPSIZE) 92317680Spst i = 0; 92417680Spst } while (i != xid_map_hint); 92517680Spst 92617680Spst /* search failed */ 92775118Sfenner return (-1); 92817680Spst} 92917680Spst 93017680Spst/* 93117680Spst * Routines for parsing reply packets 93217680Spst */ 93317680Spst 93417680Spst/* 93517680Spst * Return a pointer to the beginning of the actual results. 93675118Sfenner * If the packet was truncated, return 0. 93717680Spst */ 93817680Spststatic const u_int32_t * 93975118Sfennerparserep(register const struct rpc_msg *rp, register u_int length) 94017680Spst{ 94117680Spst register const u_int32_t *dp; 94275118Sfenner u_int len; 94317680Spst enum accept_stat astat; 94417680Spst 94517680Spst /* 94617680Spst * Portability note: 94717680Spst * Here we find the address of the ar_verf credentials. 94817680Spst * Originally, this calculation was 94917680Spst * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 95017680Spst * On the wire, the rp_acpt field starts immediately after 95117680Spst * the (32 bit) rp_stat field. However, rp_acpt (which is a 95217680Spst * "struct accepted_reply") contains a "struct opaque_auth", 95317680Spst * whose internal representation contains a pointer, so on a 95417680Spst * 64-bit machine the compiler inserts 32 bits of padding 95517680Spst * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 95617680Spst * the internal representation to parse the on-the-wire 95717680Spst * representation. Instead, we skip past the rp_stat field, 95817680Spst * which is an "enum" and so occupies one 32-bit word. 95917680Spst */ 96017680Spst dp = ((const u_int32_t *)&rp->rm_reply) + 1; 96175118Sfenner TCHECK(dp[1]); 96217680Spst len = ntohl(dp[1]); 96317680Spst if (len >= length) 96426183Sfenner return (NULL); 96517680Spst /* 96617680Spst * skip past the ar_verf credentials. 96717680Spst */ 96817680Spst dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 96926183Sfenner TCHECK2(dp[0], 0); 97017680Spst 97117680Spst /* 97217680Spst * now we can check the ar_stat field 97317680Spst */ 97417680Spst astat = ntohl(*(enum accept_stat *)dp); 97517680Spst switch (astat) { 97617680Spst 97717680Spst case SUCCESS: 97817680Spst break; 97917680Spst 98017680Spst case PROG_UNAVAIL: 98117680Spst printf(" PROG_UNAVAIL"); 98226183Sfenner nfserr = 1; /* suppress trunc string */ 98326183Sfenner return (NULL); 98417680Spst 98517680Spst case PROG_MISMATCH: 98617680Spst printf(" PROG_MISMATCH"); 98726183Sfenner nfserr = 1; /* suppress trunc string */ 98826183Sfenner return (NULL); 98917680Spst 99017680Spst case PROC_UNAVAIL: 99117680Spst printf(" PROC_UNAVAIL"); 99226183Sfenner nfserr = 1; /* suppress trunc string */ 99326183Sfenner return (NULL); 99417680Spst 99517680Spst case GARBAGE_ARGS: 99617680Spst printf(" GARBAGE_ARGS"); 99726183Sfenner nfserr = 1; /* suppress trunc string */ 99826183Sfenner return (NULL); 99917680Spst 100017680Spst case SYSTEM_ERR: 100117680Spst printf(" SYSTEM_ERR"); 100226183Sfenner nfserr = 1; /* suppress trunc string */ 100326183Sfenner return (NULL); 100417680Spst 100517680Spst default: 100617680Spst printf(" ar_stat %d", astat); 100726183Sfenner nfserr = 1; /* suppress trunc string */ 100826183Sfenner return (NULL); 100917680Spst } 101017680Spst /* successful return */ 101175118Sfenner TCHECK2(*dp, sizeof(astat)); 101275118Sfenner return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 101326183Sfennertrunc: 101475118Sfenner return (0); 101517680Spst} 101617680Spst 101717680Spststatic const u_int32_t * 101818976Sdfrparsestatus(const u_int32_t *dp, int *er) 101917680Spst{ 102075118Sfenner int errnum; 102117680Spst 102226183Sfenner TCHECK(dp[0]); 102375118Sfenner 102426183Sfenner errnum = ntohl(dp[0]); 102518976Sdfr if (er) 102626183Sfenner *er = errnum; 102726183Sfenner if (errnum != 0) { 102826183Sfenner if (!qflag) 102975118Sfenner printf(" ERROR: %s", 103075118Sfenner tok2str(status2str, "unk %d", errnum)); 103126183Sfenner nfserr = 1; 103226183Sfenner return (NULL); 103317680Spst } 103417680Spst return (dp + 1); 103526183Sfennertrunc: 103675118Sfenner return NULL; 103717680Spst} 103817680Spst 103917680Spststatic const u_int32_t * 104018976Sdfrparsefattr(const u_int32_t *dp, int verbose, int v3) 104117680Spst{ 104218976Sdfr const struct nfs_fattr *fap; 104317680Spst 104418976Sdfr fap = (const struct nfs_fattr *)dp; 104526184Sfenner TCHECK(fap->fa_gid); 104617680Spst if (verbose) { 104775118Sfenner printf(" %s %o ids %d/%d", 104875118Sfenner tok2str(type2str, "unk-ft %d ", 104975118Sfenner (u_int32_t)ntohl(fap->fa_type)), 105075118Sfenner (u_int32_t)ntohl(fap->fa_mode), 105175118Sfenner (u_int32_t)ntohl(fap->fa_uid), 105275118Sfenner (u_int32_t) ntohl(fap->fa_gid)); 105318976Sdfr if (v3) { 105426184Sfenner TCHECK(fap->fa3_size); 105518976Sdfr printf(" sz "); 105618976Sdfr print_int64((u_int32_t *)&fap->fa3_size, UNSIGNED); 105718976Sdfr putchar(' '); 105826184Sfenner } else { 105926184Sfenner TCHECK(fap->fa2_size); 106075118Sfenner printf(" sz %d ", (u_int32_t) ntohl(fap->fa2_size)); 106118976Sdfr } 106217680Spst } 106317680Spst /* print lots more stuff */ 106417680Spst if (verbose > 1) { 106518976Sdfr if (v3) { 106626184Sfenner TCHECK(fap->fa3_ctime); 106775118Sfenner printf("nlink %d rdev %d/%d ", 106875118Sfenner (u_int32_t)ntohl(fap->fa_nlink), 106975118Sfenner (u_int32_t) ntohl(fap->fa3_rdev.specdata1), 107075118Sfenner (u_int32_t) ntohl(fap->fa3_rdev.specdata2)); 107118976Sdfr printf("fsid "); 107218976Sdfr print_int64((u_int32_t *)&fap->fa2_fsid, HEX); 107318976Sdfr printf(" nodeid "); 107418976Sdfr print_int64((u_int32_t *)&fap->fa2_fileid, HEX); 107575118Sfenner printf(" a/m/ctime %u.%06u ", 107675118Sfenner (u_int32_t) ntohl(fap->fa3_atime.nfsv3_sec), 107775118Sfenner (u_int32_t) ntohl(fap->fa3_atime.nfsv3_nsec)); 107875118Sfenner printf("%u.%06u ", 107975118Sfenner (u_int32_t) ntohl(fap->fa3_mtime.nfsv3_sec), 108075118Sfenner (u_int32_t) ntohl(fap->fa3_mtime.nfsv3_nsec)); 108175118Sfenner printf("%u.%06u ", 108275118Sfenner (u_int32_t) ntohl(fap->fa3_ctime.nfsv3_sec), 108375118Sfenner (u_int32_t) ntohl(fap->fa3_ctime.nfsv3_nsec)); 108418976Sdfr } else { 108526184Sfenner TCHECK(fap->fa2_ctime); 108675118Sfenner printf("nlink %d rdev %x fsid %x nodeid %x a/m/ctime ", 108775118Sfenner (u_int32_t) ntohl(fap->fa_nlink), 108875118Sfenner (u_int32_t) ntohl(fap->fa2_rdev), 108975118Sfenner (u_int32_t) ntohl(fap->fa2_fsid), 109075118Sfenner (u_int32_t) ntohl(fap->fa2_fileid)); 109175118Sfenner printf("%u.%06u ", 109275118Sfenner (u_int32_t) ntohl(fap->fa2_atime.nfsv2_sec), 109375118Sfenner (u_int32_t) ntohl(fap->fa2_atime.nfsv2_usec)); 109475118Sfenner printf("%u.%06u ", 109575118Sfenner (u_int32_t) ntohl(fap->fa2_mtime.nfsv2_sec), 109675118Sfenner (u_int32_t) ntohl(fap->fa2_mtime.nfsv2_usec)); 109775118Sfenner printf("%u.%06u ", 109875118Sfenner (u_int32_t) ntohl(fap->fa2_ctime.nfsv2_sec), 109975118Sfenner (u_int32_t) ntohl(fap->fa2_ctime.nfsv2_usec)); 110018976Sdfr } 110117680Spst } 110218976Sdfr return ((const u_int32_t *)((unsigned char *)dp + 110318976Sdfr (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 110426184Sfennertrunc: 110526184Sfenner return (NULL); 110617680Spst} 110717680Spst 110817680Spststatic int 110918976Sdfrparseattrstat(const u_int32_t *dp, int verbose, int v3) 111017680Spst{ 111118976Sdfr int er; 111218976Sdfr 111318976Sdfr dp = parsestatus(dp, &er); 111418976Sdfr if (dp == NULL || er) 111517680Spst return (0); 111617680Spst 111726183Sfenner return (parsefattr(dp, verbose, v3) != NULL); 111817680Spst} 111917680Spst 112017680Spststatic int 112117680Spstparsediropres(const u_int32_t *dp) 112217680Spst{ 112318976Sdfr int er; 112418976Sdfr 112575118Sfenner if (!(dp = parsestatus(dp, &er)) || er) 112617680Spst return (0); 112717680Spst 112818976Sdfr dp = parsefh(dp, 0); 112917680Spst if (dp == NULL) 113017680Spst return (0); 113117680Spst 113218976Sdfr return (parsefattr(dp, vflag, 0) != NULL); 113317680Spst} 113417680Spst 113517680Spststatic int 113618976Sdfrparselinkres(const u_int32_t *dp, int v3) 113717680Spst{ 113818976Sdfr int er; 113918976Sdfr 114018976Sdfr dp = parsestatus(dp, &er); 114118976Sdfr if (dp == NULL || er) 114217680Spst return(0); 114375118Sfenner if (v3 && !(dp = parse_post_op_attr(dp, vflag))) 114418976Sdfr return (0); 114517680Spst putchar(' '); 114617680Spst return (parsefn(dp) != NULL); 114717680Spst} 114817680Spst 114917680Spststatic int 115018976Sdfrparsestatfs(const u_int32_t *dp, int v3) 115117680Spst{ 115218976Sdfr const struct nfs_statfs *sfsp; 115318976Sdfr int er; 115417680Spst 115518976Sdfr dp = parsestatus(dp, &er); 115618976Sdfr if (dp == NULL || (!v3 && er)) 115775118Sfenner return (0); 115817680Spst 115918976Sdfr if (qflag) 116018976Sdfr return(1); 116118976Sdfr 116218976Sdfr if (v3) { 116318976Sdfr if (vflag) 116418976Sdfr printf(" POST:"); 116575118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 116618976Sdfr return (0); 116717680Spst } 116817680Spst 116926184Sfenner TCHECK2(dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 117018976Sdfr 117118976Sdfr sfsp = (const struct nfs_statfs *)dp; 117218976Sdfr 117318976Sdfr if (v3) { 117418976Sdfr printf(" tbytes "); 117518976Sdfr print_int64((u_int32_t *)&sfsp->sf_tbytes, UNSIGNED); 117618976Sdfr printf(" fbytes "); 117718976Sdfr print_int64((u_int32_t *)&sfsp->sf_fbytes, UNSIGNED); 117818976Sdfr printf(" abytes "); 117918976Sdfr print_int64((u_int32_t *)&sfsp->sf_abytes, UNSIGNED); 118018976Sdfr if (vflag) { 118118976Sdfr printf(" tfiles "); 118218976Sdfr print_int64((u_int32_t *)&sfsp->sf_tfiles, UNSIGNED); 118318976Sdfr printf(" ffiles "); 118418976Sdfr print_int64((u_int32_t *)&sfsp->sf_ffiles, UNSIGNED); 118518976Sdfr printf(" afiles "); 118618976Sdfr print_int64((u_int32_t *)&sfsp->sf_afiles, UNSIGNED); 118775118Sfenner printf(" invar %u", 118875118Sfenner (u_int32_t) ntohl(sfsp->sf_invarsec)); 118918976Sdfr } 119018976Sdfr } else { 119175118Sfenner printf(" tsize %d bsize %d blocks %d bfree %d bavail %d", 119275118Sfenner (u_int32_t)ntohl(sfsp->sf_tsize), 119375118Sfenner (u_int32_t)ntohl(sfsp->sf_bsize), 119475118Sfenner (u_int32_t)ntohl(sfsp->sf_blocks), 119575118Sfenner (u_int32_t)ntohl(sfsp->sf_bfree), 119675118Sfenner (u_int32_t)ntohl(sfsp->sf_bavail)); 119718976Sdfr } 119818976Sdfr 119917680Spst return (1); 120026184Sfennertrunc: 120126184Sfenner return (0); 120217680Spst} 120317680Spst 120417680Spststatic int 120517680Spstparserddires(const u_int32_t *dp) 120617680Spst{ 120718976Sdfr int er; 120818976Sdfr 120918976Sdfr dp = parsestatus(dp, &er); 121075118Sfenner if (dp == 0 || er) 121117680Spst return (0); 121218976Sdfr if (qflag) 121318976Sdfr return (1); 121418976Sdfr 121526184Sfenner TCHECK(dp[2]); 121675118Sfenner printf(" offset %x size %d ", 121775118Sfenner (u_int32_t)ntohl(dp[0]), (u_int32_t)ntohl(dp[1])); 121818976Sdfr if (dp[2] != 0) 121975118Sfenner printf(" eof"); 122018976Sdfr 122118976Sdfr return (1); 122226184Sfennertrunc: 122326184Sfenner return (0); 122418976Sdfr} 122518976Sdfr 122618976Sdfrstatic const u_int32_t * 122718976Sdfrparse_wcc_attr(const u_int32_t *dp) 122818976Sdfr{ 122918976Sdfr printf(" sz "); 123018976Sdfr print_int64(dp, UNSIGNED); 123175118Sfenner printf(" mtime %u.%06u ctime %u.%06u", 123275118Sfenner (u_int32_t)ntohl(dp[2]), (u_int32_t)ntohl(dp[3]), 123375118Sfenner (u_int32_t)ntohl(dp[4]), (u_int32_t)ntohl(dp[5])); 123418976Sdfr return (dp + 6); 123518976Sdfr} 123618976Sdfr 123718976Sdfr/* 123818976Sdfr * Pre operation attributes. Print only if vflag > 1. 123918976Sdfr */ 124018976Sdfrstatic const u_int32_t * 124118976Sdfrparse_pre_op_attr(const u_int32_t *dp, int verbose) 124218976Sdfr{ 124326184Sfenner TCHECK(dp[0]); 124418976Sdfr if (!ntohl(dp[0])) 124518976Sdfr return (dp + 1); 124618976Sdfr dp++; 124726184Sfenner TCHECK2(dp, 24); 124818976Sdfr if (verbose > 1) { 124918976Sdfr return parse_wcc_attr(dp); 125018976Sdfr } else { 125118976Sdfr /* If not verbose enough, just skip over wcc_attr */ 125218976Sdfr return (dp + 6); 125317680Spst } 125426184Sfennertrunc: 125526184Sfenner return (NULL); 125618976Sdfr} 125717680Spst 125818976Sdfr/* 125918976Sdfr * Post operation attributes are printed if vflag >= 1 126018976Sdfr */ 126118976Sdfrstatic const u_int32_t * 126218976Sdfrparse_post_op_attr(const u_int32_t *dp, int verbose) 126318976Sdfr{ 126426184Sfenner TCHECK(dp[0]); 126518976Sdfr if (!ntohl(dp[0])) 126618976Sdfr return (dp + 1); 126718976Sdfr dp++; 126818976Sdfr if (verbose) { 126918976Sdfr return parsefattr(dp, verbose, 1); 127018976Sdfr } else 127118976Sdfr return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 127226184Sfennertrunc: 127326184Sfenner return (NULL); 127418976Sdfr} 127518976Sdfr 127618976Sdfrstatic const u_int32_t * 127718976Sdfrparse_wcc_data(const u_int32_t *dp, int verbose) 127818976Sdfr{ 127918976Sdfr if (verbose > 1) 128018976Sdfr printf(" PRE:"); 128175118Sfenner if (!(dp = parse_pre_op_attr(dp, verbose))) 128275118Sfenner return (0); 128318976Sdfr 128418976Sdfr if (verbose) 128518976Sdfr printf(" POST:"); 128618976Sdfr return parse_post_op_attr(dp, verbose); 128718976Sdfr} 128818976Sdfr 128918976Sdfrstatic const u_int32_t * 129018976Sdfrparsecreateopres(const u_int32_t *dp, int verbose) 129118976Sdfr{ 129218976Sdfr int er; 129318976Sdfr 129475118Sfenner if (!(dp = parsestatus(dp, &er))) 129575118Sfenner return (0); 129618976Sdfr if (er) 129718976Sdfr dp = parse_wcc_data(dp, verbose); 129818976Sdfr else { 129926184Sfenner TCHECK(dp[0]); 130018976Sdfr if (!ntohl(dp[0])) 130118976Sdfr return (dp + 1); 130218976Sdfr dp++; 130375118Sfenner if (!(dp = parsefh(dp, 1))) 130475118Sfenner return (0); 130518976Sdfr if (verbose) { 130675118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 130775118Sfenner return (0); 130818976Sdfr if (vflag > 1) { 130918976Sdfr printf("dir attr:"); 131018976Sdfr dp = parse_wcc_data(dp, verbose); 131118976Sdfr } 131218976Sdfr } 131318976Sdfr } 131418976Sdfr return (dp); 131526184Sfennertrunc: 131626184Sfenner return (NULL); 131718976Sdfr} 131818976Sdfr 131918976Sdfrstatic int 132018976Sdfrparsewccres(const u_int32_t *dp, int verbose) 132118976Sdfr{ 132218976Sdfr int er; 132318976Sdfr 132475118Sfenner if (!(dp = parsestatus(dp, &er))) 132518976Sdfr return (0); 132675118Sfenner return parse_wcc_data(dp, verbose) != 0; 132718976Sdfr} 132818976Sdfr 132918976Sdfrstatic const u_int32_t * 133018976Sdfrparsev3rddirres(const u_int32_t *dp, int verbose) 133118976Sdfr{ 133218976Sdfr int er; 133318976Sdfr 133475118Sfenner if (!(dp = parsestatus(dp, &er))) 133575118Sfenner return (0); 133618976Sdfr if (vflag) 133718976Sdfr printf(" POST:"); 133875118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 133975118Sfenner return (0); 134018976Sdfr if (er) 134118976Sdfr return dp; 134218976Sdfr if (vflag) { 134326184Sfenner TCHECK(dp[1]); 134426183Sfenner printf(" verf %08x%08x", dp[0], dp[1]); 134518976Sdfr dp += 2; 134618976Sdfr } 134718976Sdfr return dp; 134826184Sfennertrunc: 134926184Sfenner return (NULL); 135018976Sdfr} 135118976Sdfr 135218976Sdfrstatic int 135318976Sdfrparsefsinfo(const u_int32_t *dp) 135418976Sdfr{ 135518976Sdfr struct nfsv3_fsinfo *sfp; 135618976Sdfr int er; 135718976Sdfr 135875118Sfenner if (!(dp = parsestatus(dp, &er))) 135918976Sdfr return (0); 136018976Sdfr if (vflag) 136118976Sdfr printf(" POST:"); 136275118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 136318976Sdfr return (0); 136418976Sdfr if (er) 136518976Sdfr return (1); 136618976Sdfr 136718976Sdfr sfp = (struct nfsv3_fsinfo *)dp; 136826184Sfenner TCHECK(*sfp); 136975118Sfenner printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 137075118Sfenner (u_int32_t) ntohl(sfp->fs_rtmax), 137175118Sfenner (u_int32_t) ntohl(sfp->fs_rtpref), 137275118Sfenner (u_int32_t) ntohl(sfp->fs_wtmax), 137375118Sfenner (u_int32_t) ntohl(sfp->fs_wtpref), 137475118Sfenner (u_int32_t) ntohl(sfp->fs_dtpref)); 137518976Sdfr if (vflag) { 137675118Sfenner printf(" rtmult %u wtmult %u maxfsz ", 137775118Sfenner (u_int32_t) ntohl(sfp->fs_rtmult), 137875118Sfenner (u_int32_t) ntohl(sfp->fs_wtmult)); 137918976Sdfr print_int64((u_int32_t *)&sfp->fs_maxfilesize, UNSIGNED); 138075118Sfenner printf(" delta %u.%06u ", 138175118Sfenner (u_int32_t) ntohl(sfp->fs_timedelta.nfsv3_sec), 138275118Sfenner (u_int32_t) ntohl(sfp->fs_timedelta.nfsv3_nsec)); 138318976Sdfr } 138475118Sfenner return (0); 138575118Sfennertrunc: 138617680Spst return (1); 138718976Sdfr} 138818976Sdfr 138918976Sdfrstatic int 139018976Sdfrparsepathconf(const u_int32_t *dp) 139118976Sdfr{ 139218976Sdfr int er; 139318976Sdfr struct nfsv3_pathconf *spp; 139418976Sdfr 139575118Sfenner if (!(dp = parsestatus(dp, &er))) 139618976Sdfr return (0); 139718976Sdfr if (vflag) 139818976Sdfr printf(" POST:"); 139975118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 140018976Sdfr return (0); 140118976Sdfr if (er) 140218976Sdfr return (1); 140318976Sdfr 140418976Sdfr spp = (struct nfsv3_pathconf *)dp; 140526184Sfenner TCHECK(*spp); 140618976Sdfr 140775118Sfenner printf(" linkmax %u namemax %u %s %s %s %s", 140875118Sfenner (u_int32_t) ntohl(spp->pc_linkmax), 140975118Sfenner (u_int32_t) ntohl(spp->pc_namemax), 141018976Sdfr ntohl(spp->pc_notrunc) ? "notrunc" : "", 141118976Sdfr ntohl(spp->pc_chownrestricted) ? "chownres" : "", 141218976Sdfr ntohl(spp->pc_caseinsensitive) ? "igncase" : "", 141318976Sdfr ntohl(spp->pc_casepreserving) ? "keepcase" : ""); 141475118Sfenner return (0); 141575118Sfennertrunc: 141626184Sfenner return (1); 141717680Spst} 141875118Sfenner 141917680Spststatic void 142018976Sdfrinterp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 142117680Spst{ 142217680Spst register const u_int32_t *dp; 142318976Sdfr register int v3; 142418976Sdfr int er; 142517680Spst 142618976Sdfr v3 = (vers == NFS_VER3); 142718976Sdfr 142818976Sdfr if (!v3 && proc < NFS_NPROCS) 142918976Sdfr proc = nfsv3_procid[proc]; 143018976Sdfr 143117680Spst switch (proc) { 143217680Spst 143317680Spst case NFSPROC_NOOP: 143417680Spst printf(" nop"); 143517680Spst return; 143618976Sdfr 143717680Spst case NFSPROC_NULL: 143817680Spst printf(" null"); 143917680Spst return; 144017680Spst 144117680Spst case NFSPROC_GETATTR: 144217680Spst printf(" getattr"); 144317680Spst dp = parserep(rp, length); 144426183Sfenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 144517680Spst return; 144617680Spst break; 144717680Spst 144817680Spst case NFSPROC_SETATTR: 144917680Spst printf(" setattr"); 145075118Sfenner if (!(dp = parserep(rp, length))) 145117680Spst return; 145218976Sdfr if (v3) { 145375118Sfenner if (parsewccres(dp, vflag)) 145418976Sdfr return; 145518976Sdfr } else { 145618976Sdfr if (parseattrstat(dp, !qflag, 0) != 0) 145718976Sdfr return; 145818976Sdfr } 145917680Spst break; 146017680Spst 146117680Spst case NFSPROC_LOOKUP: 146217680Spst printf(" lookup"); 146375118Sfenner if (!(dp = parserep(rp, length))) 146418976Sdfr break; 146518976Sdfr if (v3) { 146675118Sfenner if (!(dp = parsestatus(dp, &er))) 146718976Sdfr break; 146818976Sdfr if (er) { 146918976Sdfr if (vflag > 1) { 147018976Sdfr printf(" post dattr:"); 147118976Sdfr dp = parse_post_op_attr(dp, vflag); 147218976Sdfr } 147318976Sdfr } else { 147475118Sfenner if (!(dp = parsefh(dp, v3))) 147518976Sdfr break; 147675118Sfenner if ((dp = parse_post_op_attr(dp, vflag)) && 147775118Sfenner vflag > 1) { 147818976Sdfr printf(" post dattr:"); 147918976Sdfr dp = parse_post_op_attr(dp, vflag); 148018976Sdfr } 148118976Sdfr } 148275118Sfenner if (dp) 148318976Sdfr return; 148418976Sdfr } else { 148518976Sdfr if (parsediropres(dp) != 0) 148618976Sdfr return; 148718976Sdfr } 148817680Spst break; 148917680Spst 149018976Sdfr case NFSPROC_ACCESS: 149118976Sdfr printf(" access"); 149218976Sdfr dp = parserep(rp, length); 149375118Sfenner if (!(dp = parsestatus(dp, &er))) 149418976Sdfr break; 149518976Sdfr if (vflag) 149618976Sdfr printf(" attr:"); 149775118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 149818976Sdfr break; 149918976Sdfr if (!er) 150075118Sfenner printf(" c %04x", (u_int32_t)ntohl(dp[0])); 150118976Sdfr return; 150218976Sdfr 150317680Spst case NFSPROC_READLINK: 150417680Spst printf(" readlink"); 150517680Spst dp = parserep(rp, length); 150626183Sfenner if (dp != NULL && parselinkres(dp, v3) != 0) 150717680Spst return; 150817680Spst break; 150917680Spst 151017680Spst case NFSPROC_READ: 151117680Spst printf(" read"); 151275118Sfenner if (!(dp = parserep(rp, length))) 151318976Sdfr break; 151418976Sdfr if (v3) { 151575118Sfenner if (!(dp = parsestatus(dp, &er))) 151618976Sdfr break; 151775118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 151818976Sdfr break; 151918976Sdfr if (er) 152018976Sdfr return; 152118976Sdfr if (vflag) { 152275118Sfenner TCHECK(dp[1]); 152375118Sfenner printf("%u bytes", (u_int32_t) ntohl(dp[0])); 152418976Sdfr if (ntohl(dp[1])) 152518976Sdfr printf(" EOF"); 152618976Sdfr } 152717680Spst return; 152818976Sdfr } else { 152918976Sdfr if (parseattrstat(dp, vflag, 0) != 0) 153018976Sdfr return; 153118976Sdfr } 153217680Spst break; 153317680Spst 153417680Spst case NFSPROC_WRITE: 153517680Spst printf(" write"); 153675118Sfenner if (!(dp = parserep(rp, length))) 153718976Sdfr break; 153818976Sdfr if (v3) { 153975118Sfenner if (!(dp = parsestatus(dp, &er))) 154018976Sdfr break; 154175118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 154218976Sdfr break; 154318976Sdfr if (er) 154418976Sdfr return; 154518976Sdfr if (vflag) { 154675118Sfenner TCHECK(dp[0]); 154775118Sfenner printf("%u bytes", (u_int32_t) ntohl(dp[0])); 154818976Sdfr if (vflag > 1) { 154975118Sfenner TCHECK(dp[1]); 155018976Sdfr printf(" <%s>", 155175118Sfenner tok2str(nfsv3_writemodes, 155275118Sfenner NULL, ntohl(dp[1]))); 155318976Sdfr } 155418976Sdfr return; 155518976Sdfr } 155618976Sdfr } else { 155718976Sdfr if (parseattrstat(dp, vflag, v3) != 0) 155818976Sdfr return; 155918976Sdfr } 156017680Spst break; 156117680Spst 156217680Spst case NFSPROC_CREATE: 156317680Spst printf(" create"); 156475118Sfenner if (!(dp = parserep(rp, length))) 156518976Sdfr break; 156618976Sdfr if (v3) { 156775118Sfenner if (parsecreateopres(dp, vflag) != 0) 156818976Sdfr return; 156918976Sdfr } else { 157018976Sdfr if (parsediropres(dp) != 0) 157118976Sdfr return; 157218976Sdfr } 157318976Sdfr break; 157418976Sdfr 157518976Sdfr case NFSPROC_MKDIR: 157618976Sdfr printf(" mkdir"); 157775118Sfenner if (!(dp = parserep(rp, length))) 157818976Sdfr break; 157918976Sdfr if (v3) { 158075118Sfenner if (parsecreateopres(dp, vflag) != 0) 158118976Sdfr return; 158218976Sdfr } else { 158318976Sdfr if (parsediropres(dp) != 0) 158418976Sdfr return; 158518976Sdfr } 158618976Sdfr break; 158718976Sdfr 158818976Sdfr case NFSPROC_SYMLINK: 158918976Sdfr printf(" symlink"); 159075118Sfenner if (!(dp = parserep(rp, length))) 159118976Sdfr break; 159218976Sdfr if (v3) { 159375118Sfenner if (parsecreateopres(dp, vflag) != 0) 159418976Sdfr return; 159518976Sdfr } else { 159675118Sfenner if (parsestatus(dp, &er) != 0) 159718976Sdfr return; 159818976Sdfr } 159918976Sdfr break; 160018976Sdfr 160118976Sdfr case NFSPROC_MKNOD: 160218976Sdfr printf(" mknod"); 160375118Sfenner if (!(dp = parserep(rp, length))) 160418976Sdfr break; 160575118Sfenner if (parsecreateopres(dp, vflag) != 0) 160617680Spst return; 160717680Spst break; 160817680Spst 160917680Spst case NFSPROC_REMOVE: 161017680Spst printf(" remove"); 161175118Sfenner if (!(dp = parserep(rp, length))) 161218976Sdfr break; 161318976Sdfr if (v3) { 161475118Sfenner if (parsewccres(dp, vflag)) 161518976Sdfr return; 161618976Sdfr } else { 161775118Sfenner if (parsestatus(dp, &er) != 0) 161818976Sdfr return; 161918976Sdfr } 162017680Spst break; 162117680Spst 162218976Sdfr case NFSPROC_RMDIR: 162318976Sdfr printf(" rmdir"); 162475118Sfenner if (!(dp = parserep(rp, length))) 162518976Sdfr break; 162618976Sdfr if (v3) { 162775118Sfenner if (parsewccres(dp, vflag)) 162818976Sdfr return; 162918976Sdfr } else { 163075118Sfenner if (parsestatus(dp, &er) != 0) 163118976Sdfr return; 163218976Sdfr } 163318976Sdfr break; 163418976Sdfr 163517680Spst case NFSPROC_RENAME: 163617680Spst printf(" rename"); 163775118Sfenner if (!(dp = parserep(rp, length))) 163818976Sdfr break; 163918976Sdfr if (v3) { 164075118Sfenner if (!(dp = parsestatus(dp, &er))) 164118976Sdfr break; 164218976Sdfr if (vflag) { 164318976Sdfr printf(" from:"); 164475118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 164518976Sdfr break; 164618976Sdfr printf(" to:"); 164775118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 164818976Sdfr break; 164918976Sdfr } 165017680Spst return; 165118976Sdfr } else { 165275118Sfenner if (parsestatus(dp, &er) != 0) 165318976Sdfr return; 165418976Sdfr } 165517680Spst break; 165617680Spst 165717680Spst case NFSPROC_LINK: 165817680Spst printf(" link"); 165975118Sfenner if (!(dp = parserep(rp, length))) 166018976Sdfr break; 166118976Sdfr if (v3) { 166275118Sfenner if (!(dp = parsestatus(dp, &er))) 166318976Sdfr break; 166418976Sdfr if (vflag) { 166518976Sdfr printf(" file POST:"); 166675118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 166718976Sdfr break; 166818976Sdfr printf(" dir:"); 166975118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 167018976Sdfr break; 167118976Sdfr return; 167218976Sdfr } 167318976Sdfr } else { 167475118Sfenner if (parsestatus(dp, &er) != 0) 167518976Sdfr return; 167618976Sdfr } 167717680Spst break; 167817680Spst 167918976Sdfr case NFSPROC_READDIR: 168018976Sdfr printf(" readdir"); 168175118Sfenner if (!(dp = parserep(rp, length))) 168218976Sdfr break; 168318976Sdfr if (v3) { 168475118Sfenner if (parsev3rddirres(dp, vflag)) 168518976Sdfr return; 168618976Sdfr } else { 168718976Sdfr if (parserddires(dp) != 0) 168818976Sdfr return; 168918976Sdfr } 169018976Sdfr break; 169118976Sdfr 169218976Sdfr case NFSPROC_READDIRPLUS: 169318976Sdfr printf(" readdirplus"); 169475118Sfenner if (!(dp = parserep(rp, length))) 169518976Sdfr break; 169675118Sfenner if (parsev3rddirres(dp, vflag)) 169717680Spst return; 169817680Spst break; 169917680Spst 170018976Sdfr case NFSPROC_FSSTAT: 170118976Sdfr printf(" fsstat"); 170217680Spst dp = parserep(rp, length); 170375118Sfenner if (dp != NULL && parsestatfs(dp, v3) != 0) 170417680Spst return; 170517680Spst break; 170617680Spst 170718976Sdfr case NFSPROC_FSINFO: 170818976Sdfr printf(" fsinfo"); 170917680Spst dp = parserep(rp, length); 171075118Sfenner if (dp != NULL && parsefsinfo(dp) != 0) 171117680Spst return; 171217680Spst break; 171317680Spst 171418976Sdfr case NFSPROC_PATHCONF: 171518976Sdfr printf(" pathconf"); 171617680Spst dp = parserep(rp, length); 171726183Sfenner if (dp != NULL && parsepathconf(dp) != 0) 171817680Spst return; 171917680Spst break; 172017680Spst 172118976Sdfr case NFSPROC_COMMIT: 172218976Sdfr printf(" commit"); 172317680Spst dp = parserep(rp, length); 172426183Sfenner if (dp != NULL && parsewccres(dp, vflag) != 0) 172517680Spst return; 172617680Spst break; 172717680Spst 172817680Spst default: 172926183Sfenner printf(" proc-%u", proc); 173017680Spst return; 173117680Spst } 173218976Sdfrtrunc: 173326183Sfenner if (!nfserr) 173426183Sfenner fputs(" [|nfs]", stdout); 173517680Spst} 1736