14edb46e9SPaul Traina /* 2699fc314SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20943ee2b1SBill Fenner * 21943ee2b1SBill Fenner * $FreeBSD$ 224edb46e9SPaul Traina */ 234edb46e9SPaul Traina 244edb46e9SPaul Traina #ifndef lint 25cc391cceSBruce M Simpson static const char rcsid[] _U_ = 2629292c17SSam Leffler "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.106.2.2 2005/05/06 07:57:18 guy Exp $ (LBL)"; 27943ee2b1SBill Fenner #endif 28943ee2b1SBill Fenner 29943ee2b1SBill Fenner #ifdef HAVE_CONFIG_H 30943ee2b1SBill Fenner #include "config.h" 314edb46e9SPaul Traina #endif 324edb46e9SPaul Traina 33cc391cceSBruce M Simpson #include <tcpdump-stdinc.h> 344edb46e9SPaul Traina 352ebf6c05SBill Fenner #include <pcap.h> 364edb46e9SPaul Traina #include <stdio.h> 374edb46e9SPaul Traina #include <string.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include "interface.h" 404edb46e9SPaul Traina #include "addrtoname.h" 41cc391cceSBruce M Simpson #include "extract.h" 424edb46e9SPaul Traina 43647f50c3SDoug Rabson #include "nfs.h" 444edb46e9SPaul Traina #include "nfsfh.h" 454edb46e9SPaul Traina 46943ee2b1SBill Fenner #include "ip.h" 47943ee2b1SBill Fenner #ifdef INET6 48943ee2b1SBill Fenner #include "ip6.h" 49943ee2b1SBill Fenner #endif 50c1ad1296SSam Leffler #include "rpc_auth.h" 51c1ad1296SSam Leffler #include "rpc_msg.h" 52943ee2b1SBill Fenner 53943ee2b1SBill Fenner static void nfs_printfh(const u_int32_t *, const u_int); 54c1ad1296SSam Leffler static void xid_map_enter(const struct sunrpc_msg *, const u_char *); 55c1ad1296SSam Leffler static int32_t xid_map_find(const struct sunrpc_msg *, const u_char *, 56943ee2b1SBill Fenner u_int32_t *, u_int32_t *); 57c1ad1296SSam Leffler static void interp_reply(const struct sunrpc_msg *, u_int32_t, u_int32_t, int); 58647f50c3SDoug Rabson static const u_int32_t *parse_post_op_attr(const u_int32_t *, int); 59943ee2b1SBill Fenner static void print_sattr3(const struct nfsv3_sattr *sa3, int verbose); 60943ee2b1SBill Fenner static void print_nfsaddr(const u_char *, const char *, const char *); 612ebf6c05SBill Fenner 62647f50c3SDoug Rabson /* 63647f50c3SDoug Rabson * Mapping of old NFS Version 2 RPC numbers to generic numbers. 64647f50c3SDoug Rabson */ 65647f50c3SDoug Rabson u_int32_t nfsv3_procid[NFS_NPROCS] = { 66647f50c3SDoug Rabson NFSPROC_NULL, 67647f50c3SDoug Rabson NFSPROC_GETATTR, 68647f50c3SDoug Rabson NFSPROC_SETATTR, 69647f50c3SDoug Rabson NFSPROC_NOOP, 70647f50c3SDoug Rabson NFSPROC_LOOKUP, 71647f50c3SDoug Rabson NFSPROC_READLINK, 72647f50c3SDoug Rabson NFSPROC_READ, 73647f50c3SDoug Rabson NFSPROC_NOOP, 74647f50c3SDoug Rabson NFSPROC_WRITE, 75647f50c3SDoug Rabson NFSPROC_CREATE, 76647f50c3SDoug Rabson NFSPROC_REMOVE, 77647f50c3SDoug Rabson NFSPROC_RENAME, 78647f50c3SDoug Rabson NFSPROC_LINK, 79647f50c3SDoug Rabson NFSPROC_SYMLINK, 80647f50c3SDoug Rabson NFSPROC_MKDIR, 81647f50c3SDoug Rabson NFSPROC_RMDIR, 82647f50c3SDoug Rabson NFSPROC_READDIR, 83647f50c3SDoug Rabson NFSPROC_FSSTAT, 84647f50c3SDoug Rabson NFSPROC_NOOP, 85647f50c3SDoug Rabson NFSPROC_NOOP, 86647f50c3SDoug Rabson NFSPROC_NOOP, 87647f50c3SDoug Rabson NFSPROC_NOOP, 88647f50c3SDoug Rabson NFSPROC_NOOP, 89647f50c3SDoug Rabson NFSPROC_NOOP, 90647f50c3SDoug Rabson NFSPROC_NOOP, 91647f50c3SDoug Rabson NFSPROC_NOOP 92647f50c3SDoug Rabson }; 93647f50c3SDoug Rabson 94943ee2b1SBill Fenner /* 95943ee2b1SBill Fenner * NFS V2 and V3 status values. 96943ee2b1SBill Fenner * 97943ee2b1SBill Fenner * Some of these come from the RFCs for NFS V2 and V3, with the message 98943ee2b1SBill Fenner * strings taken from the FreeBSD C library "errlst.c". 99943ee2b1SBill Fenner * 100943ee2b1SBill Fenner * Others are errors that are not in the RFC but that I suspect some 101943ee2b1SBill Fenner * NFS servers could return; the values are FreeBSD errno values, as 102943ee2b1SBill Fenner * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS 103943ee2b1SBill Fenner * was primarily BSD-derived. 104943ee2b1SBill Fenner */ 105943ee2b1SBill Fenner static struct tok status2str[] = { 106943ee2b1SBill Fenner { 1, "Operation not permitted" }, /* EPERM */ 107943ee2b1SBill Fenner { 2, "No such file or directory" }, /* ENOENT */ 108943ee2b1SBill Fenner { 5, "Input/output error" }, /* EIO */ 109943ee2b1SBill Fenner { 6, "Device not configured" }, /* ENXIO */ 110943ee2b1SBill Fenner { 11, "Resource deadlock avoided" }, /* EDEADLK */ 111943ee2b1SBill Fenner { 12, "Cannot allocate memory" }, /* ENOMEM */ 112943ee2b1SBill Fenner { 13, "Permission denied" }, /* EACCES */ 113943ee2b1SBill Fenner { 17, "File exists" }, /* EEXIST */ 114943ee2b1SBill Fenner { 18, "Cross-device link" }, /* EXDEV */ 115943ee2b1SBill Fenner { 19, "Operation not supported by device" }, /* ENODEV */ 116943ee2b1SBill Fenner { 20, "Not a directory" }, /* ENOTDIR */ 117943ee2b1SBill Fenner { 21, "Is a directory" }, /* EISDIR */ 118943ee2b1SBill Fenner { 22, "Invalid argument" }, /* EINVAL */ 119943ee2b1SBill Fenner { 26, "Text file busy" }, /* ETXTBSY */ 120943ee2b1SBill Fenner { 27, "File too large" }, /* EFBIG */ 121943ee2b1SBill Fenner { 28, "No space left on device" }, /* ENOSPC */ 122943ee2b1SBill Fenner { 30, "Read-only file system" }, /* EROFS */ 123943ee2b1SBill Fenner { 31, "Too many links" }, /* EMLINK */ 124943ee2b1SBill Fenner { 45, "Operation not supported" }, /* EOPNOTSUPP */ 125943ee2b1SBill Fenner { 62, "Too many levels of symbolic links" }, /* ELOOP */ 126943ee2b1SBill Fenner { 63, "File name too long" }, /* ENAMETOOLONG */ 127943ee2b1SBill Fenner { 66, "Directory not empty" }, /* ENOTEMPTY */ 128943ee2b1SBill Fenner { 69, "Disc quota exceeded" }, /* EDQUOT */ 129943ee2b1SBill Fenner { 70, "Stale NFS file handle" }, /* ESTALE */ 130943ee2b1SBill Fenner { 71, "Too many levels of remote in path" }, /* EREMOTE */ 131943ee2b1SBill Fenner { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */ 132943ee2b1SBill Fenner { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */ 133943ee2b1SBill Fenner { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */ 134943ee2b1SBill Fenner { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */ 135943ee2b1SBill Fenner { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */ 136943ee2b1SBill Fenner { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */ 137943ee2b1SBill Fenner { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */ 138943ee2b1SBill Fenner { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */ 139943ee2b1SBill Fenner { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */ 140943ee2b1SBill Fenner { 0, NULL } 141943ee2b1SBill Fenner }; 142943ee2b1SBill Fenner 143943ee2b1SBill Fenner static struct tok nfsv3_writemodes[] = { 144943ee2b1SBill Fenner { 0, "unstable" }, 145943ee2b1SBill Fenner { 1, "datasync" }, 146943ee2b1SBill Fenner { 2, "filesync" }, 147943ee2b1SBill Fenner { 0, NULL } 148647f50c3SDoug Rabson }; 149647f50c3SDoug Rabson 150647f50c3SDoug Rabson static struct tok type2str[] = { 151647f50c3SDoug Rabson { NFNON, "NON" }, 152647f50c3SDoug Rabson { NFREG, "REG" }, 153647f50c3SDoug Rabson { NFDIR, "DIR" }, 154647f50c3SDoug Rabson { NFBLK, "BLK" }, 155647f50c3SDoug Rabson { NFCHR, "CHR" }, 156647f50c3SDoug Rabson { NFLNK, "LNK" }, 157647f50c3SDoug Rabson { NFFIFO, "FIFO" }, 158647f50c3SDoug Rabson { 0, NULL } 159647f50c3SDoug Rabson }; 160647f50c3SDoug Rabson 161943ee2b1SBill Fenner static void 162943ee2b1SBill Fenner print_nfsaddr(const u_char *bp, const char *s, const char *d) 163943ee2b1SBill Fenner { 164943ee2b1SBill Fenner struct ip *ip; 165943ee2b1SBill Fenner #ifdef INET6 166943ee2b1SBill Fenner struct ip6_hdr *ip6; 167943ee2b1SBill Fenner char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; 168943ee2b1SBill Fenner #else 169943ee2b1SBill Fenner #ifndef INET_ADDRSTRLEN 170943ee2b1SBill Fenner #define INET_ADDRSTRLEN 16 171943ee2b1SBill Fenner #endif 172943ee2b1SBill Fenner char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN]; 173943ee2b1SBill Fenner #endif 174943ee2b1SBill Fenner 175943ee2b1SBill Fenner srcaddr[0] = dstaddr[0] = '\0'; 176943ee2b1SBill Fenner switch (IP_V((struct ip *)bp)) { 177943ee2b1SBill Fenner case 4: 178943ee2b1SBill Fenner ip = (struct ip *)bp; 179943ee2b1SBill Fenner strlcpy(srcaddr, ipaddr_string(&ip->ip_src), sizeof(srcaddr)); 180943ee2b1SBill Fenner strlcpy(dstaddr, ipaddr_string(&ip->ip_dst), sizeof(dstaddr)); 181943ee2b1SBill Fenner break; 182943ee2b1SBill Fenner #ifdef INET6 183943ee2b1SBill Fenner case 6: 184943ee2b1SBill Fenner ip6 = (struct ip6_hdr *)bp; 185943ee2b1SBill Fenner strlcpy(srcaddr, ip6addr_string(&ip6->ip6_src), 186943ee2b1SBill Fenner sizeof(srcaddr)); 187943ee2b1SBill Fenner strlcpy(dstaddr, ip6addr_string(&ip6->ip6_dst), 188943ee2b1SBill Fenner sizeof(dstaddr)); 189943ee2b1SBill Fenner break; 190943ee2b1SBill Fenner #endif 191943ee2b1SBill Fenner default: 192943ee2b1SBill Fenner strlcpy(srcaddr, "?", sizeof(srcaddr)); 193943ee2b1SBill Fenner strlcpy(dstaddr, "?", sizeof(dstaddr)); 194943ee2b1SBill Fenner break; 195943ee2b1SBill Fenner } 196943ee2b1SBill Fenner 197943ee2b1SBill Fenner (void)printf("%s.%s > %s.%s: ", srcaddr, s, dstaddr, d); 198943ee2b1SBill Fenner } 199943ee2b1SBill Fenner 200647f50c3SDoug Rabson static const u_int32_t * 201647f50c3SDoug Rabson parse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3) 202647f50c3SDoug Rabson { 203943ee2b1SBill Fenner TCHECK(dp[0]); 204cc391cceSBruce M Simpson sa3->sa_modeset = EXTRACT_32BITS(dp); 205cc391cceSBruce M Simpson dp++; 206cc391cceSBruce M Simpson if (sa3->sa_modeset) { 207943ee2b1SBill Fenner TCHECK(dp[0]); 208cc391cceSBruce M Simpson sa3->sa_mode = EXTRACT_32BITS(dp); 209cc391cceSBruce M Simpson dp++; 210647f50c3SDoug Rabson } 211647f50c3SDoug Rabson 212943ee2b1SBill Fenner TCHECK(dp[0]); 213cc391cceSBruce M Simpson sa3->sa_uidset = EXTRACT_32BITS(dp); 214cc391cceSBruce M Simpson dp++; 215cc391cceSBruce M Simpson if (sa3->sa_uidset) { 216943ee2b1SBill Fenner TCHECK(dp[0]); 217cc391cceSBruce M Simpson sa3->sa_uid = EXTRACT_32BITS(dp); 218cc391cceSBruce M Simpson dp++; 219647f50c3SDoug Rabson } 220647f50c3SDoug Rabson 221943ee2b1SBill Fenner TCHECK(dp[0]); 222cc391cceSBruce M Simpson sa3->sa_gidset = EXTRACT_32BITS(dp); 223cc391cceSBruce M Simpson dp++; 224cc391cceSBruce M Simpson if (sa3->sa_gidset) { 225943ee2b1SBill Fenner TCHECK(dp[0]); 226cc391cceSBruce M Simpson sa3->sa_gid = EXTRACT_32BITS(dp); 227cc391cceSBruce M Simpson dp++; 228647f50c3SDoug Rabson } 229647f50c3SDoug Rabson 230943ee2b1SBill Fenner TCHECK(dp[0]); 231cc391cceSBruce M Simpson sa3->sa_sizeset = EXTRACT_32BITS(dp); 232cc391cceSBruce M Simpson dp++; 233cc391cceSBruce M Simpson if (sa3->sa_sizeset) { 234943ee2b1SBill Fenner TCHECK(dp[0]); 235cc391cceSBruce M Simpson sa3->sa_size = EXTRACT_32BITS(dp); 236cc391cceSBruce M Simpson dp++; 237647f50c3SDoug Rabson } 238647f50c3SDoug Rabson 239943ee2b1SBill Fenner TCHECK(dp[0]); 240cc391cceSBruce M Simpson sa3->sa_atimetype = EXTRACT_32BITS(dp); 241cc391cceSBruce M Simpson dp++; 242cc391cceSBruce M Simpson if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) { 243943ee2b1SBill Fenner TCHECK(dp[1]); 244cc391cceSBruce M Simpson sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp); 245cc391cceSBruce M Simpson dp++; 246cc391cceSBruce M Simpson sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp); 247cc391cceSBruce M Simpson dp++; 248647f50c3SDoug Rabson } 249647f50c3SDoug Rabson 250943ee2b1SBill Fenner TCHECK(dp[0]); 251cc391cceSBruce M Simpson sa3->sa_mtimetype = EXTRACT_32BITS(dp); 252cc391cceSBruce M Simpson dp++; 253cc391cceSBruce M Simpson if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) { 254943ee2b1SBill Fenner TCHECK(dp[1]); 255cc391cceSBruce M Simpson sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp); 256cc391cceSBruce M Simpson dp++; 257cc391cceSBruce M Simpson sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp); 258cc391cceSBruce M Simpson dp++; 259647f50c3SDoug Rabson } 260647f50c3SDoug Rabson 261647f50c3SDoug Rabson return dp; 262943ee2b1SBill Fenner trunc: 263943ee2b1SBill Fenner return NULL; 264647f50c3SDoug Rabson } 265647f50c3SDoug Rabson 266943ee2b1SBill Fenner static int nfserr; /* true if we error rather than trunc */ 267943ee2b1SBill Fenner 268943ee2b1SBill Fenner static void 269647f50c3SDoug Rabson print_sattr3(const struct nfsv3_sattr *sa3, int verbose) 270647f50c3SDoug Rabson { 271647f50c3SDoug Rabson if (sa3->sa_modeset) 272647f50c3SDoug Rabson printf(" mode %o", sa3->sa_mode); 273647f50c3SDoug Rabson if (sa3->sa_uidset) 274647f50c3SDoug Rabson printf(" uid %u", sa3->sa_uid); 275647f50c3SDoug Rabson if (sa3->sa_gidset) 276647f50c3SDoug Rabson printf(" gid %u", sa3->sa_gid); 277647f50c3SDoug Rabson if (verbose > 1) { 278647f50c3SDoug Rabson if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 279647f50c3SDoug Rabson printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec, 280647f50c3SDoug Rabson sa3->sa_atime.nfsv3_nsec); 281647f50c3SDoug Rabson if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 282647f50c3SDoug Rabson printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 283647f50c3SDoug Rabson sa3->sa_mtime.nfsv3_nsec); 284647f50c3SDoug Rabson } 285647f50c3SDoug Rabson } 2864edb46e9SPaul Traina 2874edb46e9SPaul Traina void 2884edb46e9SPaul Traina nfsreply_print(register const u_char *bp, u_int length, 2894edb46e9SPaul Traina register const u_char *bp2) 2904edb46e9SPaul Traina { 291c1ad1296SSam Leffler register const struct sunrpc_msg *rp; 292647f50c3SDoug Rabson u_int32_t proc, vers; 293943ee2b1SBill Fenner char srcid[20], dstid[20]; /*fits 32bit*/ 2944edb46e9SPaul Traina 2952ebf6c05SBill Fenner nfserr = 0; /* assume no error */ 296c1ad1296SSam Leffler rp = (const struct sunrpc_msg *)bp; 2974edb46e9SPaul Traina 298943ee2b1SBill Fenner if (!nflag) { 299943ee2b1SBill Fenner strlcpy(srcid, "nfs", sizeof(srcid)); 300943ee2b1SBill Fenner snprintf(dstid, sizeof(dstid), "%u", 301cc391cceSBruce M Simpson EXTRACT_32BITS(&rp->rm_xid)); 302943ee2b1SBill Fenner } else { 303943ee2b1SBill Fenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 304943ee2b1SBill Fenner snprintf(dstid, sizeof(dstid), "%u", 305cc391cceSBruce M Simpson EXTRACT_32BITS(&rp->rm_xid)); 306943ee2b1SBill Fenner } 307943ee2b1SBill Fenner print_nfsaddr(bp2, srcid, dstid); 308943ee2b1SBill Fenner (void)printf("reply %s %d", 309c1ad1296SSam Leffler EXTRACT_32BITS(&rp->rm_reply.rp_stat) == SUNRPC_MSG_ACCEPTED? 3104edb46e9SPaul Traina "ok":"ERR", 3114edb46e9SPaul Traina length); 3124edb46e9SPaul Traina 313943ee2b1SBill Fenner if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 314647f50c3SDoug Rabson interp_reply(rp, proc, vers, length); 3154edb46e9SPaul Traina } 3164edb46e9SPaul Traina 3174edb46e9SPaul Traina /* 3184edb46e9SPaul Traina * Return a pointer to the first file handle in the packet. 319943ee2b1SBill Fenner * If the packet was truncated, return 0. 3204edb46e9SPaul Traina */ 3214edb46e9SPaul Traina static const u_int32_t * 322c1ad1296SSam Leffler parsereq(register const struct sunrpc_msg *rp, register u_int length) 3234edb46e9SPaul Traina { 3242ebf6c05SBill Fenner register const u_int32_t *dp; 3254edb46e9SPaul Traina register u_int len; 3264edb46e9SPaul Traina 3274edb46e9SPaul Traina /* 3284edb46e9SPaul Traina * find the start of the req data (if we captured it) 3294edb46e9SPaul Traina */ 3302ebf6c05SBill Fenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 3312ebf6c05SBill Fenner TCHECK(dp[1]); 332cc391cceSBruce M Simpson len = EXTRACT_32BITS(&dp[1]); 3332ebf6c05SBill Fenner if (len < length) { 3342ebf6c05SBill Fenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 3352ebf6c05SBill Fenner TCHECK(dp[1]); 336cc391cceSBruce M Simpson len = EXTRACT_32BITS(&dp[1]); 3372ebf6c05SBill Fenner if (len < length) { 3382ebf6c05SBill Fenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 3392ebf6c05SBill Fenner TCHECK2(dp[0], 0); 3404edb46e9SPaul Traina return (dp); 3414edb46e9SPaul Traina } 3424edb46e9SPaul Traina } 3432ebf6c05SBill Fenner trunc: 3442ebf6c05SBill Fenner return (NULL); 3454edb46e9SPaul Traina } 3464edb46e9SPaul Traina 3474edb46e9SPaul Traina /* 3484edb46e9SPaul Traina * Print out an NFS file handle and return a pointer to following word. 349943ee2b1SBill Fenner * If packet was truncated, return 0. 3504edb46e9SPaul Traina */ 3514edb46e9SPaul Traina static const u_int32_t * 352647f50c3SDoug Rabson parsefh(register const u_int32_t *dp, int v3) 3534edb46e9SPaul Traina { 354cc391cceSBruce M Simpson u_int len; 355647f50c3SDoug Rabson 356647f50c3SDoug Rabson if (v3) { 3572ebf6c05SBill Fenner TCHECK(dp[0]); 358cc391cceSBruce M Simpson len = EXTRACT_32BITS(dp) / 4; 359647f50c3SDoug Rabson dp++; 360647f50c3SDoug Rabson } else 361647f50c3SDoug Rabson len = NFSX_V2FH / 4; 362647f50c3SDoug Rabson 3632ebf6c05SBill Fenner if (TTEST2(*dp, len * sizeof(*dp))) { 364647f50c3SDoug Rabson nfs_printfh(dp, len); 365647f50c3SDoug Rabson return (dp + len); 3664edb46e9SPaul Traina } 3672ebf6c05SBill Fenner trunc: 3682ebf6c05SBill Fenner return (NULL); 3694edb46e9SPaul Traina } 3704edb46e9SPaul Traina 3714edb46e9SPaul Traina /* 3724edb46e9SPaul Traina * Print out a file name and return pointer to 32-bit word past it. 373943ee2b1SBill Fenner * If packet was truncated, return 0. 3744edb46e9SPaul Traina */ 3754edb46e9SPaul Traina static const u_int32_t * 3764edb46e9SPaul Traina parsefn(register const u_int32_t *dp) 3774edb46e9SPaul Traina { 3784edb46e9SPaul Traina register u_int32_t len; 3794edb46e9SPaul Traina register const u_char *cp; 3804edb46e9SPaul Traina 3814edb46e9SPaul Traina /* Bail if we don't have the string length */ 382943ee2b1SBill Fenner TCHECK(*dp); 3834edb46e9SPaul Traina 3844edb46e9SPaul Traina /* Fetch string length; convert to host order */ 3854edb46e9SPaul Traina len = *dp++; 3864edb46e9SPaul Traina NTOHL(len); 3874edb46e9SPaul Traina 388943ee2b1SBill Fenner TCHECK2(*dp, ((len + 3) & ~3)); 389943ee2b1SBill Fenner 3904edb46e9SPaul Traina cp = (u_char *)dp; 3914edb46e9SPaul Traina /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 3924edb46e9SPaul Traina dp += ((len + 3) & ~3) / sizeof(*dp); 3932ebf6c05SBill Fenner putchar('"'); 39429292c17SSam Leffler if (fn_printn(cp, len, snapend)) { 39529292c17SSam Leffler putchar('"'); 39629292c17SSam Leffler goto trunc; 39729292c17SSam Leffler } 3982ebf6c05SBill Fenner putchar('"'); 3994edb46e9SPaul Traina 4004edb46e9SPaul Traina return (dp); 401943ee2b1SBill Fenner trunc: 402943ee2b1SBill Fenner return NULL; 4034edb46e9SPaul Traina } 4044edb46e9SPaul Traina 4054edb46e9SPaul Traina /* 4064edb46e9SPaul Traina * Print out file handle and file name. 4074edb46e9SPaul Traina * Return pointer to 32-bit word past file name. 408943ee2b1SBill Fenner * If packet was truncated (or there was some other error), return 0. 4094edb46e9SPaul Traina */ 4104edb46e9SPaul Traina static const u_int32_t * 411647f50c3SDoug Rabson parsefhn(register const u_int32_t *dp, int v3) 4124edb46e9SPaul Traina { 413647f50c3SDoug Rabson dp = parsefh(dp, v3); 4142ebf6c05SBill Fenner if (dp == NULL) 4152ebf6c05SBill Fenner return (NULL); 4164edb46e9SPaul Traina putchar(' '); 4174edb46e9SPaul Traina return (parsefn(dp)); 4184edb46e9SPaul Traina } 4194edb46e9SPaul Traina 4204edb46e9SPaul Traina void 4214edb46e9SPaul Traina nfsreq_print(register const u_char *bp, u_int length, 4224edb46e9SPaul Traina register const u_char *bp2) 4234edb46e9SPaul Traina { 424c1ad1296SSam Leffler register const struct sunrpc_msg *rp; 4254edb46e9SPaul Traina register const u_int32_t *dp; 426943ee2b1SBill Fenner nfs_type type; 427943ee2b1SBill Fenner int v3; 428943ee2b1SBill Fenner u_int32_t proc; 429647f50c3SDoug Rabson struct nfsv3_sattr sa3; 430943ee2b1SBill Fenner char srcid[20], dstid[20]; /*fits 32bit*/ 4314edb46e9SPaul Traina 4322ebf6c05SBill Fenner nfserr = 0; /* assume no error */ 433c1ad1296SSam Leffler rp = (const struct sunrpc_msg *)bp; 434943ee2b1SBill Fenner if (!nflag) { 435943ee2b1SBill Fenner snprintf(srcid, sizeof(srcid), "%u", 436cc391cceSBruce M Simpson EXTRACT_32BITS(&rp->rm_xid)); 437943ee2b1SBill Fenner strlcpy(dstid, "nfs", sizeof(dstid)); 438943ee2b1SBill Fenner } else { 439943ee2b1SBill Fenner snprintf(srcid, sizeof(srcid), "%u", 440cc391cceSBruce M Simpson EXTRACT_32BITS(&rp->rm_xid)); 441943ee2b1SBill Fenner snprintf(dstid, sizeof(dstid), "%u", NFS_PORT); 442943ee2b1SBill Fenner } 443943ee2b1SBill Fenner print_nfsaddr(bp2, srcid, dstid); 444943ee2b1SBill Fenner (void)printf("%d", length); 4454edb46e9SPaul Traina 446943ee2b1SBill Fenner xid_map_enter(rp, bp2); /* record proc number for later on */ 4474edb46e9SPaul Traina 448cc391cceSBruce M Simpson v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3); 449cc391cceSBruce M Simpson proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 450647f50c3SDoug Rabson 451647f50c3SDoug Rabson if (!v3 && proc < NFS_NPROCS) 452647f50c3SDoug Rabson proc = nfsv3_procid[proc]; 453647f50c3SDoug Rabson 454647f50c3SDoug Rabson switch (proc) { 4554edb46e9SPaul Traina case NFSPROC_NOOP: 4564edb46e9SPaul Traina printf(" nop"); 4574edb46e9SPaul Traina return; 4584edb46e9SPaul Traina case NFSPROC_NULL: 4594edb46e9SPaul Traina printf(" null"); 4604edb46e9SPaul Traina return; 4614edb46e9SPaul Traina 4624edb46e9SPaul Traina case NFSPROC_GETATTR: 4634edb46e9SPaul Traina printf(" getattr"); 464943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 465943ee2b1SBill Fenner parsefh(dp, v3) != NULL) 4664edb46e9SPaul Traina return; 4674edb46e9SPaul Traina break; 4684edb46e9SPaul Traina 4694edb46e9SPaul Traina case NFSPROC_SETATTR: 4704edb46e9SPaul Traina printf(" setattr"); 471943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 472943ee2b1SBill Fenner parsefh(dp, v3) != NULL) 4734edb46e9SPaul Traina return; 4744edb46e9SPaul Traina break; 4754edb46e9SPaul Traina 4764edb46e9SPaul Traina case NFSPROC_LOOKUP: 4774edb46e9SPaul Traina printf(" lookup"); 478943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 479943ee2b1SBill Fenner parsefhn(dp, v3) != NULL) 4804edb46e9SPaul Traina return; 4814edb46e9SPaul Traina break; 4824edb46e9SPaul Traina 483647f50c3SDoug Rabson case NFSPROC_ACCESS: 484647f50c3SDoug Rabson printf(" access"); 4852ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 4862ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 487943ee2b1SBill Fenner TCHECK(dp[0]); 488cc391cceSBruce M Simpson printf(" %04x", EXTRACT_32BITS(&dp[0])); 489647f50c3SDoug Rabson return; 490647f50c3SDoug Rabson } 491647f50c3SDoug Rabson break; 492647f50c3SDoug Rabson 4934edb46e9SPaul Traina case NFSPROC_READLINK: 4944edb46e9SPaul Traina printf(" readlink"); 495943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 496943ee2b1SBill Fenner parsefh(dp, v3) != NULL) 4974edb46e9SPaul Traina return; 4984edb46e9SPaul Traina break; 4994edb46e9SPaul Traina 5004edb46e9SPaul Traina case NFSPROC_READ: 5014edb46e9SPaul Traina printf(" read"); 5022ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5032ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 504647f50c3SDoug Rabson if (v3) { 505943ee2b1SBill Fenner TCHECK(dp[2]); 506c1ad1296SSam Leffler printf(" %u bytes @ %" PRIu64, 507c1ad1296SSam Leffler EXTRACT_32BITS(&dp[2]), 508c1ad1296SSam Leffler EXTRACT_64BITS(&dp[0])); 509647f50c3SDoug Rabson } else { 510943ee2b1SBill Fenner TCHECK(dp[1]); 511943ee2b1SBill Fenner printf(" %u bytes @ %u", 512cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[1]), 513cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[0])); 514647f50c3SDoug Rabson } 5154edb46e9SPaul Traina return; 5164edb46e9SPaul Traina } 5174edb46e9SPaul Traina break; 5184edb46e9SPaul Traina 5194edb46e9SPaul Traina case NFSPROC_WRITE: 5204edb46e9SPaul Traina printf(" write"); 5212ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5222ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 523647f50c3SDoug Rabson if (v3) { 524c1ad1296SSam Leffler TCHECK(dp[2]); 525c1ad1296SSam Leffler printf(" %u (%u) bytes @ %" PRIu64, 526c1ad1296SSam Leffler EXTRACT_32BITS(&dp[4]), 527c1ad1296SSam Leffler EXTRACT_32BITS(&dp[2]), 528c1ad1296SSam Leffler EXTRACT_64BITS(&dp[0])); 529647f50c3SDoug Rabson if (vflag) { 530647f50c3SDoug Rabson dp += 3; 531943ee2b1SBill Fenner TCHECK(dp[0]); 532647f50c3SDoug Rabson printf(" <%s>", 533943ee2b1SBill Fenner tok2str(nfsv3_writemodes, 534cc391cceSBruce M Simpson NULL, EXTRACT_32BITS(dp))); 535647f50c3SDoug Rabson } 536647f50c3SDoug Rabson } else { 537943ee2b1SBill Fenner TCHECK(dp[3]); 538943ee2b1SBill Fenner printf(" %u (%u) bytes @ %u (%u)", 539cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[3]), 540cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[2]), 541cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[1]), 542cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[0])); 543647f50c3SDoug Rabson } 5444edb46e9SPaul Traina return; 5454edb46e9SPaul Traina } 5464edb46e9SPaul Traina break; 5474edb46e9SPaul Traina 5484edb46e9SPaul Traina case NFSPROC_CREATE: 5494edb46e9SPaul Traina printf(" create"); 550943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 551943ee2b1SBill Fenner parsefhn(dp, v3) != NULL) 5524edb46e9SPaul Traina return; 5534edb46e9SPaul Traina break; 5544edb46e9SPaul Traina 555647f50c3SDoug Rabson case NFSPROC_MKDIR: 556647f50c3SDoug Rabson printf(" mkdir"); 557943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) 558647f50c3SDoug Rabson return; 559647f50c3SDoug Rabson break; 560647f50c3SDoug Rabson 561647f50c3SDoug Rabson case NFSPROC_SYMLINK: 562647f50c3SDoug Rabson printf(" symlink"); 563943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != 0 && 564943ee2b1SBill Fenner (dp = parsefhn(dp, v3)) != 0) { 565647f50c3SDoug Rabson fputs(" ->", stdout); 566943ee2b1SBill Fenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) 567647f50c3SDoug Rabson break; 568943ee2b1SBill Fenner if (parsefn(dp) == 0) 569647f50c3SDoug Rabson break; 570647f50c3SDoug Rabson if (v3 && vflag) 571647f50c3SDoug Rabson print_sattr3(&sa3, vflag); 572647f50c3SDoug Rabson return; 573647f50c3SDoug Rabson } 574647f50c3SDoug Rabson break; 575647f50c3SDoug Rabson 576647f50c3SDoug Rabson case NFSPROC_MKNOD: 577647f50c3SDoug Rabson printf(" mknod"); 578943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != 0 && 579943ee2b1SBill Fenner (dp = parsefhn(dp, v3)) != 0) { 580943ee2b1SBill Fenner TCHECK(*dp); 581cc391cceSBruce M Simpson type = (nfs_type)EXTRACT_32BITS(dp); 582cc391cceSBruce M Simpson dp++; 583943ee2b1SBill Fenner if ((dp = parse_sattr3(dp, &sa3)) == 0) 584647f50c3SDoug Rabson break; 585647f50c3SDoug Rabson printf(" %s", tok2str(type2str, "unk-ft %d", type)); 586647f50c3SDoug Rabson if (vflag && (type == NFCHR || type == NFBLK)) { 587943ee2b1SBill Fenner TCHECK(dp[1]); 588943ee2b1SBill Fenner printf(" %u/%u", 589cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[0]), 590cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[1])); 591647f50c3SDoug Rabson dp += 2; 592647f50c3SDoug Rabson } 593647f50c3SDoug Rabson if (vflag) 594647f50c3SDoug Rabson print_sattr3(&sa3, vflag); 595647f50c3SDoug Rabson return; 596647f50c3SDoug Rabson } 597647f50c3SDoug Rabson break; 598647f50c3SDoug Rabson 5994edb46e9SPaul Traina case NFSPROC_REMOVE: 6004edb46e9SPaul Traina printf(" remove"); 601943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 602943ee2b1SBill Fenner parsefhn(dp, v3) != NULL) 603647f50c3SDoug Rabson return; 604647f50c3SDoug Rabson break; 605647f50c3SDoug Rabson 606647f50c3SDoug Rabson case NFSPROC_RMDIR: 607647f50c3SDoug Rabson printf(" rmdir"); 608943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 609943ee2b1SBill Fenner parsefhn(dp, v3) != NULL) 6104edb46e9SPaul Traina return; 6114edb46e9SPaul Traina break; 6124edb46e9SPaul Traina 6134edb46e9SPaul Traina case NFSPROC_RENAME: 6144edb46e9SPaul Traina printf(" rename"); 6152ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6162ebf6c05SBill Fenner (dp = parsefhn(dp, v3)) != NULL) { 6174edb46e9SPaul Traina fputs(" ->", stdout); 6182ebf6c05SBill Fenner if (parsefhn(dp, v3) != NULL) 6194edb46e9SPaul Traina return; 6204edb46e9SPaul Traina } 6214edb46e9SPaul Traina break; 6224edb46e9SPaul Traina 6234edb46e9SPaul Traina case NFSPROC_LINK: 6244edb46e9SPaul Traina printf(" link"); 6252ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6262ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 6274edb46e9SPaul Traina fputs(" ->", stdout); 6282ebf6c05SBill Fenner if (parsefhn(dp, v3) != NULL) 6294edb46e9SPaul Traina return; 6304edb46e9SPaul Traina } 6314edb46e9SPaul Traina break; 6324edb46e9SPaul Traina 6334edb46e9SPaul Traina case NFSPROC_READDIR: 6344edb46e9SPaul Traina printf(" readdir"); 6352ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6362ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 637647f50c3SDoug Rabson if (v3) { 638943ee2b1SBill Fenner TCHECK(dp[4]); 6394edb46e9SPaul Traina /* 640647f50c3SDoug Rabson * We shouldn't really try to interpret the 641647f50c3SDoug Rabson * offset cookie here. 6424edb46e9SPaul Traina */ 643c1ad1296SSam Leffler printf(" %u bytes @ %" PRId64, 644c1ad1296SSam Leffler EXTRACT_32BITS(&dp[4]), 645c1ad1296SSam Leffler EXTRACT_64BITS(&dp[0])); 646647f50c3SDoug Rabson if (vflag) 6472ebf6c05SBill Fenner printf(" verf %08x%08x", dp[2], 648647f50c3SDoug Rabson dp[3]); 649647f50c3SDoug Rabson } else { 650943ee2b1SBill Fenner TCHECK(dp[1]); 651647f50c3SDoug Rabson /* 652647f50c3SDoug Rabson * Print the offset as signed, since -1 is 653647f50c3SDoug Rabson * common, but offsets > 2^31 aren't. 654647f50c3SDoug Rabson */ 655943ee2b1SBill Fenner printf(" %u bytes @ %d", 656cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[1]), 657cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[0])); 658647f50c3SDoug Rabson } 6594edb46e9SPaul Traina return; 6604edb46e9SPaul Traina } 6614edb46e9SPaul Traina break; 6624edb46e9SPaul Traina 663647f50c3SDoug Rabson case NFSPROC_READDIRPLUS: 664647f50c3SDoug Rabson printf(" readdirplus"); 6652ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6662ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 667943ee2b1SBill Fenner TCHECK(dp[4]); 668647f50c3SDoug Rabson /* 669647f50c3SDoug Rabson * We don't try to interpret the offset 670647f50c3SDoug Rabson * cookie here. 671647f50c3SDoug Rabson */ 672c1ad1296SSam Leffler printf(" %u bytes @ %" PRId64, 673c1ad1296SSam Leffler EXTRACT_32BITS(&dp[4]), 674c1ad1296SSam Leffler EXTRACT_64BITS(&dp[0])); 675c1ad1296SSam Leffler if (vflag) { 676c1ad1296SSam Leffler TCHECK(dp[5]); 677943ee2b1SBill Fenner printf(" max %u verf %08x%08x", 678cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[5]), dp[2], dp[3]); 679c1ad1296SSam Leffler } 680647f50c3SDoug Rabson return; 681647f50c3SDoug Rabson } 682647f50c3SDoug Rabson break; 683647f50c3SDoug Rabson 684647f50c3SDoug Rabson case NFSPROC_FSSTAT: 685647f50c3SDoug Rabson printf(" fsstat"); 686943ee2b1SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 687943ee2b1SBill Fenner parsefh(dp, v3) != NULL) 6884edb46e9SPaul Traina return; 6894edb46e9SPaul Traina break; 6904edb46e9SPaul Traina 691647f50c3SDoug Rabson case NFSPROC_FSINFO: 692647f50c3SDoug Rabson printf(" fsinfo"); 6930e0def19SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6940e0def19SBill Fenner parsefh(dp, v3) != NULL) 6950e0def19SBill Fenner return; 696647f50c3SDoug Rabson break; 697647f50c3SDoug Rabson 698647f50c3SDoug Rabson case NFSPROC_PATHCONF: 699647f50c3SDoug Rabson printf(" pathconf"); 7000e0def19SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 7010e0def19SBill Fenner parsefh(dp, v3) != NULL) 7020e0def19SBill Fenner return; 703647f50c3SDoug Rabson break; 704647f50c3SDoug Rabson 705647f50c3SDoug Rabson case NFSPROC_COMMIT: 706647f50c3SDoug Rabson printf(" commit"); 7072ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 7082ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 709c1ad1296SSam Leffler TCHECK(dp[2]); 710c1ad1296SSam Leffler printf(" %u bytes @ %" PRIu64, 711c1ad1296SSam Leffler EXTRACT_32BITS(&dp[2]), 712c1ad1296SSam Leffler EXTRACT_64BITS(&dp[0])); 713647f50c3SDoug Rabson return; 714647f50c3SDoug Rabson } 715647f50c3SDoug Rabson break; 716647f50c3SDoug Rabson 7174edb46e9SPaul Traina default: 718cc391cceSBruce M Simpson printf(" proc-%u", EXTRACT_32BITS(&rp->rm_call.cb_proc)); 7194edb46e9SPaul Traina return; 7204edb46e9SPaul Traina } 721943ee2b1SBill Fenner 7224edb46e9SPaul Traina trunc: 7232ebf6c05SBill Fenner if (!nfserr) 7244edb46e9SPaul Traina fputs(" [|nfs]", stdout); 7254edb46e9SPaul Traina } 7264edb46e9SPaul Traina 7274edb46e9SPaul Traina /* 7284edb46e9SPaul Traina * Print out an NFS file handle. 7294edb46e9SPaul Traina * We assume packet was not truncated before the end of the 7304edb46e9SPaul Traina * file handle pointed to by dp. 7314edb46e9SPaul Traina * 7324edb46e9SPaul Traina * Note: new version (using portable file-handle parser) doesn't produce 7334edb46e9SPaul Traina * generation number. It probably could be made to do that, with some 7344edb46e9SPaul Traina * additional hacking on the parser code. 7354edb46e9SPaul Traina */ 7364edb46e9SPaul Traina static void 737943ee2b1SBill Fenner nfs_printfh(register const u_int32_t *dp, const u_int len) 7384edb46e9SPaul Traina { 7394edb46e9SPaul Traina my_fsid fsid; 7404edb46e9SPaul Traina ino_t ino; 741cc391cceSBruce M Simpson const char *sfsname = NULL; 742cc391cceSBruce M Simpson char *spacep; 7434edb46e9SPaul Traina 744cc391cceSBruce M Simpson if (uflag) { 745cc391cceSBruce M Simpson u_int i; 746cc391cceSBruce M Simpson char const *sep = ""; 747cc391cceSBruce M Simpson 748cc391cceSBruce M Simpson printf(" fh["); 749cc391cceSBruce M Simpson for (i=0; i<len; i++) { 750cc391cceSBruce M Simpson (void)printf("%s%x", sep, dp[i]); 751cc391cceSBruce M Simpson sep = ":"; 752cc391cceSBruce M Simpson } 753cc391cceSBruce M Simpson printf("]"); 754cc391cceSBruce M Simpson return; 755cc391cceSBruce M Simpson } 756cc391cceSBruce M Simpson 757cc391cceSBruce M Simpson Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0); 7584edb46e9SPaul Traina 7594edb46e9SPaul Traina if (sfsname) { 7604edb46e9SPaul Traina /* file system ID is ASCII, not numeric, for this server OS */ 761647f50c3SDoug Rabson static char temp[NFSX_V3FHMAX+1]; 7624edb46e9SPaul Traina 7634edb46e9SPaul Traina /* Make sure string is null-terminated */ 764647f50c3SDoug Rabson strncpy(temp, sfsname, NFSX_V3FHMAX); 765943ee2b1SBill Fenner temp[sizeof(temp) - 1] = '\0'; 7664edb46e9SPaul Traina /* Remove trailing spaces */ 767cc391cceSBruce M Simpson spacep = strchr(temp, ' '); 768cc391cceSBruce M Simpson if (spacep) 769cc391cceSBruce M Simpson *spacep = '\0'; 7704edb46e9SPaul Traina 771943ee2b1SBill Fenner (void)printf(" fh %s/", temp); 7722ebf6c05SBill Fenner } else { 773943ee2b1SBill Fenner (void)printf(" fh %d,%d/", 774943ee2b1SBill Fenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); 7754edb46e9SPaul Traina } 776943ee2b1SBill Fenner 777cc391cceSBruce M Simpson if(fsid.Fsid_dev.Minor == 257) 778943ee2b1SBill Fenner /* Print the undecoded handle */ 779943ee2b1SBill Fenner (void)printf("%s", fsid.Opaque_Handle); 780943ee2b1SBill Fenner else 781943ee2b1SBill Fenner (void)printf("%ld", (long) ino); 7824edb46e9SPaul Traina } 7834edb46e9SPaul Traina 7844edb46e9SPaul Traina /* 7854edb46e9SPaul Traina * Maintain a small cache of recent client.XID.server/proc pairs, to allow 7864edb46e9SPaul Traina * us to match up replies with requests and thus to know how to parse 7874edb46e9SPaul Traina * the reply. 7884edb46e9SPaul Traina */ 7894edb46e9SPaul Traina 7904edb46e9SPaul Traina struct xid_map_entry { 7914edb46e9SPaul Traina u_int32_t xid; /* transaction ID (net order) */ 792943ee2b1SBill Fenner int ipver; /* IP version (4 or 6) */ 793943ee2b1SBill Fenner #ifdef INET6 794943ee2b1SBill Fenner struct in6_addr client; /* client IP address (net order) */ 795943ee2b1SBill Fenner struct in6_addr server; /* server IP address (net order) */ 796943ee2b1SBill Fenner #else 7974edb46e9SPaul Traina struct in_addr client; /* client IP address (net order) */ 7984edb46e9SPaul Traina struct in_addr server; /* server IP address (net order) */ 799943ee2b1SBill Fenner #endif 8004edb46e9SPaul Traina u_int32_t proc; /* call proc number (host order) */ 801647f50c3SDoug Rabson u_int32_t vers; /* program version (host order) */ 8024edb46e9SPaul Traina }; 8034edb46e9SPaul Traina 8044edb46e9SPaul Traina /* 8054edb46e9SPaul Traina * Map entries are kept in an array that we manage as a ring; 8064edb46e9SPaul Traina * new entries are always added at the tail of the ring. Initially, 8074edb46e9SPaul Traina * all the entries are zero and hence don't match anything. 8084edb46e9SPaul Traina */ 8094edb46e9SPaul Traina 8104edb46e9SPaul Traina #define XIDMAPSIZE 64 8114edb46e9SPaul Traina 8124edb46e9SPaul Traina struct xid_map_entry xid_map[XIDMAPSIZE]; 8134edb46e9SPaul Traina 8144edb46e9SPaul Traina int xid_map_next = 0; 8154edb46e9SPaul Traina int xid_map_hint = 0; 8164edb46e9SPaul Traina 8174edb46e9SPaul Traina static void 818c1ad1296SSam Leffler xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp) 8194edb46e9SPaul Traina { 820943ee2b1SBill Fenner struct ip *ip = NULL; 821943ee2b1SBill Fenner #ifdef INET6 822943ee2b1SBill Fenner struct ip6_hdr *ip6 = NULL; 823943ee2b1SBill Fenner #endif 8244edb46e9SPaul Traina struct xid_map_entry *xmep; 8254edb46e9SPaul Traina 826943ee2b1SBill Fenner switch (IP_V((struct ip *)bp)) { 827943ee2b1SBill Fenner case 4: 828943ee2b1SBill Fenner ip = (struct ip *)bp; 829943ee2b1SBill Fenner break; 830943ee2b1SBill Fenner #ifdef INET6 831943ee2b1SBill Fenner case 6: 832943ee2b1SBill Fenner ip6 = (struct ip6_hdr *)bp; 833943ee2b1SBill Fenner break; 834943ee2b1SBill Fenner #endif 835943ee2b1SBill Fenner default: 836943ee2b1SBill Fenner return; 837943ee2b1SBill Fenner } 838943ee2b1SBill Fenner 8394edb46e9SPaul Traina xmep = &xid_map[xid_map_next]; 8404edb46e9SPaul Traina 8414edb46e9SPaul Traina if (++xid_map_next >= XIDMAPSIZE) 8424edb46e9SPaul Traina xid_map_next = 0; 8434edb46e9SPaul Traina 8444edb46e9SPaul Traina xmep->xid = rp->rm_xid; 845943ee2b1SBill Fenner if (ip) { 846943ee2b1SBill Fenner xmep->ipver = 4; 847943ee2b1SBill Fenner memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 848943ee2b1SBill Fenner memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 849943ee2b1SBill Fenner } 850943ee2b1SBill Fenner #ifdef INET6 851943ee2b1SBill Fenner else if (ip6) { 852943ee2b1SBill Fenner xmep->ipver = 6; 853943ee2b1SBill Fenner memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 854943ee2b1SBill Fenner memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 855943ee2b1SBill Fenner } 856943ee2b1SBill Fenner #endif 857cc391cceSBruce M Simpson xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 858cc391cceSBruce M Simpson xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers); 8594edb46e9SPaul Traina } 8604edb46e9SPaul Traina 8612ebf6c05SBill Fenner /* 8622ebf6c05SBill Fenner * Returns 0 and puts NFSPROC_xxx in proc return and 8632ebf6c05SBill Fenner * version in vers return, or returns -1 on failure 8642ebf6c05SBill Fenner */ 865647f50c3SDoug Rabson static int 866c1ad1296SSam Leffler xid_map_find(const struct sunrpc_msg *rp, const u_char *bp, u_int32_t *proc, 867647f50c3SDoug Rabson u_int32_t *vers) 8684edb46e9SPaul Traina { 8694edb46e9SPaul Traina int i; 8704edb46e9SPaul Traina struct xid_map_entry *xmep; 8714edb46e9SPaul Traina u_int32_t xid = rp->rm_xid; 872943ee2b1SBill Fenner struct ip *ip = (struct ip *)bp; 873943ee2b1SBill Fenner #ifdef INET6 874943ee2b1SBill Fenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 875943ee2b1SBill Fenner #endif 876943ee2b1SBill Fenner int cmp; 8774edb46e9SPaul Traina 8784edb46e9SPaul Traina /* Start searching from where we last left off */ 8794edb46e9SPaul Traina i = xid_map_hint; 8804edb46e9SPaul Traina do { 8814edb46e9SPaul Traina xmep = &xid_map[i]; 882943ee2b1SBill Fenner cmp = 1; 883943ee2b1SBill Fenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 884943ee2b1SBill Fenner goto nextitem; 885943ee2b1SBill Fenner switch (xmep->ipver) { 886943ee2b1SBill Fenner case 4: 887943ee2b1SBill Fenner if (memcmp(&ip->ip_src, &xmep->server, 888943ee2b1SBill Fenner sizeof(ip->ip_src)) != 0 || 889943ee2b1SBill Fenner memcmp(&ip->ip_dst, &xmep->client, 890943ee2b1SBill Fenner sizeof(ip->ip_dst)) != 0) { 891943ee2b1SBill Fenner cmp = 0; 892943ee2b1SBill Fenner } 893943ee2b1SBill Fenner break; 894943ee2b1SBill Fenner #ifdef INET6 895943ee2b1SBill Fenner case 6: 896943ee2b1SBill Fenner if (memcmp(&ip6->ip6_src, &xmep->server, 897943ee2b1SBill Fenner sizeof(ip6->ip6_src)) != 0 || 898943ee2b1SBill Fenner memcmp(&ip6->ip6_dst, &xmep->client, 899943ee2b1SBill Fenner sizeof(ip6->ip6_dst)) != 0) { 900943ee2b1SBill Fenner cmp = 0; 901943ee2b1SBill Fenner } 902943ee2b1SBill Fenner break; 903943ee2b1SBill Fenner #endif 904943ee2b1SBill Fenner default: 905943ee2b1SBill Fenner cmp = 0; 906943ee2b1SBill Fenner break; 907943ee2b1SBill Fenner } 908943ee2b1SBill Fenner if (cmp) { 9094edb46e9SPaul Traina /* match */ 9104edb46e9SPaul Traina xid_map_hint = i; 911647f50c3SDoug Rabson *proc = xmep->proc; 912647f50c3SDoug Rabson *vers = xmep->vers; 913647f50c3SDoug Rabson return 0; 9144edb46e9SPaul Traina } 915943ee2b1SBill Fenner nextitem: 9164edb46e9SPaul Traina if (++i >= XIDMAPSIZE) 9174edb46e9SPaul Traina i = 0; 9184edb46e9SPaul Traina } while (i != xid_map_hint); 9194edb46e9SPaul Traina 9204edb46e9SPaul Traina /* search failed */ 921943ee2b1SBill Fenner return (-1); 9224edb46e9SPaul Traina } 9234edb46e9SPaul Traina 9244edb46e9SPaul Traina /* 9254edb46e9SPaul Traina * Routines for parsing reply packets 9264edb46e9SPaul Traina */ 9274edb46e9SPaul Traina 9284edb46e9SPaul Traina /* 9294edb46e9SPaul Traina * Return a pointer to the beginning of the actual results. 930943ee2b1SBill Fenner * If the packet was truncated, return 0. 9314edb46e9SPaul Traina */ 9324edb46e9SPaul Traina static const u_int32_t * 933c1ad1296SSam Leffler parserep(register const struct sunrpc_msg *rp, register u_int length) 9344edb46e9SPaul Traina { 9354edb46e9SPaul Traina register const u_int32_t *dp; 936943ee2b1SBill Fenner u_int len; 937c1ad1296SSam Leffler enum sunrpc_accept_stat astat; 9384edb46e9SPaul Traina 9394edb46e9SPaul Traina /* 9404edb46e9SPaul Traina * Portability note: 9414edb46e9SPaul Traina * Here we find the address of the ar_verf credentials. 9424edb46e9SPaul Traina * Originally, this calculation was 9434edb46e9SPaul Traina * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 9444edb46e9SPaul Traina * On the wire, the rp_acpt field starts immediately after 9454edb46e9SPaul Traina * the (32 bit) rp_stat field. However, rp_acpt (which is a 9464edb46e9SPaul Traina * "struct accepted_reply") contains a "struct opaque_auth", 9474edb46e9SPaul Traina * whose internal representation contains a pointer, so on a 9484edb46e9SPaul Traina * 64-bit machine the compiler inserts 32 bits of padding 9494edb46e9SPaul Traina * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 9504edb46e9SPaul Traina * the internal representation to parse the on-the-wire 9514edb46e9SPaul Traina * representation. Instead, we skip past the rp_stat field, 9524edb46e9SPaul Traina * which is an "enum" and so occupies one 32-bit word. 9534edb46e9SPaul Traina */ 9544edb46e9SPaul Traina dp = ((const u_int32_t *)&rp->rm_reply) + 1; 955943ee2b1SBill Fenner TCHECK(dp[1]); 956cc391cceSBruce M Simpson len = EXTRACT_32BITS(&dp[1]); 9574edb46e9SPaul Traina if (len >= length) 9582ebf6c05SBill Fenner return (NULL); 9594edb46e9SPaul Traina /* 9604edb46e9SPaul Traina * skip past the ar_verf credentials. 9614edb46e9SPaul Traina */ 9624edb46e9SPaul Traina dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 9632ebf6c05SBill Fenner TCHECK2(dp[0], 0); 9644edb46e9SPaul Traina 9654edb46e9SPaul Traina /* 9664edb46e9SPaul Traina * now we can check the ar_stat field 9674edb46e9SPaul Traina */ 96829292c17SSam Leffler astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); 9694edb46e9SPaul Traina switch (astat) { 9704edb46e9SPaul Traina 971c1ad1296SSam Leffler case SUNRPC_SUCCESS: 9724edb46e9SPaul Traina break; 9734edb46e9SPaul Traina 974c1ad1296SSam Leffler case SUNRPC_PROG_UNAVAIL: 9754edb46e9SPaul Traina printf(" PROG_UNAVAIL"); 9762ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 9772ebf6c05SBill Fenner return (NULL); 9784edb46e9SPaul Traina 979c1ad1296SSam Leffler case SUNRPC_PROG_MISMATCH: 9804edb46e9SPaul Traina printf(" PROG_MISMATCH"); 9812ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 9822ebf6c05SBill Fenner return (NULL); 9834edb46e9SPaul Traina 984c1ad1296SSam Leffler case SUNRPC_PROC_UNAVAIL: 9854edb46e9SPaul Traina printf(" PROC_UNAVAIL"); 9862ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 9872ebf6c05SBill Fenner return (NULL); 9884edb46e9SPaul Traina 989c1ad1296SSam Leffler case SUNRPC_GARBAGE_ARGS: 9904edb46e9SPaul Traina printf(" GARBAGE_ARGS"); 9912ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 9922ebf6c05SBill Fenner return (NULL); 9934edb46e9SPaul Traina 994c1ad1296SSam Leffler case SUNRPC_SYSTEM_ERR: 9954edb46e9SPaul Traina printf(" SYSTEM_ERR"); 9962ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 9972ebf6c05SBill Fenner return (NULL); 9984edb46e9SPaul Traina 9994edb46e9SPaul Traina default: 10004edb46e9SPaul Traina printf(" ar_stat %d", astat); 10012ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 10022ebf6c05SBill Fenner return (NULL); 10034edb46e9SPaul Traina } 10044edb46e9SPaul Traina /* successful return */ 1005943ee2b1SBill Fenner TCHECK2(*dp, sizeof(astat)); 10064edb46e9SPaul Traina return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 10072ebf6c05SBill Fenner trunc: 1008943ee2b1SBill Fenner return (0); 10094edb46e9SPaul Traina } 10104edb46e9SPaul Traina 1011647f50c3SDoug Rabson static const u_int32_t * 1012647f50c3SDoug Rabson parsestatus(const u_int32_t *dp, int *er) 1013647f50c3SDoug Rabson { 1014943ee2b1SBill Fenner int errnum; 1015647f50c3SDoug Rabson 10162ebf6c05SBill Fenner TCHECK(dp[0]); 1017943ee2b1SBill Fenner 1018cc391cceSBruce M Simpson errnum = EXTRACT_32BITS(&dp[0]); 1019647f50c3SDoug Rabson if (er) 10202ebf6c05SBill Fenner *er = errnum; 10212ebf6c05SBill Fenner if (errnum != 0) { 10222ebf6c05SBill Fenner if (!qflag) 1023943ee2b1SBill Fenner printf(" ERROR: %s", 1024943ee2b1SBill Fenner tok2str(status2str, "unk %d", errnum)); 10252ebf6c05SBill Fenner nfserr = 1; 10264edb46e9SPaul Traina } 10274edb46e9SPaul Traina return (dp + 1); 10282ebf6c05SBill Fenner trunc: 1029943ee2b1SBill Fenner return NULL; 10304edb46e9SPaul Traina } 10314edb46e9SPaul Traina 10324edb46e9SPaul Traina static const u_int32_t * 1033647f50c3SDoug Rabson parsefattr(const u_int32_t *dp, int verbose, int v3) 10344edb46e9SPaul Traina { 1035647f50c3SDoug Rabson const struct nfs_fattr *fap; 10364edb46e9SPaul Traina 1037647f50c3SDoug Rabson fap = (const struct nfs_fattr *)dp; 1038685b49deSBill Fenner TCHECK(fap->fa_gid); 10394edb46e9SPaul Traina if (verbose) { 1040943ee2b1SBill Fenner printf(" %s %o ids %d/%d", 1041943ee2b1SBill Fenner tok2str(type2str, "unk-ft %d ", 1042cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_type)), 1043cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_mode), 1044cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_uid), 1045cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_gid)); 1046647f50c3SDoug Rabson if (v3) { 1047685b49deSBill Fenner TCHECK(fap->fa3_size); 1048c1ad1296SSam Leffler printf(" sz %" PRIu64, 1049c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&fap->fa3_size)); 1050685b49deSBill Fenner } else { 1051685b49deSBill Fenner TCHECK(fap->fa2_size); 1052cc391cceSBruce M Simpson printf(" sz %d", EXTRACT_32BITS(&fap->fa2_size)); 1053647f50c3SDoug Rabson } 10544edb46e9SPaul Traina } 10554edb46e9SPaul Traina /* print lots more stuff */ 10564edb46e9SPaul Traina if (verbose > 1) { 1057647f50c3SDoug Rabson if (v3) { 1058685b49deSBill Fenner TCHECK(fap->fa3_ctime); 1059943ee2b1SBill Fenner printf(" nlink %d rdev %d/%d", 1060cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_nlink), 1061cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_rdev.specdata1), 1062cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_rdev.specdata2)); 1063c1ad1296SSam Leffler printf(" fsid %" PRIx64, 1064c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&fap->fa3_fsid)); 1065c1ad1296SSam Leffler printf(" fileid %" PRIx64, 1066c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&fap->fa3_fileid)); 1067943ee2b1SBill Fenner printf(" a/m/ctime %u.%06u", 1068cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec), 1069cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)); 1070943ee2b1SBill Fenner printf(" %u.%06u", 1071cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec), 1072cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)); 1073943ee2b1SBill Fenner printf(" %u.%06u", 1074cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec), 1075cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)); 1076647f50c3SDoug Rabson } else { 1077685b49deSBill Fenner TCHECK(fap->fa2_ctime); 1078943ee2b1SBill Fenner printf(" nlink %d rdev %x fsid %x nodeid %x a/m/ctime", 1079cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa_nlink), 1080cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_rdev), 1081cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_fsid), 1082cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_fileid)); 1083943ee2b1SBill Fenner printf(" %u.%06u", 1084cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec), 1085cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)); 1086943ee2b1SBill Fenner printf(" %u.%06u", 1087cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec), 1088cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)); 1089943ee2b1SBill Fenner printf(" %u.%06u", 1090cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec), 1091cc391cceSBruce M Simpson EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)); 10924edb46e9SPaul Traina } 1093647f50c3SDoug Rabson } 1094647f50c3SDoug Rabson return ((const u_int32_t *)((unsigned char *)dp + 1095647f50c3SDoug Rabson (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 1096685b49deSBill Fenner trunc: 1097685b49deSBill Fenner return (NULL); 10984edb46e9SPaul Traina } 10994edb46e9SPaul Traina 11004edb46e9SPaul Traina static int 1101647f50c3SDoug Rabson parseattrstat(const u_int32_t *dp, int verbose, int v3) 11024edb46e9SPaul Traina { 1103647f50c3SDoug Rabson int er; 1104647f50c3SDoug Rabson 1105647f50c3SDoug Rabson dp = parsestatus(dp, &er); 11060e0def19SBill Fenner if (dp == NULL) 11074edb46e9SPaul Traina return (0); 11080e0def19SBill Fenner if (er) 11090e0def19SBill Fenner return (1); 11104edb46e9SPaul Traina 11112ebf6c05SBill Fenner return (parsefattr(dp, verbose, v3) != NULL); 11124edb46e9SPaul Traina } 11134edb46e9SPaul Traina 11144edb46e9SPaul Traina static int 11154edb46e9SPaul Traina parsediropres(const u_int32_t *dp) 11164edb46e9SPaul Traina { 1117647f50c3SDoug Rabson int er; 1118647f50c3SDoug Rabson 11190e0def19SBill Fenner if (!(dp = parsestatus(dp, &er))) 1120647f50c3SDoug Rabson return (0); 11210e0def19SBill Fenner if (er) 11220e0def19SBill Fenner return (1); 1123647f50c3SDoug Rabson 1124647f50c3SDoug Rabson dp = parsefh(dp, 0); 11254edb46e9SPaul Traina if (dp == NULL) 11264edb46e9SPaul Traina return (0); 11274edb46e9SPaul Traina 1128647f50c3SDoug Rabson return (parsefattr(dp, vflag, 0) != NULL); 11294edb46e9SPaul Traina } 11304edb46e9SPaul Traina 11314edb46e9SPaul Traina static int 1132647f50c3SDoug Rabson parselinkres(const u_int32_t *dp, int v3) 11334edb46e9SPaul Traina { 1134647f50c3SDoug Rabson int er; 11354edb46e9SPaul Traina 1136647f50c3SDoug Rabson dp = parsestatus(dp, &er); 11370e0def19SBill Fenner if (dp == NULL) 1138647f50c3SDoug Rabson return(0); 11390e0def19SBill Fenner if (er) 11400e0def19SBill Fenner return(1); 1141943ee2b1SBill Fenner if (v3 && !(dp = parse_post_op_attr(dp, vflag))) 1142647f50c3SDoug Rabson return (0); 11434edb46e9SPaul Traina putchar(' '); 11444edb46e9SPaul Traina return (parsefn(dp) != NULL); 11454edb46e9SPaul Traina } 11464edb46e9SPaul Traina 11474edb46e9SPaul Traina static int 1148647f50c3SDoug Rabson parsestatfs(const u_int32_t *dp, int v3) 11494edb46e9SPaul Traina { 1150647f50c3SDoug Rabson const struct nfs_statfs *sfsp; 1151647f50c3SDoug Rabson int er; 11524edb46e9SPaul Traina 1153647f50c3SDoug Rabson dp = parsestatus(dp, &er); 11540e0def19SBill Fenner if (dp == NULL) 11554edb46e9SPaul Traina return (0); 11560e0def19SBill Fenner if (!v3 && er) 11570e0def19SBill Fenner return (1); 11584edb46e9SPaul Traina 1159647f50c3SDoug Rabson if (qflag) 1160647f50c3SDoug Rabson return(1); 1161647f50c3SDoug Rabson 1162647f50c3SDoug Rabson if (v3) { 1163647f50c3SDoug Rabson if (vflag) 1164647f50c3SDoug Rabson printf(" POST:"); 1165943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1166647f50c3SDoug Rabson return (0); 1167647f50c3SDoug Rabson } 1168647f50c3SDoug Rabson 11690e0def19SBill Fenner TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 1170647f50c3SDoug Rabson 1171647f50c3SDoug Rabson sfsp = (const struct nfs_statfs *)dp; 1172647f50c3SDoug Rabson 1173647f50c3SDoug Rabson if (v3) { 1174c1ad1296SSam Leffler printf(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64, 1175c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tbytes), 1176c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_fbytes), 1177c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_abytes)); 1178647f50c3SDoug Rabson if (vflag) { 1179c1ad1296SSam Leffler printf(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u", 1180c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tfiles), 1181c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_ffiles), 1182c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfsp->sf_afiles), 1183cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_invarsec)); 1184647f50c3SDoug Rabson } 1185647f50c3SDoug Rabson } else { 1186943ee2b1SBill Fenner printf(" tsize %d bsize %d blocks %d bfree %d bavail %d", 1187cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_tsize), 1188cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_bsize), 1189cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_blocks), 1190cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_bfree), 1191cc391cceSBruce M Simpson EXTRACT_32BITS(&sfsp->sf_bavail)); 11924edb46e9SPaul Traina } 11934edb46e9SPaul Traina 11944edb46e9SPaul Traina return (1); 1195685b49deSBill Fenner trunc: 1196685b49deSBill Fenner return (0); 11974edb46e9SPaul Traina } 11984edb46e9SPaul Traina 11994edb46e9SPaul Traina static int 12004edb46e9SPaul Traina parserddires(const u_int32_t *dp) 12014edb46e9SPaul Traina { 1202647f50c3SDoug Rabson int er; 1203647f50c3SDoug Rabson 1204647f50c3SDoug Rabson dp = parsestatus(dp, &er); 12050e0def19SBill Fenner if (dp == NULL) 12064edb46e9SPaul Traina return (0); 12070e0def19SBill Fenner if (er) 12080e0def19SBill Fenner return (1); 1209647f50c3SDoug Rabson if (qflag) 1210647f50c3SDoug Rabson return (1); 1211647f50c3SDoug Rabson 1212685b49deSBill Fenner TCHECK(dp[2]); 1213943ee2b1SBill Fenner printf(" offset %x size %d ", 1214cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])); 12154edb46e9SPaul Traina if (dp[2] != 0) 12164edb46e9SPaul Traina printf(" eof"); 12174edb46e9SPaul Traina 12184edb46e9SPaul Traina return (1); 1219685b49deSBill Fenner trunc: 1220685b49deSBill Fenner return (0); 1221647f50c3SDoug Rabson } 1222647f50c3SDoug Rabson 1223647f50c3SDoug Rabson static const u_int32_t * 1224647f50c3SDoug Rabson parse_wcc_attr(const u_int32_t *dp) 1225647f50c3SDoug Rabson { 1226c1ad1296SSam Leffler printf(" sz %" PRIu64, EXTRACT_64BITS(&dp[0])); 1227943ee2b1SBill Fenner printf(" mtime %u.%06u ctime %u.%06u", 1228cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]), 1229cc391cceSBruce M Simpson EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])); 1230647f50c3SDoug Rabson return (dp + 6); 1231647f50c3SDoug Rabson } 1232647f50c3SDoug Rabson 1233647f50c3SDoug Rabson /* 1234647f50c3SDoug Rabson * Pre operation attributes. Print only if vflag > 1. 1235647f50c3SDoug Rabson */ 1236647f50c3SDoug Rabson static const u_int32_t * 1237647f50c3SDoug Rabson parse_pre_op_attr(const u_int32_t *dp, int verbose) 1238647f50c3SDoug Rabson { 1239685b49deSBill Fenner TCHECK(dp[0]); 1240cc391cceSBruce M Simpson if (!EXTRACT_32BITS(&dp[0])) 1241647f50c3SDoug Rabson return (dp + 1); 1242647f50c3SDoug Rabson dp++; 12430e0def19SBill Fenner TCHECK2(*dp, 24); 1244647f50c3SDoug Rabson if (verbose > 1) { 1245647f50c3SDoug Rabson return parse_wcc_attr(dp); 1246647f50c3SDoug Rabson } else { 1247647f50c3SDoug Rabson /* If not verbose enough, just skip over wcc_attr */ 1248647f50c3SDoug Rabson return (dp + 6); 1249647f50c3SDoug Rabson } 1250685b49deSBill Fenner trunc: 1251685b49deSBill Fenner return (NULL); 1252647f50c3SDoug Rabson } 1253647f50c3SDoug Rabson 1254647f50c3SDoug Rabson /* 1255647f50c3SDoug Rabson * Post operation attributes are printed if vflag >= 1 1256647f50c3SDoug Rabson */ 1257647f50c3SDoug Rabson static const u_int32_t * 1258647f50c3SDoug Rabson parse_post_op_attr(const u_int32_t *dp, int verbose) 1259647f50c3SDoug Rabson { 1260685b49deSBill Fenner TCHECK(dp[0]); 1261cc391cceSBruce M Simpson if (!EXTRACT_32BITS(&dp[0])) 1262647f50c3SDoug Rabson return (dp + 1); 1263647f50c3SDoug Rabson dp++; 1264647f50c3SDoug Rabson if (verbose) { 1265647f50c3SDoug Rabson return parsefattr(dp, verbose, 1); 1266647f50c3SDoug Rabson } else 1267647f50c3SDoug Rabson return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 1268685b49deSBill Fenner trunc: 1269685b49deSBill Fenner return (NULL); 1270647f50c3SDoug Rabson } 1271647f50c3SDoug Rabson 1272647f50c3SDoug Rabson static const u_int32_t * 1273647f50c3SDoug Rabson parse_wcc_data(const u_int32_t *dp, int verbose) 1274647f50c3SDoug Rabson { 1275647f50c3SDoug Rabson if (verbose > 1) 1276647f50c3SDoug Rabson printf(" PRE:"); 1277943ee2b1SBill Fenner if (!(dp = parse_pre_op_attr(dp, verbose))) 1278943ee2b1SBill Fenner return (0); 1279647f50c3SDoug Rabson 1280647f50c3SDoug Rabson if (verbose) 1281647f50c3SDoug Rabson printf(" POST:"); 1282647f50c3SDoug Rabson return parse_post_op_attr(dp, verbose); 1283647f50c3SDoug Rabson } 1284647f50c3SDoug Rabson 1285647f50c3SDoug Rabson static const u_int32_t * 1286647f50c3SDoug Rabson parsecreateopres(const u_int32_t *dp, int verbose) 1287647f50c3SDoug Rabson { 1288647f50c3SDoug Rabson int er; 1289647f50c3SDoug Rabson 1290943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1291943ee2b1SBill Fenner return (0); 1292647f50c3SDoug Rabson if (er) 1293647f50c3SDoug Rabson dp = parse_wcc_data(dp, verbose); 1294647f50c3SDoug Rabson else { 1295685b49deSBill Fenner TCHECK(dp[0]); 1296cc391cceSBruce M Simpson if (!EXTRACT_32BITS(&dp[0])) 1297647f50c3SDoug Rabson return (dp + 1); 1298647f50c3SDoug Rabson dp++; 1299943ee2b1SBill Fenner if (!(dp = parsefh(dp, 1))) 1300943ee2b1SBill Fenner return (0); 1301647f50c3SDoug Rabson if (verbose) { 1302943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, verbose))) 1303943ee2b1SBill Fenner return (0); 1304647f50c3SDoug Rabson if (vflag > 1) { 1305647f50c3SDoug Rabson printf(" dir attr:"); 1306647f50c3SDoug Rabson dp = parse_wcc_data(dp, verbose); 1307647f50c3SDoug Rabson } 1308647f50c3SDoug Rabson } 1309647f50c3SDoug Rabson } 1310647f50c3SDoug Rabson return (dp); 1311685b49deSBill Fenner trunc: 1312685b49deSBill Fenner return (NULL); 1313647f50c3SDoug Rabson } 1314647f50c3SDoug Rabson 1315647f50c3SDoug Rabson static int 1316647f50c3SDoug Rabson parsewccres(const u_int32_t *dp, int verbose) 1317647f50c3SDoug Rabson { 1318647f50c3SDoug Rabson int er; 1319647f50c3SDoug Rabson 1320943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1321647f50c3SDoug Rabson return (0); 1322943ee2b1SBill Fenner return parse_wcc_data(dp, verbose) != 0; 1323647f50c3SDoug Rabson } 1324647f50c3SDoug Rabson 1325647f50c3SDoug Rabson static const u_int32_t * 1326647f50c3SDoug Rabson parsev3rddirres(const u_int32_t *dp, int verbose) 1327647f50c3SDoug Rabson { 1328647f50c3SDoug Rabson int er; 1329647f50c3SDoug Rabson 1330943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1331943ee2b1SBill Fenner return (0); 1332647f50c3SDoug Rabson if (vflag) 1333647f50c3SDoug Rabson printf(" POST:"); 1334943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, verbose))) 1335943ee2b1SBill Fenner return (0); 1336647f50c3SDoug Rabson if (er) 1337647f50c3SDoug Rabson return dp; 1338647f50c3SDoug Rabson if (vflag) { 1339685b49deSBill Fenner TCHECK(dp[1]); 13402ebf6c05SBill Fenner printf(" verf %08x%08x", dp[0], dp[1]); 1341647f50c3SDoug Rabson dp += 2; 1342647f50c3SDoug Rabson } 1343647f50c3SDoug Rabson return dp; 1344685b49deSBill Fenner trunc: 1345685b49deSBill Fenner return (NULL); 1346647f50c3SDoug Rabson } 1347647f50c3SDoug Rabson 1348647f50c3SDoug Rabson static int 1349647f50c3SDoug Rabson parsefsinfo(const u_int32_t *dp) 1350647f50c3SDoug Rabson { 1351647f50c3SDoug Rabson struct nfsv3_fsinfo *sfp; 1352647f50c3SDoug Rabson int er; 1353647f50c3SDoug Rabson 1354943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1355647f50c3SDoug Rabson return (0); 1356647f50c3SDoug Rabson if (vflag) 1357647f50c3SDoug Rabson printf(" POST:"); 1358943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1359647f50c3SDoug Rabson return (0); 1360647f50c3SDoug Rabson if (er) 1361647f50c3SDoug Rabson return (1); 1362647f50c3SDoug Rabson 1363647f50c3SDoug Rabson sfp = (struct nfsv3_fsinfo *)dp; 1364685b49deSBill Fenner TCHECK(*sfp); 1365943ee2b1SBill Fenner printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 1366cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_rtmax), 1367cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_rtpref), 1368cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_wtmax), 1369cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_wtpref), 1370cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_dtpref)); 1371647f50c3SDoug Rabson if (vflag) { 1372c1ad1296SSam Leffler printf(" rtmult %u wtmult %u maxfsz %" PRIu64, 1373cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_rtmult), 1374c1ad1296SSam Leffler EXTRACT_32BITS(&sfp->fs_wtmult), 1375c1ad1296SSam Leffler EXTRACT_64BITS((u_int32_t *)&sfp->fs_maxfilesize)); 1376943ee2b1SBill Fenner printf(" delta %u.%06u ", 1377cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec), 1378cc391cceSBruce M Simpson EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)); 1379647f50c3SDoug Rabson } 1380943ee2b1SBill Fenner return (1); 13810e0def19SBill Fenner trunc: 13820e0def19SBill Fenner return (0); 1383647f50c3SDoug Rabson } 1384647f50c3SDoug Rabson 1385647f50c3SDoug Rabson static int 1386647f50c3SDoug Rabson parsepathconf(const u_int32_t *dp) 1387647f50c3SDoug Rabson { 1388647f50c3SDoug Rabson int er; 1389647f50c3SDoug Rabson struct nfsv3_pathconf *spp; 1390647f50c3SDoug Rabson 1391943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1392647f50c3SDoug Rabson return (0); 1393647f50c3SDoug Rabson if (vflag) 1394647f50c3SDoug Rabson printf(" POST:"); 1395943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1396647f50c3SDoug Rabson return (0); 1397647f50c3SDoug Rabson if (er) 1398647f50c3SDoug Rabson return (1); 1399647f50c3SDoug Rabson 1400647f50c3SDoug Rabson spp = (struct nfsv3_pathconf *)dp; 1401685b49deSBill Fenner TCHECK(*spp); 1402647f50c3SDoug Rabson 1403943ee2b1SBill Fenner printf(" linkmax %u namemax %u %s %s %s %s", 1404cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_linkmax), 1405cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_namemax), 1406cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "", 1407cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "", 1408cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "", 1409cc391cceSBruce M Simpson EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""); 1410943ee2b1SBill Fenner return (1); 14110e0def19SBill Fenner trunc: 14120e0def19SBill Fenner return (0); 14134edb46e9SPaul Traina } 14144edb46e9SPaul Traina 14154edb46e9SPaul Traina static void 1416c1ad1296SSam Leffler interp_reply(const struct sunrpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 14174edb46e9SPaul Traina { 14184edb46e9SPaul Traina register const u_int32_t *dp; 1419647f50c3SDoug Rabson register int v3; 1420647f50c3SDoug Rabson int er; 1421647f50c3SDoug Rabson 1422647f50c3SDoug Rabson v3 = (vers == NFS_VER3); 1423647f50c3SDoug Rabson 1424647f50c3SDoug Rabson if (!v3 && proc < NFS_NPROCS) 1425647f50c3SDoug Rabson proc = nfsv3_procid[proc]; 14264edb46e9SPaul Traina 14274edb46e9SPaul Traina switch (proc) { 14284edb46e9SPaul Traina 14294edb46e9SPaul Traina case NFSPROC_NOOP: 14304edb46e9SPaul Traina printf(" nop"); 14314edb46e9SPaul Traina return; 1432647f50c3SDoug Rabson 14334edb46e9SPaul Traina case NFSPROC_NULL: 14344edb46e9SPaul Traina printf(" null"); 14354edb46e9SPaul Traina return; 14364edb46e9SPaul Traina 14374edb46e9SPaul Traina case NFSPROC_GETATTR: 14384edb46e9SPaul Traina printf(" getattr"); 14394edb46e9SPaul Traina dp = parserep(rp, length); 14402ebf6c05SBill Fenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 14414edb46e9SPaul Traina return; 14424edb46e9SPaul Traina break; 14434edb46e9SPaul Traina 14444edb46e9SPaul Traina case NFSPROC_SETATTR: 14454edb46e9SPaul Traina printf(" setattr"); 1446943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 14474edb46e9SPaul Traina return; 1448647f50c3SDoug Rabson if (v3) { 1449943ee2b1SBill Fenner if (parsewccres(dp, vflag)) 1450647f50c3SDoug Rabson return; 1451647f50c3SDoug Rabson } else { 1452647f50c3SDoug Rabson if (parseattrstat(dp, !qflag, 0) != 0) 1453647f50c3SDoug Rabson return; 1454647f50c3SDoug Rabson } 14554edb46e9SPaul Traina break; 14564edb46e9SPaul Traina 14574edb46e9SPaul Traina case NFSPROC_LOOKUP: 14584edb46e9SPaul Traina printf(" lookup"); 1459943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 14604edb46e9SPaul Traina break; 1461647f50c3SDoug Rabson if (v3) { 1462943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1463647f50c3SDoug Rabson break; 1464647f50c3SDoug Rabson if (er) { 1465647f50c3SDoug Rabson if (vflag > 1) { 1466647f50c3SDoug Rabson printf(" post dattr:"); 1467647f50c3SDoug Rabson dp = parse_post_op_attr(dp, vflag); 1468647f50c3SDoug Rabson } 1469647f50c3SDoug Rabson } else { 1470943ee2b1SBill Fenner if (!(dp = parsefh(dp, v3))) 1471647f50c3SDoug Rabson break; 1472943ee2b1SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) && 1473943ee2b1SBill Fenner vflag > 1) { 1474647f50c3SDoug Rabson printf(" post dattr:"); 1475647f50c3SDoug Rabson dp = parse_post_op_attr(dp, vflag); 1476647f50c3SDoug Rabson } 1477647f50c3SDoug Rabson } 1478943ee2b1SBill Fenner if (dp) 1479647f50c3SDoug Rabson return; 1480647f50c3SDoug Rabson } else { 1481647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1482647f50c3SDoug Rabson return; 1483647f50c3SDoug Rabson } 1484647f50c3SDoug Rabson break; 1485647f50c3SDoug Rabson 1486647f50c3SDoug Rabson case NFSPROC_ACCESS: 1487647f50c3SDoug Rabson printf(" access"); 1488a1c2090eSBill Fenner if (!(dp = parserep(rp, length))) 1489a1c2090eSBill Fenner break; 1490943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1491647f50c3SDoug Rabson break; 1492647f50c3SDoug Rabson if (vflag) 1493647f50c3SDoug Rabson printf(" attr:"); 1494943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1495647f50c3SDoug Rabson break; 1496647f50c3SDoug Rabson if (!er) 1497cc391cceSBruce M Simpson printf(" c %04x", EXTRACT_32BITS(&dp[0])); 1498647f50c3SDoug Rabson return; 14994edb46e9SPaul Traina 15004edb46e9SPaul Traina case NFSPROC_READLINK: 15014edb46e9SPaul Traina printf(" readlink"); 15024edb46e9SPaul Traina dp = parserep(rp, length); 15032ebf6c05SBill Fenner if (dp != NULL && parselinkres(dp, v3) != 0) 15044edb46e9SPaul Traina return; 15054edb46e9SPaul Traina break; 15064edb46e9SPaul Traina 15074edb46e9SPaul Traina case NFSPROC_READ: 15084edb46e9SPaul Traina printf(" read"); 1509943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1510647f50c3SDoug Rabson break; 1511647f50c3SDoug Rabson if (v3) { 1512943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1513647f50c3SDoug Rabson break; 1514943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1515647f50c3SDoug Rabson break; 1516647f50c3SDoug Rabson if (er) 15174edb46e9SPaul Traina return; 1518647f50c3SDoug Rabson if (vflag) { 1519943ee2b1SBill Fenner TCHECK(dp[1]); 1520cc391cceSBruce M Simpson printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 1521cc391cceSBruce M Simpson if (EXTRACT_32BITS(&dp[1])) 1522647f50c3SDoug Rabson printf(" EOF"); 1523647f50c3SDoug Rabson } 1524647f50c3SDoug Rabson return; 1525647f50c3SDoug Rabson } else { 1526647f50c3SDoug Rabson if (parseattrstat(dp, vflag, 0) != 0) 1527647f50c3SDoug Rabson return; 1528647f50c3SDoug Rabson } 15294edb46e9SPaul Traina break; 15304edb46e9SPaul Traina 15314edb46e9SPaul Traina case NFSPROC_WRITE: 15324edb46e9SPaul Traina printf(" write"); 1533943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1534647f50c3SDoug Rabson break; 1535647f50c3SDoug Rabson if (v3) { 1536943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1537647f50c3SDoug Rabson break; 1538943ee2b1SBill Fenner if (!(dp = parse_wcc_data(dp, vflag))) 1539647f50c3SDoug Rabson break; 1540647f50c3SDoug Rabson if (er) 15414edb46e9SPaul Traina return; 1542647f50c3SDoug Rabson if (vflag) { 1543943ee2b1SBill Fenner TCHECK(dp[0]); 1544cc391cceSBruce M Simpson printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 1545647f50c3SDoug Rabson if (vflag > 1) { 1546943ee2b1SBill Fenner TCHECK(dp[1]); 1547647f50c3SDoug Rabson printf(" <%s>", 1548943ee2b1SBill Fenner tok2str(nfsv3_writemodes, 1549cc391cceSBruce M Simpson NULL, EXTRACT_32BITS(&dp[1]))); 1550647f50c3SDoug Rabson } 1551647f50c3SDoug Rabson return; 1552647f50c3SDoug Rabson } 1553647f50c3SDoug Rabson } else { 1554647f50c3SDoug Rabson if (parseattrstat(dp, vflag, v3) != 0) 1555647f50c3SDoug Rabson return; 1556647f50c3SDoug Rabson } 15574edb46e9SPaul Traina break; 15584edb46e9SPaul Traina 15594edb46e9SPaul Traina case NFSPROC_CREATE: 15604edb46e9SPaul Traina printf(" create"); 1561943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1562647f50c3SDoug Rabson break; 1563647f50c3SDoug Rabson if (v3) { 1564943ee2b1SBill Fenner if (parsecreateopres(dp, vflag) != 0) 1565647f50c3SDoug Rabson return; 1566647f50c3SDoug Rabson } else { 1567647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1568647f50c3SDoug Rabson return; 1569647f50c3SDoug Rabson } 1570647f50c3SDoug Rabson break; 1571647f50c3SDoug Rabson 1572647f50c3SDoug Rabson case NFSPROC_MKDIR: 1573647f50c3SDoug Rabson printf(" mkdir"); 1574943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1575647f50c3SDoug Rabson break; 1576647f50c3SDoug Rabson if (v3) { 1577943ee2b1SBill Fenner if (parsecreateopres(dp, vflag) != 0) 1578647f50c3SDoug Rabson return; 1579647f50c3SDoug Rabson } else { 1580647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1581647f50c3SDoug Rabson return; 1582647f50c3SDoug Rabson } 1583647f50c3SDoug Rabson break; 1584647f50c3SDoug Rabson 1585647f50c3SDoug Rabson case NFSPROC_SYMLINK: 1586647f50c3SDoug Rabson printf(" symlink"); 1587943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1588647f50c3SDoug Rabson break; 1589647f50c3SDoug Rabson if (v3) { 1590943ee2b1SBill Fenner if (parsecreateopres(dp, vflag) != 0) 1591647f50c3SDoug Rabson return; 1592647f50c3SDoug Rabson } else { 1593943ee2b1SBill Fenner if (parsestatus(dp, &er) != 0) 1594647f50c3SDoug Rabson return; 1595647f50c3SDoug Rabson } 1596647f50c3SDoug Rabson break; 1597647f50c3SDoug Rabson 1598647f50c3SDoug Rabson case NFSPROC_MKNOD: 1599647f50c3SDoug Rabson printf(" mknod"); 1600943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1601647f50c3SDoug Rabson break; 1602943ee2b1SBill Fenner if (parsecreateopres(dp, vflag) != 0) 16034edb46e9SPaul Traina return; 16044edb46e9SPaul Traina break; 16054edb46e9SPaul Traina 16064edb46e9SPaul Traina case NFSPROC_REMOVE: 16074edb46e9SPaul Traina printf(" remove"); 1608943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 16094edb46e9SPaul Traina break; 1610647f50c3SDoug Rabson if (v3) { 1611943ee2b1SBill Fenner if (parsewccres(dp, vflag)) 16124edb46e9SPaul Traina return; 1613647f50c3SDoug Rabson } else { 1614943ee2b1SBill Fenner if (parsestatus(dp, &er) != 0) 16154edb46e9SPaul Traina return; 1616647f50c3SDoug Rabson } 16174edb46e9SPaul Traina break; 16184edb46e9SPaul Traina 16194edb46e9SPaul Traina case NFSPROC_RMDIR: 16204edb46e9SPaul Traina printf(" rmdir"); 1621943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1622647f50c3SDoug Rabson break; 1623647f50c3SDoug Rabson if (v3) { 1624943ee2b1SBill Fenner if (parsewccres(dp, vflag)) 16254edb46e9SPaul Traina return; 1626647f50c3SDoug Rabson } else { 1627943ee2b1SBill Fenner if (parsestatus(dp, &er) != 0) 1628647f50c3SDoug Rabson return; 1629647f50c3SDoug Rabson } 1630647f50c3SDoug Rabson break; 1631647f50c3SDoug Rabson 1632647f50c3SDoug Rabson case NFSPROC_RENAME: 1633647f50c3SDoug Rabson printf(" rename"); 1634943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1635647f50c3SDoug Rabson break; 1636647f50c3SDoug Rabson if (v3) { 1637943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1638647f50c3SDoug Rabson break; 1639647f50c3SDoug Rabson if (vflag) { 1640647f50c3SDoug Rabson printf(" from:"); 1641943ee2b1SBill Fenner if (!(dp = parse_wcc_data(dp, vflag))) 1642647f50c3SDoug Rabson break; 1643647f50c3SDoug Rabson printf(" to:"); 1644943ee2b1SBill Fenner if (!(dp = parse_wcc_data(dp, vflag))) 1645647f50c3SDoug Rabson break; 1646647f50c3SDoug Rabson } 1647647f50c3SDoug Rabson return; 1648647f50c3SDoug Rabson } else { 1649943ee2b1SBill Fenner if (parsestatus(dp, &er) != 0) 1650647f50c3SDoug Rabson return; 1651647f50c3SDoug Rabson } 1652647f50c3SDoug Rabson break; 1653647f50c3SDoug Rabson 1654647f50c3SDoug Rabson case NFSPROC_LINK: 1655647f50c3SDoug Rabson printf(" link"); 1656943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1657647f50c3SDoug Rabson break; 1658647f50c3SDoug Rabson if (v3) { 1659943ee2b1SBill Fenner if (!(dp = parsestatus(dp, &er))) 1660647f50c3SDoug Rabson break; 1661647f50c3SDoug Rabson if (vflag) { 1662647f50c3SDoug Rabson printf(" file POST:"); 1663943ee2b1SBill Fenner if (!(dp = parse_post_op_attr(dp, vflag))) 1664647f50c3SDoug Rabson break; 1665647f50c3SDoug Rabson printf(" dir:"); 1666943ee2b1SBill Fenner if (!(dp = parse_wcc_data(dp, vflag))) 1667647f50c3SDoug Rabson break; 1668647f50c3SDoug Rabson return; 1669647f50c3SDoug Rabson } 1670647f50c3SDoug Rabson } else { 1671943ee2b1SBill Fenner if (parsestatus(dp, &er) != 0) 1672647f50c3SDoug Rabson return; 1673647f50c3SDoug Rabson } 16744edb46e9SPaul Traina break; 16754edb46e9SPaul Traina 16764edb46e9SPaul Traina case NFSPROC_READDIR: 16774edb46e9SPaul Traina printf(" readdir"); 1678943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1679647f50c3SDoug Rabson break; 1680647f50c3SDoug Rabson if (v3) { 1681943ee2b1SBill Fenner if (parsev3rddirres(dp, vflag)) 1682647f50c3SDoug Rabson return; 1683647f50c3SDoug Rabson } else { 1684647f50c3SDoug Rabson if (parserddires(dp) != 0) 1685647f50c3SDoug Rabson return; 1686647f50c3SDoug Rabson } 1687647f50c3SDoug Rabson break; 1688647f50c3SDoug Rabson 1689647f50c3SDoug Rabson case NFSPROC_READDIRPLUS: 1690647f50c3SDoug Rabson printf(" readdirplus"); 1691943ee2b1SBill Fenner if (!(dp = parserep(rp, length))) 1692647f50c3SDoug Rabson break; 1693943ee2b1SBill Fenner if (parsev3rddirres(dp, vflag)) 16944edb46e9SPaul Traina return; 16954edb46e9SPaul Traina break; 16964edb46e9SPaul Traina 1697647f50c3SDoug Rabson case NFSPROC_FSSTAT: 1698647f50c3SDoug Rabson printf(" fsstat"); 16994edb46e9SPaul Traina dp = parserep(rp, length); 1700943ee2b1SBill Fenner if (dp != NULL && parsestatfs(dp, v3) != 0) 1701647f50c3SDoug Rabson return; 1702647f50c3SDoug Rabson break; 1703647f50c3SDoug Rabson 1704647f50c3SDoug Rabson case NFSPROC_FSINFO: 1705647f50c3SDoug Rabson printf(" fsinfo"); 1706647f50c3SDoug Rabson dp = parserep(rp, length); 1707943ee2b1SBill Fenner if (dp != NULL && parsefsinfo(dp) != 0) 1708647f50c3SDoug Rabson return; 1709647f50c3SDoug Rabson break; 1710647f50c3SDoug Rabson 1711647f50c3SDoug Rabson case NFSPROC_PATHCONF: 1712647f50c3SDoug Rabson printf(" pathconf"); 1713647f50c3SDoug Rabson dp = parserep(rp, length); 17142ebf6c05SBill Fenner if (dp != NULL && parsepathconf(dp) != 0) 1715647f50c3SDoug Rabson return; 1716647f50c3SDoug Rabson break; 1717647f50c3SDoug Rabson 1718647f50c3SDoug Rabson case NFSPROC_COMMIT: 1719647f50c3SDoug Rabson printf(" commit"); 1720647f50c3SDoug Rabson dp = parserep(rp, length); 17212ebf6c05SBill Fenner if (dp != NULL && parsewccres(dp, vflag) != 0) 17224edb46e9SPaul Traina return; 17234edb46e9SPaul Traina break; 17244edb46e9SPaul Traina 17254edb46e9SPaul Traina default: 17262ebf6c05SBill Fenner printf(" proc-%u", proc); 17274edb46e9SPaul Traina return; 17284edb46e9SPaul Traina } 1729647f50c3SDoug Rabson trunc: 17302ebf6c05SBill Fenner if (!nfserr) 17314edb46e9SPaul Traina fputs(" [|nfs]", stdout); 17324edb46e9SPaul Traina } 1733