print-nfs.c revision 111729
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 111729 2003-03-02 08:25:48Z fenner $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 2526183Sfennerstatic const char rcsid[] = 26111729Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.89.4.2 2002/06/01 23:51:14 guy 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 3717680Spst#include <netinet/in.h> 3817680Spst 3917680Spst#include <rpc/rpc.h> 4017680Spst 4117680Spst#include <ctype.h> 4226183Sfenner#include <pcap.h> 4317680Spst#include <stdio.h> 4417680Spst#include <string.h> 4517680Spst 4617680Spst#include "interface.h" 4717680Spst#include "addrtoname.h" 4817680Spst 4918976Sdfr#include "nfs.h" 5017680Spst#include "nfsfh.h" 5117680Spst 5275118Sfenner#include "ip.h" 5375118Sfenner#ifdef INET6 5475118Sfenner#include "ip6.h" 5575118Sfenner#endif 5675118Sfenner 5775118Sfennerstatic void nfs_printfh(const u_int32_t *, const u_int); 5875118Sfennerstatic void xid_map_enter(const struct rpc_msg *, const u_char *); 5975118Sfennerstatic int32_t xid_map_find(const struct rpc_msg *, const u_char *, 6075118Sfenner u_int32_t *, u_int32_t *); 6118976Sdfrstatic void interp_reply(const struct rpc_msg *, u_int32_t, u_int32_t, int); 6218976Sdfrstatic const u_int32_t *parse_post_op_attr(const u_int32_t *, int); 6375118Sfennerstatic void print_sattr3(const struct nfsv3_sattr *sa3, int verbose); 6475118Sfennerstatic int print_int64(const u_int32_t *dp, int how); 6575118Sfennerstatic void print_nfsaddr(const u_char *, const char *, const char *); 6617680Spst 6718976Sdfr/* 6818976Sdfr * Mapping of old NFS Version 2 RPC numbers to generic numbers. 6918976Sdfr */ 7018976Sdfru_int32_t nfsv3_procid[NFS_NPROCS] = { 7118976Sdfr NFSPROC_NULL, 7218976Sdfr NFSPROC_GETATTR, 7318976Sdfr NFSPROC_SETATTR, 7418976Sdfr NFSPROC_NOOP, 7518976Sdfr NFSPROC_LOOKUP, 7618976Sdfr NFSPROC_READLINK, 7718976Sdfr NFSPROC_READ, 7818976Sdfr NFSPROC_NOOP, 7918976Sdfr NFSPROC_WRITE, 8018976Sdfr NFSPROC_CREATE, 8118976Sdfr NFSPROC_REMOVE, 8218976Sdfr NFSPROC_RENAME, 8318976Sdfr NFSPROC_LINK, 8418976Sdfr NFSPROC_SYMLINK, 8518976Sdfr NFSPROC_MKDIR, 8618976Sdfr NFSPROC_RMDIR, 8718976Sdfr NFSPROC_READDIR, 8818976Sdfr NFSPROC_FSSTAT, 8918976Sdfr NFSPROC_NOOP, 9018976Sdfr NFSPROC_NOOP, 9118976Sdfr NFSPROC_NOOP, 9218976Sdfr NFSPROC_NOOP, 9318976Sdfr NFSPROC_NOOP, 9418976Sdfr NFSPROC_NOOP, 9518976Sdfr NFSPROC_NOOP, 9618976Sdfr NFSPROC_NOOP 9718976Sdfr}; 9818976Sdfr 9975118Sfenner/* 10075118Sfenner * NFS V2 and V3 status values. 10175118Sfenner * 10275118Sfenner * Some of these come from the RFCs for NFS V2 and V3, with the message 10375118Sfenner * strings taken from the FreeBSD C library "errlst.c". 10475118Sfenner * 10575118Sfenner * Others are errors that are not in the RFC but that I suspect some 10675118Sfenner * NFS servers could return; the values are FreeBSD errno values, as 10775118Sfenner * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS 10875118Sfenner * was primarily BSD-derived. 10975118Sfenner */ 11075118Sfennerstatic struct tok status2str[] = { 11175118Sfenner { 1, "Operation not permitted" }, /* EPERM */ 11275118Sfenner { 2, "No such file or directory" }, /* ENOENT */ 11375118Sfenner { 5, "Input/output error" }, /* EIO */ 11475118Sfenner { 6, "Device not configured" }, /* ENXIO */ 11575118Sfenner { 11, "Resource deadlock avoided" }, /* EDEADLK */ 11675118Sfenner { 12, "Cannot allocate memory" }, /* ENOMEM */ 11775118Sfenner { 13, "Permission denied" }, /* EACCES */ 11875118Sfenner { 17, "File exists" }, /* EEXIST */ 11975118Sfenner { 18, "Cross-device link" }, /* EXDEV */ 12075118Sfenner { 19, "Operation not supported by device" }, /* ENODEV */ 12175118Sfenner { 20, "Not a directory" }, /* ENOTDIR */ 12275118Sfenner { 21, "Is a directory" }, /* EISDIR */ 12375118Sfenner { 22, "Invalid argument" }, /* EINVAL */ 12475118Sfenner { 26, "Text file busy" }, /* ETXTBSY */ 12575118Sfenner { 27, "File too large" }, /* EFBIG */ 12675118Sfenner { 28, "No space left on device" }, /* ENOSPC */ 12775118Sfenner { 30, "Read-only file system" }, /* EROFS */ 12875118Sfenner { 31, "Too many links" }, /* EMLINK */ 12975118Sfenner { 45, "Operation not supported" }, /* EOPNOTSUPP */ 13075118Sfenner { 62, "Too many levels of symbolic links" }, /* ELOOP */ 13175118Sfenner { 63, "File name too long" }, /* ENAMETOOLONG */ 13275118Sfenner { 66, "Directory not empty" }, /* ENOTEMPTY */ 13375118Sfenner { 69, "Disc quota exceeded" }, /* EDQUOT */ 13475118Sfenner { 70, "Stale NFS file handle" }, /* ESTALE */ 13575118Sfenner { 71, "Too many levels of remote in path" }, /* EREMOTE */ 13675118Sfenner { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */ 13775118Sfenner { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */ 13875118Sfenner { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */ 13975118Sfenner { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */ 14075118Sfenner { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */ 14175118Sfenner { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */ 14275118Sfenner { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */ 14375118Sfenner { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */ 14475118Sfenner { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */ 14575118Sfenner { 0, NULL } 14618976Sdfr}; 14718976Sdfr 14875118Sfennerstatic struct tok nfsv3_writemodes[] = { 14975118Sfenner { 0, "unstable" }, 15075118Sfenner { 1, "datasync" }, 15175118Sfenner { 2, "filesync" }, 15275118Sfenner { 0, NULL } 15375118Sfenner}; 15475118Sfenner 15518976Sdfrstatic struct tok type2str[] = { 15618976Sdfr { NFNON, "NON" }, 15718976Sdfr { NFREG, "REG" }, 15818976Sdfr { NFDIR, "DIR" }, 15918976Sdfr { NFBLK, "BLK" }, 16018976Sdfr { NFCHR, "CHR" }, 16118976Sdfr { NFLNK, "LNK" }, 16218976Sdfr { NFFIFO, "FIFO" }, 16318976Sdfr { 0, NULL } 16418976Sdfr}; 16518976Sdfr 16618976Sdfr/* 16718976Sdfr * Print out a 64-bit integer. This appears to be different on each system, 16818976Sdfr * try to make the best of it. The integer stored as 2 consecutive XDR 16918976Sdfr * encoded 32-bit integers, to which a pointer is passed. 17018976Sdfr * 17118976Sdfr * Assume that a system that has INT64_FORMAT defined, has a 64-bit 17218976Sdfr * integer datatype and can print it. 17318976Sdfr */ 17418976Sdfr 17518976Sdfr#define UNSIGNED 0 17618976Sdfr#define SIGNED 1 17718976Sdfr#define HEX 2 17818976Sdfr 17975118Sfennerstatic int print_int64(const u_int32_t *dp, int how) 18018976Sdfr{ 18118976Sdfr#ifdef INT64_FORMAT 18218976Sdfr u_int64_t res; 18318976Sdfr 18418976Sdfr res = ((u_int64_t)ntohl(dp[0]) << 32) | (u_int64_t)ntohl(dp[1]); 18518976Sdfr switch (how) { 18618976Sdfr case SIGNED: 18718976Sdfr printf(INT64_FORMAT, res); 18818976Sdfr break; 18918976Sdfr case UNSIGNED: 19018976Sdfr printf(U_INT64_FORMAT, res); 19118976Sdfr break; 19218976Sdfr case HEX: 19318976Sdfr printf(HEX_INT64_FORMAT, res); 19418976Sdfr break; 19518976Sdfr default: 19618976Sdfr return (0); 19718976Sdfr } 19818976Sdfr#else 19975118Sfenner switch (how) { 20075118Sfenner case SIGNED: 20175118Sfenner case UNSIGNED: 20275118Sfenner case HEX: 20375118Sfenner printf("0x%x%08x", (u_int32_t)ntohl(dp[0]), 20475118Sfenner (u_int32_t)ntohl(dp[1])); 20575118Sfenner break; 20675118Sfenner default: 20775118Sfenner return (0); 20875118Sfenner } 20918976Sdfr#endif 21018976Sdfr return 1; 21118976Sdfr} 21218976Sdfr 21375118Sfennerstatic void 21475118Sfennerprint_nfsaddr(const u_char *bp, const char *s, const char *d) 21575118Sfenner{ 21675118Sfenner struct ip *ip; 21775118Sfenner#ifdef INET6 21875118Sfenner struct ip6_hdr *ip6; 21975118Sfenner char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; 22075118Sfenner#else 22175118Sfenner#ifndef INET_ADDRSTRLEN 22275118Sfenner#define INET_ADDRSTRLEN 16 22375118Sfenner#endif 22475118Sfenner char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN]; 22575118Sfenner#endif 22675118Sfenner 22775118Sfenner srcaddr[0] = dstaddr[0] = '\0'; 22875118Sfenner switch (IP_V((struct ip *)bp)) { 22975118Sfenner case 4: 23075118Sfenner ip = (struct ip *)bp; 23175118Sfenner strlcpy(srcaddr, ipaddr_string(&ip->ip_src), sizeof(srcaddr)); 23275118Sfenner strlcpy(dstaddr, ipaddr_string(&ip->ip_dst), sizeof(dstaddr)); 23375118Sfenner break; 23475118Sfenner#ifdef INET6 23575118Sfenner case 6: 23675118Sfenner ip6 = (struct ip6_hdr *)bp; 23775118Sfenner strlcpy(srcaddr, ip6addr_string(&ip6->ip6_src), 23875118Sfenner sizeof(srcaddr)); 23975118Sfenner strlcpy(dstaddr, ip6addr_string(&ip6->ip6_dst), 24075118Sfenner sizeof(dstaddr)); 24175118Sfenner break; 24275118Sfenner#endif 24375118Sfenner default: 24475118Sfenner strlcpy(srcaddr, "?", sizeof(srcaddr)); 24575118Sfenner strlcpy(dstaddr, "?", sizeof(dstaddr)); 24675118Sfenner break; 24775118Sfenner } 24875118Sfenner 24975118Sfenner (void)printf("%s.%s > %s.%s: ", srcaddr, s, dstaddr, d); 25075118Sfenner} 25175118Sfenner 25218976Sdfrstatic const u_int32_t * 25318976Sdfrparse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3) 25418976Sdfr{ 25575118Sfenner TCHECK(dp[0]); 25618976Sdfr if ((sa3->sa_modeset = ntohl(*dp++))) { 25775118Sfenner TCHECK(dp[0]); 25818976Sdfr sa3->sa_mode = ntohl(*dp++); 25918976Sdfr } 26018976Sdfr 26175118Sfenner TCHECK(dp[0]); 26218976Sdfr if ((sa3->sa_uidset = ntohl(*dp++))) { 26375118Sfenner TCHECK(dp[0]); 26418976Sdfr sa3->sa_uid = ntohl(*dp++); 26518976Sdfr } 26618976Sdfr 26775118Sfenner TCHECK(dp[0]); 26818976Sdfr if ((sa3->sa_gidset = ntohl(*dp++))) { 26975118Sfenner TCHECK(dp[0]); 27018976Sdfr sa3->sa_gid = ntohl(*dp++); 27118976Sdfr } 27218976Sdfr 27375118Sfenner TCHECK(dp[0]); 27418976Sdfr if ((sa3->sa_sizeset = ntohl(*dp++))) { 27575118Sfenner TCHECK(dp[0]); 27618976Sdfr sa3->sa_size = ntohl(*dp++); 27718976Sdfr } 27818976Sdfr 27975118Sfenner TCHECK(dp[0]); 28018976Sdfr if ((sa3->sa_atimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 28175118Sfenner TCHECK(dp[1]); 28218976Sdfr sa3->sa_atime.nfsv3_sec = ntohl(*dp++); 28318976Sdfr sa3->sa_atime.nfsv3_nsec = ntohl(*dp++); 28418976Sdfr } 28518976Sdfr 28675118Sfenner TCHECK(dp[0]); 28718976Sdfr if ((sa3->sa_mtimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 28875118Sfenner TCHECK(dp[1]); 28918976Sdfr sa3->sa_mtime.nfsv3_sec = ntohl(*dp++); 29018976Sdfr sa3->sa_mtime.nfsv3_nsec = ntohl(*dp++); 29118976Sdfr } 29218976Sdfr 29318976Sdfr return dp; 29475118Sfennertrunc: 29575118Sfenner return NULL; 29618976Sdfr} 29718976Sdfr 29875118Sfennerstatic int nfserr; /* true if we error rather than trunc */ 29975118Sfenner 30075118Sfennerstatic void 30118976Sdfrprint_sattr3(const struct nfsv3_sattr *sa3, int verbose) 30218976Sdfr{ 30318976Sdfr if (sa3->sa_modeset) 30418976Sdfr printf(" mode %o", sa3->sa_mode); 30518976Sdfr if (sa3->sa_uidset) 30618976Sdfr printf(" uid %u", sa3->sa_uid); 30718976Sdfr if (sa3->sa_gidset) 30818976Sdfr printf(" gid %u", sa3->sa_gid); 30918976Sdfr if (verbose > 1) { 31018976Sdfr if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 31118976Sdfr printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec, 31218976Sdfr sa3->sa_atime.nfsv3_nsec); 31318976Sdfr if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 31418976Sdfr printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 31518976Sdfr sa3->sa_mtime.nfsv3_nsec); 31618976Sdfr } 31718976Sdfr} 31818976Sdfr 31918976Sdfrvoid 32017680Spstnfsreply_print(register const u_char *bp, u_int length, 32117680Spst register const u_char *bp2) 32217680Spst{ 32317680Spst register const struct rpc_msg *rp; 32418976Sdfr u_int32_t proc, vers; 32575118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 32617680Spst 32726183Sfenner nfserr = 0; /* assume no error */ 32817680Spst rp = (const struct rpc_msg *)bp; 32917680Spst 33075118Sfenner if (!nflag) { 33175118Sfenner strlcpy(srcid, "nfs", sizeof(srcid)); 33275118Sfenner snprintf(dstid, sizeof(dstid), "%u", 33375118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 33475118Sfenner } else { 33575118Sfenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 33675118Sfenner snprintf(dstid, sizeof(dstid), "%u", 33775118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 33875118Sfenner } 33975118Sfenner print_nfsaddr(bp2, srcid, dstid); 34075118Sfenner (void)printf("reply %s %d", 34175118Sfenner ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 34275118Sfenner "ok":"ERR", 34317680Spst length); 34417680Spst 34575118Sfenner if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 34618976Sdfr interp_reply(rp, proc, vers, length); 34717680Spst} 34817680Spst 34917680Spst/* 35017680Spst * Return a pointer to the first file handle in the packet. 35175118Sfenner * If the packet was truncated, return 0. 35217680Spst */ 35317680Spststatic const u_int32_t * 35475118Sfennerparsereq(register const struct rpc_msg *rp, register u_int length) 35517680Spst{ 35626183Sfenner register const u_int32_t *dp; 35717680Spst register u_int len; 35817680Spst 35917680Spst /* 36017680Spst * find the start of the req data (if we captured it) 36117680Spst */ 36226183Sfenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 36326183Sfenner TCHECK(dp[1]); 36426183Sfenner len = ntohl(dp[1]); 36526183Sfenner if (len < length) { 36626183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 36726183Sfenner TCHECK(dp[1]); 36817680Spst len = ntohl(dp[1]); 36926183Sfenner if (len < length) { 37026183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 37126183Sfenner TCHECK2(dp[0], 0); 37226183Sfenner return (dp); 37317680Spst } 37417680Spst } 37526183Sfennertrunc: 37626183Sfenner return (NULL); 37717680Spst} 37817680Spst 37917680Spst/* 38017680Spst * Print out an NFS file handle and return a pointer to following word. 38175118Sfenner * If packet was truncated, return 0. 38217680Spst */ 38317680Spststatic const u_int32_t * 38418976Sdfrparsefh(register const u_int32_t *dp, int v3) 38517680Spst{ 38618976Sdfr int len; 38718976Sdfr 38818976Sdfr if (v3) { 38926183Sfenner TCHECK(dp[0]); 39018976Sdfr len = (int)ntohl(*dp) / 4; 39118976Sdfr dp++; 39218976Sdfr } else 39318976Sdfr len = NFSX_V2FH / 4; 39418976Sdfr 39526183Sfenner if (TTEST2(*dp, len * sizeof(*dp))) { 39618976Sdfr nfs_printfh(dp, len); 39718976Sdfr return (dp + len); 39817680Spst } 39926183Sfennertrunc: 40026183Sfenner return (NULL); 40117680Spst} 40217680Spst 40317680Spst/* 40417680Spst * Print out a file name and return pointer to 32-bit word past it. 40575118Sfenner * If packet was truncated, return 0. 40617680Spst */ 40717680Spststatic const u_int32_t * 40817680Spstparsefn(register const u_int32_t *dp) 40917680Spst{ 41017680Spst register u_int32_t len; 41117680Spst register const u_char *cp; 41217680Spst 41317680Spst /* Bail if we don't have the string length */ 41475118Sfenner TCHECK(*dp); 41517680Spst 41617680Spst /* Fetch string length; convert to host order */ 41717680Spst len = *dp++; 41817680Spst NTOHL(len); 41917680Spst 42075118Sfenner TCHECK2(*dp, ((len + 3) & ~3)); 42175118Sfenner 42217680Spst cp = (u_char *)dp; 42317680Spst /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 42417680Spst dp += ((len + 3) & ~3) / sizeof(*dp); 42517680Spst /* XXX seems like we should be checking the length */ 42626183Sfenner putchar('"'); 42717680Spst (void) fn_printn(cp, len, NULL); 42826183Sfenner putchar('"'); 42917680Spst 43017680Spst return (dp); 43175118Sfennertrunc: 43275118Sfenner return NULL; 43317680Spst} 43417680Spst 43517680Spst/* 43617680Spst * Print out file handle and file name. 43717680Spst * Return pointer to 32-bit word past file name. 43875118Sfenner * If packet was truncated (or there was some other error), return 0. 43917680Spst */ 44017680Spststatic const u_int32_t * 44118976Sdfrparsefhn(register const u_int32_t *dp, int v3) 44217680Spst{ 44318976Sdfr dp = parsefh(dp, v3); 44426183Sfenner if (dp == NULL) 44526183Sfenner return (NULL); 44617680Spst putchar(' '); 44717680Spst return (parsefn(dp)); 44817680Spst} 44917680Spst 45017680Spstvoid 45117680Spstnfsreq_print(register const u_char *bp, u_int length, 45217680Spst register const u_char *bp2) 45317680Spst{ 45417680Spst register const struct rpc_msg *rp; 45517680Spst register const u_int32_t *dp; 45675118Sfenner nfs_type type; 45775118Sfenner int v3; 45875118Sfenner u_int32_t proc; 45918976Sdfr struct nfsv3_sattr sa3; 46075118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 46117680Spst 46226183Sfenner nfserr = 0; /* assume no error */ 46317680Spst rp = (const struct rpc_msg *)bp; 46475118Sfenner if (!nflag) { 46575118Sfenner snprintf(srcid, sizeof(srcid), "%u", 46675118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 46775118Sfenner strlcpy(dstid, "nfs", sizeof(dstid)); 46875118Sfenner } else { 46975118Sfenner snprintf(srcid, sizeof(srcid), "%u", 47075118Sfenner (u_int32_t)ntohl(rp->rm_xid)); 47175118Sfenner snprintf(dstid, sizeof(dstid), "%u", NFS_PORT); 47275118Sfenner } 47375118Sfenner print_nfsaddr(bp2, srcid, dstid); 47475118Sfenner (void)printf("%d", length); 47517680Spst 47675118Sfenner xid_map_enter(rp, bp2); /* record proc number for later on */ 47717680Spst 47818976Sdfr v3 = (ntohl(rp->rm_call.cb_vers) == NFS_VER3); 47918976Sdfr proc = ntohl(rp->rm_call.cb_proc); 48018976Sdfr 48118976Sdfr if (!v3 && proc < NFS_NPROCS) 48218976Sdfr proc = nfsv3_procid[proc]; 48318976Sdfr 48418976Sdfr switch (proc) { 48517680Spst case NFSPROC_NOOP: 48617680Spst printf(" nop"); 48717680Spst return; 48817680Spst case NFSPROC_NULL: 48917680Spst printf(" null"); 49017680Spst return; 49117680Spst 49217680Spst case NFSPROC_GETATTR: 49317680Spst printf(" getattr"); 49475118Sfenner if ((dp = parsereq(rp, length)) != NULL && 49575118Sfenner parsefh(dp, v3) != NULL) 49617680Spst return; 49717680Spst break; 49817680Spst 49917680Spst case NFSPROC_SETATTR: 50017680Spst printf(" setattr"); 50175118Sfenner if ((dp = parsereq(rp, length)) != NULL && 50275118Sfenner parsefh(dp, v3) != NULL) 50317680Spst return; 50417680Spst break; 50517680Spst 50617680Spst case NFSPROC_LOOKUP: 50717680Spst printf(" lookup"); 50875118Sfenner if ((dp = parsereq(rp, length)) != NULL && 50975118Sfenner parsefhn(dp, v3) != NULL) 51017680Spst return; 51117680Spst break; 51217680Spst 51318976Sdfr case NFSPROC_ACCESS: 51418976Sdfr printf(" access"); 51526183Sfenner if ((dp = parsereq(rp, length)) != NULL && 51626183Sfenner (dp = parsefh(dp, v3)) != NULL) { 51775118Sfenner TCHECK(dp[0]); 51875118Sfenner printf(" %04x", (u_int32_t)ntohl(dp[0])); 51918976Sdfr return; 52018976Sdfr } 52118976Sdfr break; 52218976Sdfr 52317680Spst case NFSPROC_READLINK: 52417680Spst printf(" readlink"); 52575118Sfenner if ((dp = parsereq(rp, length)) != NULL && 52675118Sfenner parsefh(dp, v3) != NULL) 52717680Spst return; 52817680Spst break; 52917680Spst 53017680Spst case NFSPROC_READ: 53117680Spst printf(" read"); 53226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 53326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 53418976Sdfr if (v3) { 53575118Sfenner TCHECK(dp[2]); 53675118Sfenner printf(" %u bytes @ ", 53775118Sfenner (u_int32_t) ntohl(dp[2])); 53818976Sdfr print_int64(dp, UNSIGNED); 53918976Sdfr } else { 54075118Sfenner TCHECK(dp[1]); 54175118Sfenner printf(" %u bytes @ %u", 54275118Sfenner (u_int32_t)ntohl(dp[1]), 54375118Sfenner (u_int32_t)ntohl(dp[0])); 54418976Sdfr } 54517680Spst return; 54617680Spst } 54717680Spst break; 54817680Spst 54917680Spst case NFSPROC_WRITE: 55017680Spst printf(" write"); 55126183Sfenner if ((dp = parsereq(rp, length)) != NULL && 55226183Sfenner (dp = parsefh(dp, v3)) != NULL) { 55318976Sdfr if (v3) { 55475118Sfenner TCHECK(dp[4]); 55575118Sfenner printf(" %u bytes @ ", 55675118Sfenner (u_int32_t) ntohl(dp[4])); 55718976Sdfr print_int64(dp, UNSIGNED); 55818976Sdfr if (vflag) { 55918976Sdfr dp += 3; 56075118Sfenner TCHECK(dp[0]); 56118976Sdfr printf(" <%s>", 56275118Sfenner tok2str(nfsv3_writemodes, 56375118Sfenner NULL, ntohl(*dp))); 56418976Sdfr } 56518976Sdfr } else { 56675118Sfenner TCHECK(dp[3]); 56775118Sfenner printf(" %u (%u) bytes @ %u (%u)", 56875118Sfenner (u_int32_t)ntohl(dp[3]), 56975118Sfenner (u_int32_t)ntohl(dp[2]), 57075118Sfenner (u_int32_t)ntohl(dp[1]), 57175118Sfenner (u_int32_t)ntohl(dp[0])); 57218976Sdfr } 57317680Spst return; 57417680Spst } 57517680Spst break; 57617680Spst 57717680Spst case NFSPROC_CREATE: 57817680Spst printf(" create"); 57975118Sfenner if ((dp = parsereq(rp, length)) != NULL && 58075118Sfenner parsefhn(dp, v3) != NULL) 58117680Spst return; 58217680Spst break; 58317680Spst 58418976Sdfr case NFSPROC_MKDIR: 58518976Sdfr printf(" mkdir"); 58675118Sfenner if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) 58718976Sdfr return; 58818976Sdfr break; 58918976Sdfr 59018976Sdfr case NFSPROC_SYMLINK: 59118976Sdfr printf(" symlink"); 59275118Sfenner if ((dp = parsereq(rp, length)) != 0 && 59375118Sfenner (dp = parsefhn(dp, v3)) != 0) { 59475118Sfenner fputs(" ->", stdout); 59575118Sfenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) 59618976Sdfr break; 59775118Sfenner if (parsefn(dp) == 0) 59818976Sdfr break; 59918976Sdfr if (v3 && vflag) 60018976Sdfr print_sattr3(&sa3, vflag); 60118976Sdfr return; 60218976Sdfr } 60318976Sdfr break; 60418976Sdfr 60518976Sdfr case NFSPROC_MKNOD: 60618976Sdfr printf(" mknod"); 60775118Sfenner if ((dp = parsereq(rp, length)) != 0 && 60875118Sfenner (dp = parsefhn(dp, v3)) != 0) { 60975118Sfenner TCHECK(*dp); 61075118Sfenner type = (nfs_type)ntohl(*dp++); 61175118Sfenner if ((dp = parse_sattr3(dp, &sa3)) == 0) 61218976Sdfr break; 61318976Sdfr printf(" %s", tok2str(type2str, "unk-ft %d", type)); 61418976Sdfr if (vflag && (type == NFCHR || type == NFBLK)) { 61575118Sfenner TCHECK(dp[1]); 61675118Sfenner printf(" %u/%u", 61775118Sfenner (u_int32_t)ntohl(dp[0]), 61875118Sfenner (u_int32_t)ntohl(dp[1])); 61918976Sdfr dp += 2; 62018976Sdfr } 62118976Sdfr if (vflag) 62218976Sdfr print_sattr3(&sa3, vflag); 62318976Sdfr return; 62418976Sdfr } 62518976Sdfr break; 62618976Sdfr 62717680Spst case NFSPROC_REMOVE: 62817680Spst printf(" remove"); 62975118Sfenner if ((dp = parsereq(rp, length)) != NULL && 63075118Sfenner parsefhn(dp, v3) != NULL) 63117680Spst return; 63217680Spst break; 63317680Spst 63418976Sdfr case NFSPROC_RMDIR: 63518976Sdfr printf(" rmdir"); 63675118Sfenner if ((dp = parsereq(rp, length)) != NULL && 63775118Sfenner parsefhn(dp, v3) != NULL) 63818976Sdfr return; 63918976Sdfr break; 64018976Sdfr 64117680Spst case NFSPROC_RENAME: 64217680Spst printf(" rename"); 64326183Sfenner if ((dp = parsereq(rp, length)) != NULL && 64426183Sfenner (dp = parsefhn(dp, v3)) != NULL) { 64517680Spst fputs(" ->", stdout); 64626183Sfenner if (parsefhn(dp, v3) != NULL) 64717680Spst return; 64817680Spst } 64917680Spst break; 65017680Spst 65117680Spst case NFSPROC_LINK: 65217680Spst printf(" link"); 65326183Sfenner if ((dp = parsereq(rp, length)) != NULL && 65426183Sfenner (dp = parsefh(dp, v3)) != NULL) { 65517680Spst fputs(" ->", stdout); 65626183Sfenner if (parsefhn(dp, v3) != NULL) 65717680Spst return; 65817680Spst } 65917680Spst break; 66017680Spst 66118976Sdfr case NFSPROC_READDIR: 66218976Sdfr printf(" readdir"); 66326183Sfenner if ((dp = parsereq(rp, length)) != NULL && 66426183Sfenner (dp = parsefh(dp, v3)) != NULL) { 66518976Sdfr if (v3) { 66675118Sfenner TCHECK(dp[4]); 66718976Sdfr /* 66818976Sdfr * We shouldn't really try to interpret the 66918976Sdfr * offset cookie here. 67018976Sdfr */ 67175118Sfenner printf(" %u bytes @ ", 67275118Sfenner (u_int32_t) ntohl(dp[4])); 67318976Sdfr print_int64(dp, SIGNED); 67418976Sdfr if (vflag) 67526183Sfenner printf(" verf %08x%08x", dp[2], 67618976Sdfr dp[3]); 67718976Sdfr } else { 67875118Sfenner TCHECK(dp[1]); 67918976Sdfr /* 68018976Sdfr * Print the offset as signed, since -1 is 68118976Sdfr * common, but offsets > 2^31 aren't. 68218976Sdfr */ 68375118Sfenner printf(" %u bytes @ %d", 68475118Sfenner (u_int32_t)ntohl(dp[1]), 68575118Sfenner (u_int32_t)ntohl(dp[0])); 68618976Sdfr } 68718976Sdfr return; 68817680Spst } 68917680Spst break; 69017680Spst 69118976Sdfr case NFSPROC_READDIRPLUS: 69218976Sdfr printf(" readdirplus"); 69326183Sfenner if ((dp = parsereq(rp, length)) != NULL && 69426183Sfenner (dp = parsefh(dp, v3)) != NULL) { 69575118Sfenner TCHECK(dp[4]); 69618976Sdfr /* 69718976Sdfr * We don't try to interpret the offset 69818976Sdfr * cookie here. 69918976Sdfr */ 70075118Sfenner printf(" %u bytes @ ", (u_int32_t) ntohl(dp[4])); 70118976Sdfr print_int64(dp, SIGNED); 70218976Sdfr if (vflag) 70375118Sfenner printf(" max %u verf %08x%08x", 70475118Sfenner (u_int32_t) ntohl(dp[5]), dp[2], dp[3]); 70517680Spst return; 70618976Sdfr } 70717680Spst break; 70817680Spst 70918976Sdfr case NFSPROC_FSSTAT: 71018976Sdfr printf(" fsstat"); 71175118Sfenner if ((dp = parsereq(rp, length)) != NULL && 71275118Sfenner parsefh(dp, v3) != NULL) 71317680Spst return; 71417680Spst break; 71517680Spst 71618976Sdfr case NFSPROC_FSINFO: 71718976Sdfr printf(" fsinfo"); 718111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 719111729Sfenner parsefh(dp, v3) != NULL) 720111729Sfenner return; 72118976Sdfr break; 72218976Sdfr 72318976Sdfr case NFSPROC_PATHCONF: 72418976Sdfr printf(" pathconf"); 725111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 726111729Sfenner parsefh(dp, v3) != NULL) 727111729Sfenner return; 72818976Sdfr break; 72918976Sdfr 73018976Sdfr case NFSPROC_COMMIT: 73118976Sdfr printf(" commit"); 73226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 73326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 73475118Sfenner printf(" %u bytes @ ", (u_int32_t) ntohl(dp[2])); 73518976Sdfr print_int64(dp, UNSIGNED); 73617680Spst return; 73717680Spst } 73817680Spst break; 73917680Spst 74017680Spst default: 74175118Sfenner printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc)); 74217680Spst return; 74317680Spst } 74475118Sfenner 74517680Spsttrunc: 74626183Sfenner if (!nfserr) 74726183Sfenner fputs(" [|nfs]", stdout); 74817680Spst} 74917680Spst 75017680Spst/* 75117680Spst * Print out an NFS file handle. 75217680Spst * We assume packet was not truncated before the end of the 75317680Spst * file handle pointed to by dp. 75417680Spst * 75517680Spst * Note: new version (using portable file-handle parser) doesn't produce 75617680Spst * generation number. It probably could be made to do that, with some 75717680Spst * additional hacking on the parser code. 75817680Spst */ 75917680Spststatic void 76075118Sfennernfs_printfh(register const u_int32_t *dp, const u_int len) 76117680Spst{ 76217680Spst my_fsid fsid; 76317680Spst ino_t ino; 76417680Spst char *sfsname = NULL; 76517680Spst 76675118Sfenner Parse_fh((caddr_t*)dp, len, &fsid, &ino, NULL, &sfsname, 0); 76717680Spst 76817680Spst if (sfsname) { 76926183Sfenner /* file system ID is ASCII, not numeric, for this server OS */ 77026183Sfenner static char temp[NFSX_V3FHMAX+1]; 77117680Spst 77226183Sfenner /* Make sure string is null-terminated */ 77326183Sfenner strncpy(temp, sfsname, NFSX_V3FHMAX); 77475118Sfenner temp[sizeof(temp) - 1] = '\0'; 77526183Sfenner /* Remove trailing spaces */ 77626183Sfenner sfsname = strchr(temp, ' '); 77726183Sfenner if (sfsname) 77826183Sfenner *sfsname = 0; 77917680Spst 78075118Sfenner (void)printf(" fh %s/", temp); 78126183Sfenner } else { 78275118Sfenner (void)printf(" fh %d,%d/", 78375118Sfenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); 78417680Spst } 78575118Sfenner 78675118Sfenner if(fsid.Fsid_dev.Minor == 257 && uflag) 78775118Sfenner /* Print the undecoded handle */ 78875118Sfenner (void)printf("%s", fsid.Opaque_Handle); 78975118Sfenner else 79075118Sfenner (void)printf("%ld", (long) ino); 79117680Spst} 79217680Spst 79317680Spst/* 79417680Spst * Maintain a small cache of recent client.XID.server/proc pairs, to allow 79517680Spst * us to match up replies with requests and thus to know how to parse 79617680Spst * the reply. 79717680Spst */ 79817680Spst 79917680Spststruct xid_map_entry { 80075118Sfenner u_int32_t xid; /* transaction ID (net order) */ 80175118Sfenner int ipver; /* IP version (4 or 6) */ 80275118Sfenner#ifdef INET6 80375118Sfenner struct in6_addr client; /* client IP address (net order) */ 80475118Sfenner struct in6_addr server; /* server IP address (net order) */ 80575118Sfenner#else 80617680Spst struct in_addr client; /* client IP address (net order) */ 80717680Spst struct in_addr server; /* server IP address (net order) */ 80875118Sfenner#endif 80975118Sfenner u_int32_t proc; /* call proc number (host order) */ 81075118Sfenner u_int32_t vers; /* program version (host order) */ 81117680Spst}; 81217680Spst 81317680Spst/* 81417680Spst * Map entries are kept in an array that we manage as a ring; 81517680Spst * new entries are always added at the tail of the ring. Initially, 81617680Spst * all the entries are zero and hence don't match anything. 81717680Spst */ 81817680Spst 81917680Spst#define XIDMAPSIZE 64 82017680Spst 82117680Spststruct xid_map_entry xid_map[XIDMAPSIZE]; 82217680Spst 82317680Spstint xid_map_next = 0; 82417680Spstint xid_map_hint = 0; 82517680Spst 82617680Spststatic void 82775118Sfennerxid_map_enter(const struct rpc_msg *rp, const u_char *bp) 82817680Spst{ 82975118Sfenner struct ip *ip = NULL; 83075118Sfenner#ifdef INET6 83175118Sfenner struct ip6_hdr *ip6 = NULL; 83275118Sfenner#endif 83317680Spst struct xid_map_entry *xmep; 83417680Spst 83575118Sfenner switch (IP_V((struct ip *)bp)) { 83675118Sfenner case 4: 83775118Sfenner ip = (struct ip *)bp; 83875118Sfenner break; 83975118Sfenner#ifdef INET6 84075118Sfenner case 6: 84175118Sfenner ip6 = (struct ip6_hdr *)bp; 84275118Sfenner break; 84375118Sfenner#endif 84475118Sfenner default: 84575118Sfenner return; 84675118Sfenner } 84775118Sfenner 84817680Spst xmep = &xid_map[xid_map_next]; 84917680Spst 85017680Spst if (++xid_map_next >= XIDMAPSIZE) 85117680Spst xid_map_next = 0; 85217680Spst 85317680Spst xmep->xid = rp->rm_xid; 85475118Sfenner if (ip) { 85575118Sfenner xmep->ipver = 4; 85675118Sfenner memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 85775118Sfenner memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 85875118Sfenner } 85975118Sfenner#ifdef INET6 86075118Sfenner else if (ip6) { 86175118Sfenner xmep->ipver = 6; 86275118Sfenner memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 86375118Sfenner memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 86475118Sfenner } 86575118Sfenner#endif 86617680Spst xmep->proc = ntohl(rp->rm_call.cb_proc); 86718976Sdfr xmep->vers = ntohl(rp->rm_call.cb_vers); 86817680Spst} 86917680Spst 87026183Sfenner/* 87126183Sfenner * Returns 0 and puts NFSPROC_xxx in proc return and 87226183Sfenner * version in vers return, or returns -1 on failure 87326183Sfenner */ 87418976Sdfrstatic int 87575118Sfennerxid_map_find(const struct rpc_msg *rp, const u_char *bp, u_int32_t *proc, 87618976Sdfr u_int32_t *vers) 87717680Spst{ 87817680Spst int i; 87917680Spst struct xid_map_entry *xmep; 88017680Spst u_int32_t xid = rp->rm_xid; 88175118Sfenner struct ip *ip = (struct ip *)bp; 88275118Sfenner#ifdef INET6 88375118Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 88475118Sfenner#endif 88575118Sfenner int cmp; 88617680Spst 88717680Spst /* Start searching from where we last left off */ 88875118Sfenner i = xid_map_hint; 88917680Spst do { 89017680Spst xmep = &xid_map[i]; 89175118Sfenner cmp = 1; 89275118Sfenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 89375118Sfenner goto nextitem; 89475118Sfenner switch (xmep->ipver) { 89575118Sfenner case 4: 89675118Sfenner if (memcmp(&ip->ip_src, &xmep->server, 89775118Sfenner sizeof(ip->ip_src)) != 0 || 89875118Sfenner memcmp(&ip->ip_dst, &xmep->client, 89975118Sfenner sizeof(ip->ip_dst)) != 0) { 90075118Sfenner cmp = 0; 90175118Sfenner } 90275118Sfenner break; 90375118Sfenner#ifdef INET6 90475118Sfenner case 6: 90575118Sfenner if (memcmp(&ip6->ip6_src, &xmep->server, 90675118Sfenner sizeof(ip6->ip6_src)) != 0 || 90775118Sfenner memcmp(&ip6->ip6_dst, &xmep->client, 90875118Sfenner sizeof(ip6->ip6_dst)) != 0) { 90975118Sfenner cmp = 0; 91075118Sfenner } 91175118Sfenner break; 91275118Sfenner#endif 91375118Sfenner default: 91475118Sfenner cmp = 0; 91575118Sfenner break; 91675118Sfenner } 91775118Sfenner if (cmp) { 91817680Spst /* match */ 91917680Spst xid_map_hint = i; 92018976Sdfr *proc = xmep->proc; 92118976Sdfr *vers = xmep->vers; 92218976Sdfr return 0; 92317680Spst } 92475118Sfenner nextitem: 92517680Spst if (++i >= XIDMAPSIZE) 92617680Spst i = 0; 92717680Spst } while (i != xid_map_hint); 92817680Spst 92917680Spst /* search failed */ 93075118Sfenner return (-1); 93117680Spst} 93217680Spst 93317680Spst/* 93417680Spst * Routines for parsing reply packets 93517680Spst */ 93617680Spst 93717680Spst/* 93817680Spst * Return a pointer to the beginning of the actual results. 93975118Sfenner * If the packet was truncated, return 0. 94017680Spst */ 94117680Spststatic const u_int32_t * 94275118Sfennerparserep(register const struct rpc_msg *rp, register u_int length) 94317680Spst{ 94417680Spst register const u_int32_t *dp; 94575118Sfenner u_int len; 94617680Spst enum accept_stat astat; 94717680Spst 94817680Spst /* 94917680Spst * Portability note: 95017680Spst * Here we find the address of the ar_verf credentials. 95117680Spst * Originally, this calculation was 95217680Spst * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 95317680Spst * On the wire, the rp_acpt field starts immediately after 95417680Spst * the (32 bit) rp_stat field. However, rp_acpt (which is a 95517680Spst * "struct accepted_reply") contains a "struct opaque_auth", 95617680Spst * whose internal representation contains a pointer, so on a 95717680Spst * 64-bit machine the compiler inserts 32 bits of padding 95817680Spst * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 95917680Spst * the internal representation to parse the on-the-wire 96017680Spst * representation. Instead, we skip past the rp_stat field, 96117680Spst * which is an "enum" and so occupies one 32-bit word. 96217680Spst */ 96317680Spst dp = ((const u_int32_t *)&rp->rm_reply) + 1; 96475118Sfenner TCHECK(dp[1]); 96517680Spst len = ntohl(dp[1]); 96617680Spst if (len >= length) 96726183Sfenner return (NULL); 96817680Spst /* 96917680Spst * skip past the ar_verf credentials. 97017680Spst */ 97117680Spst dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 97226183Sfenner TCHECK2(dp[0], 0); 97317680Spst 97417680Spst /* 97517680Spst * now we can check the ar_stat field 97617680Spst */ 97717680Spst astat = ntohl(*(enum accept_stat *)dp); 97817680Spst switch (astat) { 97917680Spst 98017680Spst case SUCCESS: 98117680Spst break; 98217680Spst 98317680Spst case PROG_UNAVAIL: 98417680Spst printf(" PROG_UNAVAIL"); 98526183Sfenner nfserr = 1; /* suppress trunc string */ 98626183Sfenner return (NULL); 98717680Spst 98817680Spst case PROG_MISMATCH: 98917680Spst printf(" PROG_MISMATCH"); 99026183Sfenner nfserr = 1; /* suppress trunc string */ 99126183Sfenner return (NULL); 99217680Spst 99317680Spst case PROC_UNAVAIL: 99417680Spst printf(" PROC_UNAVAIL"); 99526183Sfenner nfserr = 1; /* suppress trunc string */ 99626183Sfenner return (NULL); 99717680Spst 99817680Spst case GARBAGE_ARGS: 99917680Spst printf(" GARBAGE_ARGS"); 100026183Sfenner nfserr = 1; /* suppress trunc string */ 100126183Sfenner return (NULL); 100217680Spst 100317680Spst case SYSTEM_ERR: 100417680Spst printf(" SYSTEM_ERR"); 100526183Sfenner nfserr = 1; /* suppress trunc string */ 100626183Sfenner return (NULL); 100717680Spst 100817680Spst default: 100917680Spst printf(" ar_stat %d", astat); 101026183Sfenner nfserr = 1; /* suppress trunc string */ 101126183Sfenner return (NULL); 101217680Spst } 101317680Spst /* successful return */ 101475118Sfenner TCHECK2(*dp, sizeof(astat)); 101575118Sfenner return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 101626183Sfennertrunc: 101775118Sfenner return (0); 101817680Spst} 101917680Spst 102017680Spststatic const u_int32_t * 102118976Sdfrparsestatus(const u_int32_t *dp, int *er) 102217680Spst{ 102375118Sfenner int errnum; 102417680Spst 102526183Sfenner TCHECK(dp[0]); 102675118Sfenner 102726183Sfenner errnum = ntohl(dp[0]); 102818976Sdfr if (er) 102926183Sfenner *er = errnum; 103026183Sfenner if (errnum != 0) { 103126183Sfenner if (!qflag) 103275118Sfenner printf(" ERROR: %s", 103375118Sfenner tok2str(status2str, "unk %d", errnum)); 103426183Sfenner nfserr = 1; 103517680Spst } 103617680Spst return (dp + 1); 103726183Sfennertrunc: 103875118Sfenner return NULL; 103917680Spst} 104017680Spst 104117680Spststatic const u_int32_t * 104218976Sdfrparsefattr(const u_int32_t *dp, int verbose, int v3) 104317680Spst{ 104418976Sdfr const struct nfs_fattr *fap; 104517680Spst 104618976Sdfr fap = (const struct nfs_fattr *)dp; 104726184Sfenner TCHECK(fap->fa_gid); 104817680Spst if (verbose) { 104975118Sfenner printf(" %s %o ids %d/%d", 105075118Sfenner tok2str(type2str, "unk-ft %d ", 105175118Sfenner (u_int32_t)ntohl(fap->fa_type)), 105275118Sfenner (u_int32_t)ntohl(fap->fa_mode), 105375118Sfenner (u_int32_t)ntohl(fap->fa_uid), 105475118Sfenner (u_int32_t) ntohl(fap->fa_gid)); 105518976Sdfr if (v3) { 105626184Sfenner TCHECK(fap->fa3_size); 105718976Sdfr printf(" sz "); 105818976Sdfr print_int64((u_int32_t *)&fap->fa3_size, UNSIGNED); 105918976Sdfr putchar(' '); 106026184Sfenner } else { 106126184Sfenner TCHECK(fap->fa2_size); 106275118Sfenner printf(" sz %d ", (u_int32_t) ntohl(fap->fa2_size)); 106318976Sdfr } 106417680Spst } 106517680Spst /* print lots more stuff */ 106617680Spst if (verbose > 1) { 106718976Sdfr if (v3) { 106826184Sfenner TCHECK(fap->fa3_ctime); 106975118Sfenner printf("nlink %d rdev %d/%d ", 107075118Sfenner (u_int32_t)ntohl(fap->fa_nlink), 107175118Sfenner (u_int32_t) ntohl(fap->fa3_rdev.specdata1), 107275118Sfenner (u_int32_t) ntohl(fap->fa3_rdev.specdata2)); 107318976Sdfr printf("fsid "); 107418976Sdfr print_int64((u_int32_t *)&fap->fa2_fsid, HEX); 107518976Sdfr printf(" nodeid "); 107618976Sdfr print_int64((u_int32_t *)&fap->fa2_fileid, HEX); 107775118Sfenner printf(" a/m/ctime %u.%06u ", 107875118Sfenner (u_int32_t) ntohl(fap->fa3_atime.nfsv3_sec), 107975118Sfenner (u_int32_t) ntohl(fap->fa3_atime.nfsv3_nsec)); 108075118Sfenner printf("%u.%06u ", 108175118Sfenner (u_int32_t) ntohl(fap->fa3_mtime.nfsv3_sec), 108275118Sfenner (u_int32_t) ntohl(fap->fa3_mtime.nfsv3_nsec)); 108375118Sfenner printf("%u.%06u ", 108475118Sfenner (u_int32_t) ntohl(fap->fa3_ctime.nfsv3_sec), 108575118Sfenner (u_int32_t) ntohl(fap->fa3_ctime.nfsv3_nsec)); 108618976Sdfr } else { 108726184Sfenner TCHECK(fap->fa2_ctime); 108875118Sfenner printf("nlink %d rdev %x fsid %x nodeid %x a/m/ctime ", 108975118Sfenner (u_int32_t) ntohl(fap->fa_nlink), 109075118Sfenner (u_int32_t) ntohl(fap->fa2_rdev), 109175118Sfenner (u_int32_t) ntohl(fap->fa2_fsid), 109275118Sfenner (u_int32_t) ntohl(fap->fa2_fileid)); 109375118Sfenner printf("%u.%06u ", 109475118Sfenner (u_int32_t) ntohl(fap->fa2_atime.nfsv2_sec), 109575118Sfenner (u_int32_t) ntohl(fap->fa2_atime.nfsv2_usec)); 109675118Sfenner printf("%u.%06u ", 109775118Sfenner (u_int32_t) ntohl(fap->fa2_mtime.nfsv2_sec), 109875118Sfenner (u_int32_t) ntohl(fap->fa2_mtime.nfsv2_usec)); 109975118Sfenner printf("%u.%06u ", 110075118Sfenner (u_int32_t) ntohl(fap->fa2_ctime.nfsv2_sec), 110175118Sfenner (u_int32_t) ntohl(fap->fa2_ctime.nfsv2_usec)); 110218976Sdfr } 110317680Spst } 110418976Sdfr return ((const u_int32_t *)((unsigned char *)dp + 110518976Sdfr (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 110626184Sfennertrunc: 110726184Sfenner return (NULL); 110817680Spst} 110917680Spst 111017680Spststatic int 111118976Sdfrparseattrstat(const u_int32_t *dp, int verbose, int v3) 111217680Spst{ 111318976Sdfr int er; 111418976Sdfr 111518976Sdfr dp = parsestatus(dp, &er); 1116111729Sfenner if (dp == NULL) 111717680Spst return (0); 1118111729Sfenner if (er) 1119111729Sfenner return (1); 112017680Spst 112126183Sfenner return (parsefattr(dp, verbose, v3) != NULL); 112217680Spst} 112317680Spst 112417680Spststatic int 112517680Spstparsediropres(const u_int32_t *dp) 112617680Spst{ 112718976Sdfr int er; 112818976Sdfr 1129111729Sfenner if (!(dp = parsestatus(dp, &er))) 113017680Spst return (0); 1131111729Sfenner if (er) 1132111729Sfenner return (1); 113317680Spst 113418976Sdfr dp = parsefh(dp, 0); 113517680Spst if (dp == NULL) 113617680Spst return (0); 113717680Spst 113818976Sdfr return (parsefattr(dp, vflag, 0) != NULL); 113917680Spst} 114017680Spst 114117680Spststatic int 114218976Sdfrparselinkres(const u_int32_t *dp, int v3) 114317680Spst{ 114418976Sdfr int er; 114518976Sdfr 114618976Sdfr dp = parsestatus(dp, &er); 1147111729Sfenner if (dp == NULL) 114817680Spst return(0); 1149111729Sfenner if (er) 1150111729Sfenner return(1); 115175118Sfenner if (v3 && !(dp = parse_post_op_attr(dp, vflag))) 115218976Sdfr return (0); 115317680Spst putchar(' '); 115417680Spst return (parsefn(dp) != NULL); 115517680Spst} 115617680Spst 115717680Spststatic int 115818976Sdfrparsestatfs(const u_int32_t *dp, int v3) 115917680Spst{ 116018976Sdfr const struct nfs_statfs *sfsp; 116118976Sdfr int er; 116217680Spst 116318976Sdfr dp = parsestatus(dp, &er); 1164111729Sfenner if (dp == NULL) 116575118Sfenner return (0); 1166111729Sfenner if (!v3 && er) 1167111729Sfenner return (1); 116817680Spst 116918976Sdfr if (qflag) 117018976Sdfr return(1); 117118976Sdfr 117218976Sdfr if (v3) { 117318976Sdfr if (vflag) 117418976Sdfr printf(" POST:"); 117575118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 117618976Sdfr return (0); 117717680Spst } 117817680Spst 1179111729Sfenner TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 118018976Sdfr 118118976Sdfr sfsp = (const struct nfs_statfs *)dp; 118218976Sdfr 118318976Sdfr if (v3) { 118418976Sdfr printf(" tbytes "); 118518976Sdfr print_int64((u_int32_t *)&sfsp->sf_tbytes, UNSIGNED); 118618976Sdfr printf(" fbytes "); 118718976Sdfr print_int64((u_int32_t *)&sfsp->sf_fbytes, UNSIGNED); 118818976Sdfr printf(" abytes "); 118918976Sdfr print_int64((u_int32_t *)&sfsp->sf_abytes, UNSIGNED); 119018976Sdfr if (vflag) { 119118976Sdfr printf(" tfiles "); 119218976Sdfr print_int64((u_int32_t *)&sfsp->sf_tfiles, UNSIGNED); 119318976Sdfr printf(" ffiles "); 119418976Sdfr print_int64((u_int32_t *)&sfsp->sf_ffiles, UNSIGNED); 119518976Sdfr printf(" afiles "); 119618976Sdfr print_int64((u_int32_t *)&sfsp->sf_afiles, UNSIGNED); 119775118Sfenner printf(" invar %u", 119875118Sfenner (u_int32_t) ntohl(sfsp->sf_invarsec)); 119918976Sdfr } 120018976Sdfr } else { 120175118Sfenner printf(" tsize %d bsize %d blocks %d bfree %d bavail %d", 120275118Sfenner (u_int32_t)ntohl(sfsp->sf_tsize), 120375118Sfenner (u_int32_t)ntohl(sfsp->sf_bsize), 120475118Sfenner (u_int32_t)ntohl(sfsp->sf_blocks), 120575118Sfenner (u_int32_t)ntohl(sfsp->sf_bfree), 120675118Sfenner (u_int32_t)ntohl(sfsp->sf_bavail)); 120718976Sdfr } 120818976Sdfr 120917680Spst return (1); 121026184Sfennertrunc: 121126184Sfenner return (0); 121217680Spst} 121317680Spst 121417680Spststatic int 121517680Spstparserddires(const u_int32_t *dp) 121617680Spst{ 121718976Sdfr int er; 121818976Sdfr 121918976Sdfr dp = parsestatus(dp, &er); 1220111729Sfenner if (dp == NULL) 122117680Spst return (0); 1222111729Sfenner if (er) 1223111729Sfenner return (1); 122418976Sdfr if (qflag) 122518976Sdfr return (1); 122618976Sdfr 122726184Sfenner TCHECK(dp[2]); 122875118Sfenner printf(" offset %x size %d ", 122975118Sfenner (u_int32_t)ntohl(dp[0]), (u_int32_t)ntohl(dp[1])); 123018976Sdfr if (dp[2] != 0) 123175118Sfenner printf(" eof"); 123218976Sdfr 123318976Sdfr return (1); 123426184Sfennertrunc: 123526184Sfenner return (0); 123618976Sdfr} 123718976Sdfr 123818976Sdfrstatic const u_int32_t * 123918976Sdfrparse_wcc_attr(const u_int32_t *dp) 124018976Sdfr{ 124118976Sdfr printf(" sz "); 124218976Sdfr print_int64(dp, UNSIGNED); 124375118Sfenner printf(" mtime %u.%06u ctime %u.%06u", 124475118Sfenner (u_int32_t)ntohl(dp[2]), (u_int32_t)ntohl(dp[3]), 124575118Sfenner (u_int32_t)ntohl(dp[4]), (u_int32_t)ntohl(dp[5])); 124618976Sdfr return (dp + 6); 124718976Sdfr} 124818976Sdfr 124918976Sdfr/* 125018976Sdfr * Pre operation attributes. Print only if vflag > 1. 125118976Sdfr */ 125218976Sdfrstatic const u_int32_t * 125318976Sdfrparse_pre_op_attr(const u_int32_t *dp, int verbose) 125418976Sdfr{ 125526184Sfenner TCHECK(dp[0]); 125618976Sdfr if (!ntohl(dp[0])) 125718976Sdfr return (dp + 1); 125818976Sdfr dp++; 1259111729Sfenner TCHECK2(*dp, 24); 126018976Sdfr if (verbose > 1) { 126118976Sdfr return parse_wcc_attr(dp); 126218976Sdfr } else { 126318976Sdfr /* If not verbose enough, just skip over wcc_attr */ 126418976Sdfr return (dp + 6); 126517680Spst } 126626184Sfennertrunc: 126726184Sfenner return (NULL); 126818976Sdfr} 126917680Spst 127018976Sdfr/* 127118976Sdfr * Post operation attributes are printed if vflag >= 1 127218976Sdfr */ 127318976Sdfrstatic const u_int32_t * 127418976Sdfrparse_post_op_attr(const u_int32_t *dp, int verbose) 127518976Sdfr{ 127626184Sfenner TCHECK(dp[0]); 127718976Sdfr if (!ntohl(dp[0])) 127818976Sdfr return (dp + 1); 127918976Sdfr dp++; 128018976Sdfr if (verbose) { 128118976Sdfr return parsefattr(dp, verbose, 1); 128218976Sdfr } else 128318976Sdfr return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 128426184Sfennertrunc: 128526184Sfenner return (NULL); 128618976Sdfr} 128718976Sdfr 128818976Sdfrstatic const u_int32_t * 128918976Sdfrparse_wcc_data(const u_int32_t *dp, int verbose) 129018976Sdfr{ 129118976Sdfr if (verbose > 1) 129218976Sdfr printf(" PRE:"); 129375118Sfenner if (!(dp = parse_pre_op_attr(dp, verbose))) 129475118Sfenner return (0); 129518976Sdfr 129618976Sdfr if (verbose) 129718976Sdfr printf(" POST:"); 129818976Sdfr return parse_post_op_attr(dp, verbose); 129918976Sdfr} 130018976Sdfr 130118976Sdfrstatic const u_int32_t * 130218976Sdfrparsecreateopres(const u_int32_t *dp, int verbose) 130318976Sdfr{ 130418976Sdfr int er; 130518976Sdfr 130675118Sfenner if (!(dp = parsestatus(dp, &er))) 130775118Sfenner return (0); 130818976Sdfr if (er) 130918976Sdfr dp = parse_wcc_data(dp, verbose); 131018976Sdfr else { 131126184Sfenner TCHECK(dp[0]); 131218976Sdfr if (!ntohl(dp[0])) 131318976Sdfr return (dp + 1); 131418976Sdfr dp++; 131575118Sfenner if (!(dp = parsefh(dp, 1))) 131675118Sfenner return (0); 131718976Sdfr if (verbose) { 131875118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 131975118Sfenner return (0); 132018976Sdfr if (vflag > 1) { 132118976Sdfr printf("dir attr:"); 132218976Sdfr dp = parse_wcc_data(dp, verbose); 132318976Sdfr } 132418976Sdfr } 132518976Sdfr } 132618976Sdfr return (dp); 132726184Sfennertrunc: 132826184Sfenner return (NULL); 132918976Sdfr} 133018976Sdfr 133118976Sdfrstatic int 133218976Sdfrparsewccres(const u_int32_t *dp, int verbose) 133318976Sdfr{ 133418976Sdfr int er; 133518976Sdfr 133675118Sfenner if (!(dp = parsestatus(dp, &er))) 133718976Sdfr return (0); 133875118Sfenner return parse_wcc_data(dp, verbose) != 0; 133918976Sdfr} 134018976Sdfr 134118976Sdfrstatic const u_int32_t * 134218976Sdfrparsev3rddirres(const u_int32_t *dp, int verbose) 134318976Sdfr{ 134418976Sdfr int er; 134518976Sdfr 134675118Sfenner if (!(dp = parsestatus(dp, &er))) 134775118Sfenner return (0); 134818976Sdfr if (vflag) 134918976Sdfr printf(" POST:"); 135075118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 135175118Sfenner return (0); 135218976Sdfr if (er) 135318976Sdfr return dp; 135418976Sdfr if (vflag) { 135526184Sfenner TCHECK(dp[1]); 135626183Sfenner printf(" verf %08x%08x", dp[0], dp[1]); 135718976Sdfr dp += 2; 135818976Sdfr } 135918976Sdfr return dp; 136026184Sfennertrunc: 136126184Sfenner return (NULL); 136218976Sdfr} 136318976Sdfr 136418976Sdfrstatic int 136518976Sdfrparsefsinfo(const u_int32_t *dp) 136618976Sdfr{ 136718976Sdfr struct nfsv3_fsinfo *sfp; 136818976Sdfr int er; 136918976Sdfr 137075118Sfenner if (!(dp = parsestatus(dp, &er))) 137118976Sdfr return (0); 137218976Sdfr if (vflag) 137318976Sdfr printf(" POST:"); 137475118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 137518976Sdfr return (0); 137618976Sdfr if (er) 137718976Sdfr return (1); 137818976Sdfr 137918976Sdfr sfp = (struct nfsv3_fsinfo *)dp; 138026184Sfenner TCHECK(*sfp); 138175118Sfenner printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 138275118Sfenner (u_int32_t) ntohl(sfp->fs_rtmax), 138375118Sfenner (u_int32_t) ntohl(sfp->fs_rtpref), 138475118Sfenner (u_int32_t) ntohl(sfp->fs_wtmax), 138575118Sfenner (u_int32_t) ntohl(sfp->fs_wtpref), 138675118Sfenner (u_int32_t) ntohl(sfp->fs_dtpref)); 138718976Sdfr if (vflag) { 138875118Sfenner printf(" rtmult %u wtmult %u maxfsz ", 138975118Sfenner (u_int32_t) ntohl(sfp->fs_rtmult), 139075118Sfenner (u_int32_t) ntohl(sfp->fs_wtmult)); 139118976Sdfr print_int64((u_int32_t *)&sfp->fs_maxfilesize, UNSIGNED); 139275118Sfenner printf(" delta %u.%06u ", 139375118Sfenner (u_int32_t) ntohl(sfp->fs_timedelta.nfsv3_sec), 139475118Sfenner (u_int32_t) ntohl(sfp->fs_timedelta.nfsv3_nsec)); 139518976Sdfr } 1396111729Sfenner return (1); 1397111729Sfennertrunc: 139875118Sfenner return (0); 139918976Sdfr} 140018976Sdfr 140118976Sdfrstatic int 140218976Sdfrparsepathconf(const u_int32_t *dp) 140318976Sdfr{ 140418976Sdfr int er; 140518976Sdfr struct nfsv3_pathconf *spp; 140618976Sdfr 140775118Sfenner if (!(dp = parsestatus(dp, &er))) 140818976Sdfr return (0); 140918976Sdfr if (vflag) 141018976Sdfr printf(" POST:"); 141175118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 141218976Sdfr return (0); 141318976Sdfr if (er) 141418976Sdfr return (1); 141518976Sdfr 141618976Sdfr spp = (struct nfsv3_pathconf *)dp; 141726184Sfenner TCHECK(*spp); 141818976Sdfr 141975118Sfenner printf(" linkmax %u namemax %u %s %s %s %s", 142075118Sfenner (u_int32_t) ntohl(spp->pc_linkmax), 142175118Sfenner (u_int32_t) ntohl(spp->pc_namemax), 142218976Sdfr ntohl(spp->pc_notrunc) ? "notrunc" : "", 142318976Sdfr ntohl(spp->pc_chownrestricted) ? "chownres" : "", 142418976Sdfr ntohl(spp->pc_caseinsensitive) ? "igncase" : "", 142518976Sdfr ntohl(spp->pc_casepreserving) ? "keepcase" : ""); 1426111729Sfenner return (1); 1427111729Sfennertrunc: 142875118Sfenner return (0); 142917680Spst} 143075118Sfenner 143117680Spststatic void 143218976Sdfrinterp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 143317680Spst{ 143417680Spst register const u_int32_t *dp; 143518976Sdfr register int v3; 143618976Sdfr int er; 143717680Spst 143818976Sdfr v3 = (vers == NFS_VER3); 143918976Sdfr 144018976Sdfr if (!v3 && proc < NFS_NPROCS) 144118976Sdfr proc = nfsv3_procid[proc]; 144218976Sdfr 144317680Spst switch (proc) { 144417680Spst 144517680Spst case NFSPROC_NOOP: 144617680Spst printf(" nop"); 144717680Spst return; 144818976Sdfr 144917680Spst case NFSPROC_NULL: 145017680Spst printf(" null"); 145117680Spst return; 145217680Spst 145317680Spst case NFSPROC_GETATTR: 145417680Spst printf(" getattr"); 145517680Spst dp = parserep(rp, length); 145626183Sfenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 145717680Spst return; 145817680Spst break; 145917680Spst 146017680Spst case NFSPROC_SETATTR: 146117680Spst printf(" setattr"); 146275118Sfenner if (!(dp = parserep(rp, length))) 146317680Spst return; 146418976Sdfr if (v3) { 146575118Sfenner if (parsewccres(dp, vflag)) 146618976Sdfr return; 146718976Sdfr } else { 146818976Sdfr if (parseattrstat(dp, !qflag, 0) != 0) 146918976Sdfr return; 147018976Sdfr } 147117680Spst break; 147217680Spst 147317680Spst case NFSPROC_LOOKUP: 147417680Spst printf(" lookup"); 147575118Sfenner if (!(dp = parserep(rp, length))) 147618976Sdfr break; 147718976Sdfr if (v3) { 147875118Sfenner if (!(dp = parsestatus(dp, &er))) 147918976Sdfr break; 148018976Sdfr if (er) { 148118976Sdfr if (vflag > 1) { 148218976Sdfr printf(" post dattr:"); 148318976Sdfr dp = parse_post_op_attr(dp, vflag); 148418976Sdfr } 148518976Sdfr } else { 148675118Sfenner if (!(dp = parsefh(dp, v3))) 148718976Sdfr break; 148875118Sfenner if ((dp = parse_post_op_attr(dp, vflag)) && 148975118Sfenner vflag > 1) { 149018976Sdfr printf(" post dattr:"); 149118976Sdfr dp = parse_post_op_attr(dp, vflag); 149218976Sdfr } 149318976Sdfr } 149475118Sfenner if (dp) 149518976Sdfr return; 149618976Sdfr } else { 149718976Sdfr if (parsediropres(dp) != 0) 149818976Sdfr return; 149918976Sdfr } 150017680Spst break; 150117680Spst 150218976Sdfr case NFSPROC_ACCESS: 150318976Sdfr printf(" access"); 150498527Sfenner if (!(dp = parserep(rp, length))) 150598527Sfenner break; 150675118Sfenner if (!(dp = parsestatus(dp, &er))) 150718976Sdfr break; 150818976Sdfr if (vflag) 150918976Sdfr printf(" attr:"); 151075118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 151118976Sdfr break; 151218976Sdfr if (!er) 151375118Sfenner printf(" c %04x", (u_int32_t)ntohl(dp[0])); 151418976Sdfr return; 151518976Sdfr 151617680Spst case NFSPROC_READLINK: 151717680Spst printf(" readlink"); 151817680Spst dp = parserep(rp, length); 151926183Sfenner if (dp != NULL && parselinkres(dp, v3) != 0) 152017680Spst return; 152117680Spst break; 152217680Spst 152317680Spst case NFSPROC_READ: 152417680Spst printf(" read"); 152575118Sfenner if (!(dp = parserep(rp, length))) 152618976Sdfr break; 152718976Sdfr if (v3) { 152875118Sfenner if (!(dp = parsestatus(dp, &er))) 152918976Sdfr break; 153075118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 153118976Sdfr break; 153218976Sdfr if (er) 153318976Sdfr return; 153418976Sdfr if (vflag) { 153575118Sfenner TCHECK(dp[1]); 153675118Sfenner printf("%u bytes", (u_int32_t) ntohl(dp[0])); 153718976Sdfr if (ntohl(dp[1])) 153818976Sdfr printf(" EOF"); 153918976Sdfr } 154017680Spst return; 154118976Sdfr } else { 154218976Sdfr if (parseattrstat(dp, vflag, 0) != 0) 154318976Sdfr return; 154418976Sdfr } 154517680Spst break; 154617680Spst 154717680Spst case NFSPROC_WRITE: 154817680Spst printf(" write"); 154975118Sfenner if (!(dp = parserep(rp, length))) 155018976Sdfr break; 155118976Sdfr if (v3) { 155275118Sfenner if (!(dp = parsestatus(dp, &er))) 155318976Sdfr break; 155475118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 155518976Sdfr break; 155618976Sdfr if (er) 155718976Sdfr return; 155818976Sdfr if (vflag) { 155975118Sfenner TCHECK(dp[0]); 156075118Sfenner printf("%u bytes", (u_int32_t) ntohl(dp[0])); 156118976Sdfr if (vflag > 1) { 156275118Sfenner TCHECK(dp[1]); 156318976Sdfr printf(" <%s>", 156475118Sfenner tok2str(nfsv3_writemodes, 156575118Sfenner NULL, ntohl(dp[1]))); 156618976Sdfr } 156718976Sdfr return; 156818976Sdfr } 156918976Sdfr } else { 157018976Sdfr if (parseattrstat(dp, vflag, v3) != 0) 157118976Sdfr return; 157218976Sdfr } 157317680Spst break; 157417680Spst 157517680Spst case NFSPROC_CREATE: 157617680Spst printf(" create"); 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_MKDIR: 158918976Sdfr printf(" mkdir"); 159075118Sfenner if (!(dp = parserep(rp, length))) 159118976Sdfr break; 159218976Sdfr if (v3) { 159375118Sfenner if (parsecreateopres(dp, vflag) != 0) 159418976Sdfr return; 159518976Sdfr } else { 159618976Sdfr if (parsediropres(dp) != 0) 159718976Sdfr return; 159818976Sdfr } 159918976Sdfr break; 160018976Sdfr 160118976Sdfr case NFSPROC_SYMLINK: 160218976Sdfr printf(" symlink"); 160375118Sfenner if (!(dp = parserep(rp, length))) 160418976Sdfr break; 160518976Sdfr if (v3) { 160675118Sfenner if (parsecreateopres(dp, vflag) != 0) 160718976Sdfr return; 160818976Sdfr } else { 160975118Sfenner if (parsestatus(dp, &er) != 0) 161018976Sdfr return; 161118976Sdfr } 161218976Sdfr break; 161318976Sdfr 161418976Sdfr case NFSPROC_MKNOD: 161518976Sdfr printf(" mknod"); 161675118Sfenner if (!(dp = parserep(rp, length))) 161718976Sdfr break; 161875118Sfenner if (parsecreateopres(dp, vflag) != 0) 161917680Spst return; 162017680Spst break; 162117680Spst 162217680Spst case NFSPROC_REMOVE: 162317680Spst printf(" remove"); 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 } 163317680Spst break; 163417680Spst 163518976Sdfr case NFSPROC_RMDIR: 163618976Sdfr printf(" rmdir"); 163775118Sfenner if (!(dp = parserep(rp, length))) 163818976Sdfr break; 163918976Sdfr if (v3) { 164075118Sfenner if (parsewccres(dp, vflag)) 164118976Sdfr return; 164218976Sdfr } else { 164375118Sfenner if (parsestatus(dp, &er) != 0) 164418976Sdfr return; 164518976Sdfr } 164618976Sdfr break; 164718976Sdfr 164817680Spst case NFSPROC_RENAME: 164917680Spst printf(" rename"); 165075118Sfenner if (!(dp = parserep(rp, length))) 165118976Sdfr break; 165218976Sdfr if (v3) { 165375118Sfenner if (!(dp = parsestatus(dp, &er))) 165418976Sdfr break; 165518976Sdfr if (vflag) { 165618976Sdfr printf(" from:"); 165775118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 165818976Sdfr break; 165918976Sdfr printf(" to:"); 166075118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 166118976Sdfr break; 166218976Sdfr } 166317680Spst return; 166418976Sdfr } else { 166575118Sfenner if (parsestatus(dp, &er) != 0) 166618976Sdfr return; 166718976Sdfr } 166817680Spst break; 166917680Spst 167017680Spst case NFSPROC_LINK: 167117680Spst printf(" link"); 167275118Sfenner if (!(dp = parserep(rp, length))) 167318976Sdfr break; 167418976Sdfr if (v3) { 167575118Sfenner if (!(dp = parsestatus(dp, &er))) 167618976Sdfr break; 167718976Sdfr if (vflag) { 167818976Sdfr printf(" file POST:"); 167975118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 168018976Sdfr break; 168118976Sdfr printf(" dir:"); 168275118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 168318976Sdfr break; 168418976Sdfr return; 168518976Sdfr } 168618976Sdfr } else { 168775118Sfenner if (parsestatus(dp, &er) != 0) 168818976Sdfr return; 168918976Sdfr } 169017680Spst break; 169117680Spst 169218976Sdfr case NFSPROC_READDIR: 169318976Sdfr printf(" readdir"); 169475118Sfenner if (!(dp = parserep(rp, length))) 169518976Sdfr break; 169618976Sdfr if (v3) { 169775118Sfenner if (parsev3rddirres(dp, vflag)) 169818976Sdfr return; 169918976Sdfr } else { 170018976Sdfr if (parserddires(dp) != 0) 170118976Sdfr return; 170218976Sdfr } 170318976Sdfr break; 170418976Sdfr 170518976Sdfr case NFSPROC_READDIRPLUS: 170618976Sdfr printf(" readdirplus"); 170775118Sfenner if (!(dp = parserep(rp, length))) 170818976Sdfr break; 170975118Sfenner if (parsev3rddirres(dp, vflag)) 171017680Spst return; 171117680Spst break; 171217680Spst 171318976Sdfr case NFSPROC_FSSTAT: 171418976Sdfr printf(" fsstat"); 171517680Spst dp = parserep(rp, length); 171675118Sfenner if (dp != NULL && parsestatfs(dp, v3) != 0) 171717680Spst return; 171817680Spst break; 171917680Spst 172018976Sdfr case NFSPROC_FSINFO: 172118976Sdfr printf(" fsinfo"); 172217680Spst dp = parserep(rp, length); 172375118Sfenner if (dp != NULL && parsefsinfo(dp) != 0) 172417680Spst return; 172517680Spst break; 172617680Spst 172718976Sdfr case NFSPROC_PATHCONF: 172818976Sdfr printf(" pathconf"); 172917680Spst dp = parserep(rp, length); 173026183Sfenner if (dp != NULL && parsepathconf(dp) != 0) 173117680Spst return; 173217680Spst break; 173317680Spst 173418976Sdfr case NFSPROC_COMMIT: 173518976Sdfr printf(" commit"); 173617680Spst dp = parserep(rp, length); 173726183Sfenner if (dp != NULL && parsewccres(dp, vflag) != 0) 173817680Spst return; 173917680Spst break; 174017680Spst 174117680Spst default: 174226183Sfenner printf(" proc-%u", proc); 174317680Spst return; 174417680Spst } 174518976Sdfrtrunc: 174626183Sfenner if (!nfserr) 174726183Sfenner fputs(" [|nfs]", stdout); 174817680Spst} 1749