print-nfs.c revision 172686
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 172686 2007-10-16 02:31:48Z mlaier $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26172686Smlaier "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.106.2.4 2007/06/15 23:17:40 guy Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2975118Sfenner#ifdef HAVE_CONFIG_H 3075118Sfenner#include "config.h" 3175118Sfenner#endif 3275118Sfenner 33127675Sbms#include <tcpdump-stdinc.h> 3417680Spst 3526183Sfenner#include <pcap.h> 3617680Spst#include <stdio.h> 3717680Spst#include <string.h> 3817680Spst 3917680Spst#include "interface.h" 4017680Spst#include "addrtoname.h" 41127675Sbms#include "extract.h" 4217680Spst 4318976Sdfr#include "nfs.h" 4417680Spst#include "nfsfh.h" 4517680Spst 4675118Sfenner#include "ip.h" 4775118Sfenner#ifdef INET6 4875118Sfenner#include "ip6.h" 4975118Sfenner#endif 50146778Ssam#include "rpc_auth.h" 51146778Ssam#include "rpc_msg.h" 5275118Sfenner 5375118Sfennerstatic void nfs_printfh(const u_int32_t *, const u_int); 54146778Ssamstatic void xid_map_enter(const struct sunrpc_msg *, const u_char *); 55146778Ssamstatic int32_t xid_map_find(const struct sunrpc_msg *, const u_char *, 5675118Sfenner u_int32_t *, u_int32_t *); 57146778Ssamstatic void interp_reply(const struct sunrpc_msg *, u_int32_t, u_int32_t, int); 5818976Sdfrstatic const u_int32_t *parse_post_op_attr(const u_int32_t *, int); 5975118Sfennerstatic void print_sattr3(const struct nfsv3_sattr *sa3, int verbose); 6075118Sfennerstatic void print_nfsaddr(const u_char *, const char *, const char *); 6117680Spst 6218976Sdfr/* 6318976Sdfr * Mapping of old NFS Version 2 RPC numbers to generic numbers. 6418976Sdfr */ 6518976Sdfru_int32_t nfsv3_procid[NFS_NPROCS] = { 6618976Sdfr NFSPROC_NULL, 6718976Sdfr NFSPROC_GETATTR, 6818976Sdfr NFSPROC_SETATTR, 6918976Sdfr NFSPROC_NOOP, 7018976Sdfr NFSPROC_LOOKUP, 7118976Sdfr NFSPROC_READLINK, 7218976Sdfr NFSPROC_READ, 7318976Sdfr NFSPROC_NOOP, 7418976Sdfr NFSPROC_WRITE, 7518976Sdfr NFSPROC_CREATE, 7618976Sdfr NFSPROC_REMOVE, 7718976Sdfr NFSPROC_RENAME, 7818976Sdfr NFSPROC_LINK, 7918976Sdfr NFSPROC_SYMLINK, 8018976Sdfr NFSPROC_MKDIR, 8118976Sdfr NFSPROC_RMDIR, 8218976Sdfr NFSPROC_READDIR, 8318976Sdfr NFSPROC_FSSTAT, 8418976Sdfr NFSPROC_NOOP, 8518976Sdfr NFSPROC_NOOP, 8618976Sdfr NFSPROC_NOOP, 8718976Sdfr NFSPROC_NOOP, 8818976Sdfr NFSPROC_NOOP, 8918976Sdfr NFSPROC_NOOP, 9018976Sdfr NFSPROC_NOOP, 9118976Sdfr NFSPROC_NOOP 9218976Sdfr}; 9318976Sdfr 9475118Sfenner/* 9575118Sfenner * NFS V2 and V3 status values. 9675118Sfenner * 9775118Sfenner * Some of these come from the RFCs for NFS V2 and V3, with the message 9875118Sfenner * strings taken from the FreeBSD C library "errlst.c". 9975118Sfenner * 10075118Sfenner * Others are errors that are not in the RFC but that I suspect some 10175118Sfenner * NFS servers could return; the values are FreeBSD errno values, as 10275118Sfenner * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS 10375118Sfenner * was primarily BSD-derived. 10475118Sfenner */ 10575118Sfennerstatic struct tok status2str[] = { 10675118Sfenner { 1, "Operation not permitted" }, /* EPERM */ 10775118Sfenner { 2, "No such file or directory" }, /* ENOENT */ 10875118Sfenner { 5, "Input/output error" }, /* EIO */ 10975118Sfenner { 6, "Device not configured" }, /* ENXIO */ 11075118Sfenner { 11, "Resource deadlock avoided" }, /* EDEADLK */ 11175118Sfenner { 12, "Cannot allocate memory" }, /* ENOMEM */ 11275118Sfenner { 13, "Permission denied" }, /* EACCES */ 11375118Sfenner { 17, "File exists" }, /* EEXIST */ 11475118Sfenner { 18, "Cross-device link" }, /* EXDEV */ 11575118Sfenner { 19, "Operation not supported by device" }, /* ENODEV */ 11675118Sfenner { 20, "Not a directory" }, /* ENOTDIR */ 11775118Sfenner { 21, "Is a directory" }, /* EISDIR */ 11875118Sfenner { 22, "Invalid argument" }, /* EINVAL */ 11975118Sfenner { 26, "Text file busy" }, /* ETXTBSY */ 12075118Sfenner { 27, "File too large" }, /* EFBIG */ 12175118Sfenner { 28, "No space left on device" }, /* ENOSPC */ 12275118Sfenner { 30, "Read-only file system" }, /* EROFS */ 12375118Sfenner { 31, "Too many links" }, /* EMLINK */ 12475118Sfenner { 45, "Operation not supported" }, /* EOPNOTSUPP */ 12575118Sfenner { 62, "Too many levels of symbolic links" }, /* ELOOP */ 12675118Sfenner { 63, "File name too long" }, /* ENAMETOOLONG */ 12775118Sfenner { 66, "Directory not empty" }, /* ENOTEMPTY */ 12875118Sfenner { 69, "Disc quota exceeded" }, /* EDQUOT */ 12975118Sfenner { 70, "Stale NFS file handle" }, /* ESTALE */ 13075118Sfenner { 71, "Too many levels of remote in path" }, /* EREMOTE */ 13175118Sfenner { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */ 13275118Sfenner { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */ 13375118Sfenner { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */ 13475118Sfenner { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */ 13575118Sfenner { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */ 13675118Sfenner { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */ 13775118Sfenner { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */ 13875118Sfenner { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */ 13975118Sfenner { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */ 14075118Sfenner { 0, NULL } 14118976Sdfr}; 14218976Sdfr 14375118Sfennerstatic struct tok nfsv3_writemodes[] = { 14475118Sfenner { 0, "unstable" }, 14575118Sfenner { 1, "datasync" }, 14675118Sfenner { 2, "filesync" }, 14775118Sfenner { 0, NULL } 14875118Sfenner}; 14975118Sfenner 15018976Sdfrstatic struct tok type2str[] = { 15118976Sdfr { NFNON, "NON" }, 15218976Sdfr { NFREG, "REG" }, 15318976Sdfr { NFDIR, "DIR" }, 15418976Sdfr { NFBLK, "BLK" }, 15518976Sdfr { NFCHR, "CHR" }, 15618976Sdfr { NFLNK, "LNK" }, 15718976Sdfr { NFFIFO, "FIFO" }, 15818976Sdfr { 0, NULL } 15918976Sdfr}; 16018976Sdfr 16175118Sfennerstatic void 16275118Sfennerprint_nfsaddr(const u_char *bp, const char *s, const char *d) 16375118Sfenner{ 16475118Sfenner struct ip *ip; 16575118Sfenner#ifdef INET6 16675118Sfenner struct ip6_hdr *ip6; 16775118Sfenner char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; 16875118Sfenner#else 16975118Sfenner#ifndef INET_ADDRSTRLEN 17075118Sfenner#define INET_ADDRSTRLEN 16 17175118Sfenner#endif 17275118Sfenner char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN]; 17375118Sfenner#endif 17475118Sfenner 17575118Sfenner srcaddr[0] = dstaddr[0] = '\0'; 17675118Sfenner switch (IP_V((struct ip *)bp)) { 17775118Sfenner case 4: 17875118Sfenner ip = (struct ip *)bp; 17975118Sfenner strlcpy(srcaddr, ipaddr_string(&ip->ip_src), sizeof(srcaddr)); 18075118Sfenner strlcpy(dstaddr, ipaddr_string(&ip->ip_dst), sizeof(dstaddr)); 18175118Sfenner break; 18275118Sfenner#ifdef INET6 18375118Sfenner case 6: 18475118Sfenner ip6 = (struct ip6_hdr *)bp; 18575118Sfenner strlcpy(srcaddr, ip6addr_string(&ip6->ip6_src), 18675118Sfenner sizeof(srcaddr)); 18775118Sfenner strlcpy(dstaddr, ip6addr_string(&ip6->ip6_dst), 18875118Sfenner sizeof(dstaddr)); 18975118Sfenner break; 19075118Sfenner#endif 19175118Sfenner default: 19275118Sfenner strlcpy(srcaddr, "?", sizeof(srcaddr)); 19375118Sfenner strlcpy(dstaddr, "?", sizeof(dstaddr)); 19475118Sfenner break; 19575118Sfenner } 19675118Sfenner 19775118Sfenner (void)printf("%s.%s > %s.%s: ", srcaddr, s, dstaddr, d); 19875118Sfenner} 19975118Sfenner 20018976Sdfrstatic const u_int32_t * 20118976Sdfrparse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3) 20218976Sdfr{ 20375118Sfenner TCHECK(dp[0]); 204127675Sbms sa3->sa_modeset = EXTRACT_32BITS(dp); 205127675Sbms dp++; 206127675Sbms if (sa3->sa_modeset) { 20775118Sfenner TCHECK(dp[0]); 208127675Sbms sa3->sa_mode = EXTRACT_32BITS(dp); 209127675Sbms dp++; 21018976Sdfr } 21118976Sdfr 21275118Sfenner TCHECK(dp[0]); 213127675Sbms sa3->sa_uidset = EXTRACT_32BITS(dp); 214127675Sbms dp++; 215127675Sbms if (sa3->sa_uidset) { 21675118Sfenner TCHECK(dp[0]); 217127675Sbms sa3->sa_uid = EXTRACT_32BITS(dp); 218127675Sbms dp++; 21918976Sdfr } 22018976Sdfr 22175118Sfenner TCHECK(dp[0]); 222127675Sbms sa3->sa_gidset = EXTRACT_32BITS(dp); 223127675Sbms dp++; 224127675Sbms if (sa3->sa_gidset) { 22575118Sfenner TCHECK(dp[0]); 226127675Sbms sa3->sa_gid = EXTRACT_32BITS(dp); 227127675Sbms dp++; 22818976Sdfr } 22918976Sdfr 23075118Sfenner TCHECK(dp[0]); 231127675Sbms sa3->sa_sizeset = EXTRACT_32BITS(dp); 232127675Sbms dp++; 233127675Sbms if (sa3->sa_sizeset) { 23475118Sfenner TCHECK(dp[0]); 235127675Sbms sa3->sa_size = EXTRACT_32BITS(dp); 236127675Sbms dp++; 23718976Sdfr } 23818976Sdfr 23975118Sfenner TCHECK(dp[0]); 240127675Sbms sa3->sa_atimetype = EXTRACT_32BITS(dp); 241127675Sbms dp++; 242127675Sbms if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) { 24375118Sfenner TCHECK(dp[1]); 244127675Sbms sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp); 245127675Sbms dp++; 246127675Sbms sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp); 247127675Sbms dp++; 24818976Sdfr } 24918976Sdfr 25075118Sfenner TCHECK(dp[0]); 251127675Sbms sa3->sa_mtimetype = EXTRACT_32BITS(dp); 252127675Sbms dp++; 253127675Sbms if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) { 25475118Sfenner TCHECK(dp[1]); 255127675Sbms sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp); 256127675Sbms dp++; 257127675Sbms sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp); 258127675Sbms dp++; 25918976Sdfr } 26018976Sdfr 26118976Sdfr return dp; 26275118Sfennertrunc: 26375118Sfenner return NULL; 26418976Sdfr} 26518976Sdfr 26675118Sfennerstatic int nfserr; /* true if we error rather than trunc */ 26775118Sfenner 26875118Sfennerstatic void 26918976Sdfrprint_sattr3(const struct nfsv3_sattr *sa3, int verbose) 27018976Sdfr{ 27118976Sdfr if (sa3->sa_modeset) 27218976Sdfr printf(" mode %o", sa3->sa_mode); 27318976Sdfr if (sa3->sa_uidset) 27418976Sdfr printf(" uid %u", sa3->sa_uid); 27518976Sdfr if (sa3->sa_gidset) 27618976Sdfr printf(" gid %u", sa3->sa_gid); 27718976Sdfr if (verbose > 1) { 27818976Sdfr if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 27918976Sdfr printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec, 28018976Sdfr sa3->sa_atime.nfsv3_nsec); 28118976Sdfr if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 28218976Sdfr printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 28318976Sdfr sa3->sa_mtime.nfsv3_nsec); 28418976Sdfr } 28518976Sdfr} 28618976Sdfr 28718976Sdfrvoid 28817680Spstnfsreply_print(register const u_char *bp, u_int length, 28917680Spst register const u_char *bp2) 29017680Spst{ 291146778Ssam register const struct sunrpc_msg *rp; 292172686Smlaier u_int32_t proc, vers, reply_stat; 29375118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 294172686Smlaier enum sunrpc_reject_stat rstat; 295172686Smlaier u_int32_t rlow; 296172686Smlaier u_int32_t rhigh; 297172686Smlaier enum sunrpc_auth_stat rwhy; 29817680Spst 29926183Sfenner nfserr = 0; /* assume no error */ 300146778Ssam rp = (const struct sunrpc_msg *)bp; 30117680Spst 30275118Sfenner if (!nflag) { 30375118Sfenner strlcpy(srcid, "nfs", sizeof(srcid)); 30475118Sfenner snprintf(dstid, sizeof(dstid), "%u", 305127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 30675118Sfenner } else { 30775118Sfenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 30875118Sfenner snprintf(dstid, sizeof(dstid), "%u", 309127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 31075118Sfenner } 31175118Sfenner print_nfsaddr(bp2, srcid, dstid); 312172686Smlaier reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat); 313172686Smlaier switch (reply_stat) { 31417680Spst 315172686Smlaier case SUNRPC_MSG_ACCEPTED: 316172686Smlaier (void)printf("reply ok %u", length); 317172686Smlaier if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 318172686Smlaier interp_reply(rp, proc, vers, length); 319172686Smlaier break; 320172686Smlaier 321172686Smlaier case SUNRPC_MSG_DENIED: 322172686Smlaier (void)printf("reply ERR %u: ", length); 323172686Smlaier rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat); 324172686Smlaier switch (rstat) { 325172686Smlaier 326172686Smlaier case SUNRPC_RPC_MISMATCH: 327172686Smlaier rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low); 328172686Smlaier rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high); 329172686Smlaier (void)printf("RPC Version mismatch (%u-%u)", 330172686Smlaier rlow, rhigh); 331172686Smlaier break; 332172686Smlaier 333172686Smlaier case SUNRPC_AUTH_ERROR: 334172686Smlaier rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why); 335172686Smlaier (void)printf("Auth "); 336172686Smlaier switch (rwhy) { 337172686Smlaier 338172686Smlaier case SUNRPC_AUTH_OK: 339172686Smlaier (void)printf("OK"); 340172686Smlaier break; 341172686Smlaier 342172686Smlaier case SUNRPC_AUTH_BADCRED: 343172686Smlaier (void)printf("Bogus Credentials (seal broken)"); 344172686Smlaier break; 345172686Smlaier 346172686Smlaier case SUNRPC_AUTH_REJECTEDCRED: 347172686Smlaier (void)printf("Rejected Credentials (client should begin new session)"); 348172686Smlaier break; 349172686Smlaier 350172686Smlaier case SUNRPC_AUTH_BADVERF: 351172686Smlaier (void)printf("Bogus Verifier (seal broken)"); 352172686Smlaier break; 353172686Smlaier 354172686Smlaier case SUNRPC_AUTH_REJECTEDVERF: 355172686Smlaier (void)printf("Verifier expired or was replayed"); 356172686Smlaier break; 357172686Smlaier 358172686Smlaier case SUNRPC_AUTH_TOOWEAK: 359172686Smlaier (void)printf("Credentials are too weak"); 360172686Smlaier break; 361172686Smlaier 362172686Smlaier case SUNRPC_AUTH_INVALIDRESP: 363172686Smlaier (void)printf("Bogus response verifier"); 364172686Smlaier break; 365172686Smlaier 366172686Smlaier case SUNRPC_AUTH_FAILED: 367172686Smlaier (void)printf("Unknown failure"); 368172686Smlaier break; 369172686Smlaier 370172686Smlaier default: 371172686Smlaier (void)printf("Invalid failure code %u", 372172686Smlaier (unsigned int)rwhy); 373172686Smlaier break; 374172686Smlaier } 375172686Smlaier break; 376172686Smlaier 377172686Smlaier default: 378172686Smlaier (void)printf("Unknown reason for rejecting rpc message %u", 379172686Smlaier (unsigned int)rstat); 380172686Smlaier break; 381172686Smlaier } 382172686Smlaier break; 383172686Smlaier 384172686Smlaier default: 385172686Smlaier (void)printf("reply Unknown rpc response code=%u %u", 386172686Smlaier reply_stat, length); 387172686Smlaier break; 388172686Smlaier } 38917680Spst} 39017680Spst 39117680Spst/* 39217680Spst * Return a pointer to the first file handle in the packet. 39375118Sfenner * If the packet was truncated, return 0. 39417680Spst */ 39517680Spststatic const u_int32_t * 396146778Ssamparsereq(register const struct sunrpc_msg *rp, register u_int length) 39717680Spst{ 39826183Sfenner register const u_int32_t *dp; 39917680Spst register u_int len; 40017680Spst 40117680Spst /* 40217680Spst * find the start of the req data (if we captured it) 40317680Spst */ 40426183Sfenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 40526183Sfenner TCHECK(dp[1]); 406127675Sbms len = EXTRACT_32BITS(&dp[1]); 40726183Sfenner if (len < length) { 40826183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 40926183Sfenner TCHECK(dp[1]); 410127675Sbms len = EXTRACT_32BITS(&dp[1]); 41126183Sfenner if (len < length) { 41226183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 41326183Sfenner TCHECK2(dp[0], 0); 41426183Sfenner return (dp); 41517680Spst } 41617680Spst } 41726183Sfennertrunc: 41826183Sfenner return (NULL); 41917680Spst} 42017680Spst 42117680Spst/* 42217680Spst * Print out an NFS file handle and return a pointer to following word. 42375118Sfenner * If packet was truncated, return 0. 42417680Spst */ 42517680Spststatic const u_int32_t * 42618976Sdfrparsefh(register const u_int32_t *dp, int v3) 42717680Spst{ 428127675Sbms u_int len; 42918976Sdfr 43018976Sdfr if (v3) { 43126183Sfenner TCHECK(dp[0]); 432127675Sbms len = EXTRACT_32BITS(dp) / 4; 43318976Sdfr dp++; 43418976Sdfr } else 43518976Sdfr len = NFSX_V2FH / 4; 43618976Sdfr 43726183Sfenner if (TTEST2(*dp, len * sizeof(*dp))) { 43818976Sdfr nfs_printfh(dp, len); 43918976Sdfr return (dp + len); 44017680Spst } 44126183Sfennertrunc: 44226183Sfenner return (NULL); 44317680Spst} 44417680Spst 44517680Spst/* 44617680Spst * Print out a file name and return pointer to 32-bit word past it. 44775118Sfenner * If packet was truncated, return 0. 44817680Spst */ 44917680Spststatic const u_int32_t * 45017680Spstparsefn(register const u_int32_t *dp) 45117680Spst{ 45217680Spst register u_int32_t len; 45317680Spst register const u_char *cp; 45417680Spst 45517680Spst /* Bail if we don't have the string length */ 45675118Sfenner TCHECK(*dp); 45717680Spst 45817680Spst /* Fetch string length; convert to host order */ 45917680Spst len = *dp++; 46017680Spst NTOHL(len); 46117680Spst 46275118Sfenner TCHECK2(*dp, ((len + 3) & ~3)); 46375118Sfenner 46417680Spst cp = (u_char *)dp; 46517680Spst /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 46617680Spst dp += ((len + 3) & ~3) / sizeof(*dp); 46726183Sfenner putchar('"'); 468147904Ssam if (fn_printn(cp, len, snapend)) { 469147904Ssam putchar('"'); 470147904Ssam goto trunc; 471147904Ssam } 47226183Sfenner putchar('"'); 47317680Spst 47417680Spst return (dp); 47575118Sfennertrunc: 47675118Sfenner return NULL; 47717680Spst} 47817680Spst 47917680Spst/* 48017680Spst * Print out file handle and file name. 48117680Spst * Return pointer to 32-bit word past file name. 48275118Sfenner * If packet was truncated (or there was some other error), return 0. 48317680Spst */ 48417680Spststatic const u_int32_t * 48518976Sdfrparsefhn(register const u_int32_t *dp, int v3) 48617680Spst{ 48718976Sdfr dp = parsefh(dp, v3); 48826183Sfenner if (dp == NULL) 48926183Sfenner return (NULL); 49017680Spst putchar(' '); 49117680Spst return (parsefn(dp)); 49217680Spst} 49317680Spst 49417680Spstvoid 49517680Spstnfsreq_print(register const u_char *bp, u_int length, 49617680Spst register const u_char *bp2) 49717680Spst{ 498146778Ssam register const struct sunrpc_msg *rp; 49917680Spst register const u_int32_t *dp; 50075118Sfenner nfs_type type; 50175118Sfenner int v3; 50275118Sfenner u_int32_t proc; 50318976Sdfr struct nfsv3_sattr sa3; 50475118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 50517680Spst 50626183Sfenner nfserr = 0; /* assume no error */ 507146778Ssam rp = (const struct sunrpc_msg *)bp; 50875118Sfenner if (!nflag) { 50975118Sfenner snprintf(srcid, sizeof(srcid), "%u", 510127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 51175118Sfenner strlcpy(dstid, "nfs", sizeof(dstid)); 51275118Sfenner } else { 51375118Sfenner snprintf(srcid, sizeof(srcid), "%u", 514127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 51575118Sfenner snprintf(dstid, sizeof(dstid), "%u", NFS_PORT); 51675118Sfenner } 51775118Sfenner print_nfsaddr(bp2, srcid, dstid); 51875118Sfenner (void)printf("%d", length); 51917680Spst 52075118Sfenner xid_map_enter(rp, bp2); /* record proc number for later on */ 52117680Spst 522127675Sbms v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3); 523127675Sbms proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 52418976Sdfr 52518976Sdfr if (!v3 && proc < NFS_NPROCS) 52618976Sdfr proc = nfsv3_procid[proc]; 52718976Sdfr 52818976Sdfr switch (proc) { 52917680Spst case NFSPROC_NOOP: 53017680Spst printf(" nop"); 53117680Spst return; 53217680Spst case NFSPROC_NULL: 53317680Spst printf(" null"); 53417680Spst return; 53517680Spst 53617680Spst case NFSPROC_GETATTR: 53717680Spst printf(" getattr"); 53875118Sfenner if ((dp = parsereq(rp, length)) != NULL && 53975118Sfenner parsefh(dp, v3) != NULL) 54017680Spst return; 54117680Spst break; 54217680Spst 54317680Spst case NFSPROC_SETATTR: 54417680Spst printf(" setattr"); 54575118Sfenner if ((dp = parsereq(rp, length)) != NULL && 54675118Sfenner parsefh(dp, v3) != NULL) 54717680Spst return; 54817680Spst break; 54917680Spst 55017680Spst case NFSPROC_LOOKUP: 55117680Spst printf(" lookup"); 55275118Sfenner if ((dp = parsereq(rp, length)) != NULL && 55375118Sfenner parsefhn(dp, v3) != NULL) 55417680Spst return; 55517680Spst break; 55617680Spst 55718976Sdfr case NFSPROC_ACCESS: 55818976Sdfr printf(" access"); 55926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 56026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 56175118Sfenner TCHECK(dp[0]); 562127675Sbms printf(" %04x", EXTRACT_32BITS(&dp[0])); 56318976Sdfr return; 56418976Sdfr } 56518976Sdfr break; 56618976Sdfr 56717680Spst case NFSPROC_READLINK: 56817680Spst printf(" readlink"); 56975118Sfenner if ((dp = parsereq(rp, length)) != NULL && 57075118Sfenner parsefh(dp, v3) != NULL) 57117680Spst return; 57217680Spst break; 57317680Spst 57417680Spst case NFSPROC_READ: 57517680Spst printf(" read"); 57626183Sfenner if ((dp = parsereq(rp, length)) != NULL && 57726183Sfenner (dp = parsefh(dp, v3)) != NULL) { 57818976Sdfr if (v3) { 57975118Sfenner TCHECK(dp[2]); 580146778Ssam printf(" %u bytes @ %" PRIu64, 581146778Ssam EXTRACT_32BITS(&dp[2]), 582146778Ssam EXTRACT_64BITS(&dp[0])); 58318976Sdfr } else { 58475118Sfenner TCHECK(dp[1]); 58575118Sfenner printf(" %u bytes @ %u", 586127675Sbms EXTRACT_32BITS(&dp[1]), 587127675Sbms EXTRACT_32BITS(&dp[0])); 58818976Sdfr } 58917680Spst return; 59017680Spst } 59117680Spst break; 59217680Spst 59317680Spst case NFSPROC_WRITE: 59417680Spst printf(" write"); 59526183Sfenner if ((dp = parsereq(rp, length)) != NULL && 59626183Sfenner (dp = parsefh(dp, v3)) != NULL) { 59718976Sdfr if (v3) { 598146778Ssam TCHECK(dp[2]); 599146778Ssam printf(" %u (%u) bytes @ %" PRIu64, 600146778Ssam EXTRACT_32BITS(&dp[4]), 601146778Ssam EXTRACT_32BITS(&dp[2]), 602146778Ssam EXTRACT_64BITS(&dp[0])); 60318976Sdfr if (vflag) { 60418976Sdfr dp += 3; 60575118Sfenner TCHECK(dp[0]); 60618976Sdfr printf(" <%s>", 60775118Sfenner tok2str(nfsv3_writemodes, 608127675Sbms NULL, EXTRACT_32BITS(dp))); 60918976Sdfr } 61018976Sdfr } else { 61175118Sfenner TCHECK(dp[3]); 61275118Sfenner printf(" %u (%u) bytes @ %u (%u)", 613127675Sbms EXTRACT_32BITS(&dp[3]), 614127675Sbms EXTRACT_32BITS(&dp[2]), 615127675Sbms EXTRACT_32BITS(&dp[1]), 616127675Sbms EXTRACT_32BITS(&dp[0])); 61718976Sdfr } 61817680Spst return; 61917680Spst } 62017680Spst break; 62117680Spst 62217680Spst case NFSPROC_CREATE: 62317680Spst printf(" create"); 62475118Sfenner if ((dp = parsereq(rp, length)) != NULL && 62575118Sfenner parsefhn(dp, v3) != NULL) 62617680Spst return; 62717680Spst break; 62817680Spst 62918976Sdfr case NFSPROC_MKDIR: 63018976Sdfr printf(" mkdir"); 63175118Sfenner if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) 63218976Sdfr return; 63318976Sdfr break; 63418976Sdfr 63518976Sdfr case NFSPROC_SYMLINK: 63618976Sdfr printf(" symlink"); 63775118Sfenner if ((dp = parsereq(rp, length)) != 0 && 63875118Sfenner (dp = parsefhn(dp, v3)) != 0) { 63975118Sfenner fputs(" ->", stdout); 64075118Sfenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) 64118976Sdfr break; 64275118Sfenner if (parsefn(dp) == 0) 64318976Sdfr break; 64418976Sdfr if (v3 && vflag) 64518976Sdfr print_sattr3(&sa3, vflag); 64618976Sdfr return; 64718976Sdfr } 64818976Sdfr break; 64918976Sdfr 65018976Sdfr case NFSPROC_MKNOD: 65118976Sdfr printf(" mknod"); 65275118Sfenner if ((dp = parsereq(rp, length)) != 0 && 65375118Sfenner (dp = parsefhn(dp, v3)) != 0) { 65475118Sfenner TCHECK(*dp); 655127675Sbms type = (nfs_type)EXTRACT_32BITS(dp); 656127675Sbms dp++; 65775118Sfenner if ((dp = parse_sattr3(dp, &sa3)) == 0) 65818976Sdfr break; 65918976Sdfr printf(" %s", tok2str(type2str, "unk-ft %d", type)); 66018976Sdfr if (vflag && (type == NFCHR || type == NFBLK)) { 66175118Sfenner TCHECK(dp[1]); 66275118Sfenner printf(" %u/%u", 663127675Sbms EXTRACT_32BITS(&dp[0]), 664127675Sbms EXTRACT_32BITS(&dp[1])); 66518976Sdfr dp += 2; 66618976Sdfr } 66718976Sdfr if (vflag) 66818976Sdfr print_sattr3(&sa3, vflag); 66918976Sdfr return; 67018976Sdfr } 67118976Sdfr break; 67218976Sdfr 67317680Spst case NFSPROC_REMOVE: 67417680Spst printf(" remove"); 67575118Sfenner if ((dp = parsereq(rp, length)) != NULL && 67675118Sfenner parsefhn(dp, v3) != NULL) 67717680Spst return; 67817680Spst break; 67917680Spst 68018976Sdfr case NFSPROC_RMDIR: 68118976Sdfr printf(" rmdir"); 68275118Sfenner if ((dp = parsereq(rp, length)) != NULL && 68375118Sfenner parsefhn(dp, v3) != NULL) 68418976Sdfr return; 68518976Sdfr break; 68618976Sdfr 68717680Spst case NFSPROC_RENAME: 68817680Spst printf(" rename"); 68926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 69026183Sfenner (dp = parsefhn(dp, v3)) != NULL) { 69117680Spst fputs(" ->", stdout); 69226183Sfenner if (parsefhn(dp, v3) != NULL) 69317680Spst return; 69417680Spst } 69517680Spst break; 69617680Spst 69717680Spst case NFSPROC_LINK: 69817680Spst printf(" link"); 69926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 70026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 70117680Spst fputs(" ->", stdout); 70226183Sfenner if (parsefhn(dp, v3) != NULL) 70317680Spst return; 70417680Spst } 70517680Spst break; 70617680Spst 70718976Sdfr case NFSPROC_READDIR: 70818976Sdfr printf(" readdir"); 70926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 71026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 71118976Sdfr if (v3) { 71275118Sfenner TCHECK(dp[4]); 71318976Sdfr /* 71418976Sdfr * We shouldn't really try to interpret the 71518976Sdfr * offset cookie here. 71618976Sdfr */ 717146778Ssam printf(" %u bytes @ %" PRId64, 718146778Ssam EXTRACT_32BITS(&dp[4]), 719146778Ssam EXTRACT_64BITS(&dp[0])); 72018976Sdfr if (vflag) 72126183Sfenner printf(" verf %08x%08x", dp[2], 72218976Sdfr dp[3]); 72318976Sdfr } else { 72475118Sfenner TCHECK(dp[1]); 72518976Sdfr /* 72618976Sdfr * Print the offset as signed, since -1 is 72718976Sdfr * common, but offsets > 2^31 aren't. 72818976Sdfr */ 72975118Sfenner printf(" %u bytes @ %d", 730127675Sbms EXTRACT_32BITS(&dp[1]), 731127675Sbms EXTRACT_32BITS(&dp[0])); 73218976Sdfr } 73318976Sdfr return; 73417680Spst } 73517680Spst break; 73617680Spst 73718976Sdfr case NFSPROC_READDIRPLUS: 73818976Sdfr printf(" readdirplus"); 73926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 74026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 74175118Sfenner TCHECK(dp[4]); 74218976Sdfr /* 74318976Sdfr * We don't try to interpret the offset 74418976Sdfr * cookie here. 74518976Sdfr */ 746146778Ssam printf(" %u bytes @ %" PRId64, 747146778Ssam EXTRACT_32BITS(&dp[4]), 748146778Ssam EXTRACT_64BITS(&dp[0])); 749146778Ssam if (vflag) { 750146778Ssam TCHECK(dp[5]); 75175118Sfenner printf(" max %u verf %08x%08x", 752127675Sbms EXTRACT_32BITS(&dp[5]), dp[2], dp[3]); 753146778Ssam } 75417680Spst return; 75518976Sdfr } 75617680Spst break; 75717680Spst 75818976Sdfr case NFSPROC_FSSTAT: 75918976Sdfr printf(" fsstat"); 76075118Sfenner if ((dp = parsereq(rp, length)) != NULL && 76175118Sfenner parsefh(dp, v3) != NULL) 76217680Spst return; 76317680Spst break; 76417680Spst 76518976Sdfr case NFSPROC_FSINFO: 76618976Sdfr printf(" fsinfo"); 767111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 768111729Sfenner parsefh(dp, v3) != NULL) 769111729Sfenner return; 77018976Sdfr break; 77118976Sdfr 77218976Sdfr case NFSPROC_PATHCONF: 77318976Sdfr printf(" pathconf"); 774111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 775111729Sfenner parsefh(dp, v3) != NULL) 776111729Sfenner return; 77718976Sdfr break; 77818976Sdfr 77918976Sdfr case NFSPROC_COMMIT: 78018976Sdfr printf(" commit"); 78126183Sfenner if ((dp = parsereq(rp, length)) != NULL && 78226183Sfenner (dp = parsefh(dp, v3)) != NULL) { 783146778Ssam TCHECK(dp[2]); 784146778Ssam printf(" %u bytes @ %" PRIu64, 785146778Ssam EXTRACT_32BITS(&dp[2]), 786146778Ssam EXTRACT_64BITS(&dp[0])); 78717680Spst return; 78817680Spst } 78917680Spst break; 79017680Spst 79117680Spst default: 792127675Sbms printf(" proc-%u", EXTRACT_32BITS(&rp->rm_call.cb_proc)); 79317680Spst return; 79417680Spst } 79575118Sfenner 79617680Spsttrunc: 79726183Sfenner if (!nfserr) 79826183Sfenner fputs(" [|nfs]", stdout); 79917680Spst} 80017680Spst 80117680Spst/* 80217680Spst * Print out an NFS file handle. 80317680Spst * We assume packet was not truncated before the end of the 80417680Spst * file handle pointed to by dp. 80517680Spst * 80617680Spst * Note: new version (using portable file-handle parser) doesn't produce 80717680Spst * generation number. It probably could be made to do that, with some 80817680Spst * additional hacking on the parser code. 80917680Spst */ 81017680Spststatic void 81175118Sfennernfs_printfh(register const u_int32_t *dp, const u_int len) 81217680Spst{ 81317680Spst my_fsid fsid; 81417680Spst ino_t ino; 815127675Sbms const char *sfsname = NULL; 816127675Sbms char *spacep; 81717680Spst 818127675Sbms if (uflag) { 819127675Sbms u_int i; 820127675Sbms char const *sep = ""; 82117680Spst 822127675Sbms printf(" fh["); 823127675Sbms for (i=0; i<len; i++) { 824127675Sbms (void)printf("%s%x", sep, dp[i]); 825127675Sbms sep = ":"; 826127675Sbms } 827127675Sbms printf("]"); 828127675Sbms return; 829127675Sbms } 830127675Sbms 831127675Sbms Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0); 832127675Sbms 83317680Spst if (sfsname) { 83426183Sfenner /* file system ID is ASCII, not numeric, for this server OS */ 83526183Sfenner static char temp[NFSX_V3FHMAX+1]; 83617680Spst 83726183Sfenner /* Make sure string is null-terminated */ 83826183Sfenner strncpy(temp, sfsname, NFSX_V3FHMAX); 83975118Sfenner temp[sizeof(temp) - 1] = '\0'; 84026183Sfenner /* Remove trailing spaces */ 841127675Sbms spacep = strchr(temp, ' '); 842127675Sbms if (spacep) 843127675Sbms *spacep = '\0'; 84417680Spst 84575118Sfenner (void)printf(" fh %s/", temp); 84626183Sfenner } else { 84775118Sfenner (void)printf(" fh %d,%d/", 84875118Sfenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); 84917680Spst } 85075118Sfenner 851127675Sbms if(fsid.Fsid_dev.Minor == 257) 852127675Sbms /* Print the undecoded handle */ 85375118Sfenner (void)printf("%s", fsid.Opaque_Handle); 85475118Sfenner else 85575118Sfenner (void)printf("%ld", (long) ino); 85617680Spst} 85717680Spst 85817680Spst/* 85917680Spst * Maintain a small cache of recent client.XID.server/proc pairs, to allow 86017680Spst * us to match up replies with requests and thus to know how to parse 86117680Spst * the reply. 86217680Spst */ 86317680Spst 86417680Spststruct xid_map_entry { 86575118Sfenner u_int32_t xid; /* transaction ID (net order) */ 86675118Sfenner int ipver; /* IP version (4 or 6) */ 86775118Sfenner#ifdef INET6 86875118Sfenner struct in6_addr client; /* client IP address (net order) */ 86975118Sfenner struct in6_addr server; /* server IP address (net order) */ 87075118Sfenner#else 87117680Spst struct in_addr client; /* client IP address (net order) */ 87217680Spst struct in_addr server; /* server IP address (net order) */ 87375118Sfenner#endif 87475118Sfenner u_int32_t proc; /* call proc number (host order) */ 87575118Sfenner u_int32_t vers; /* program version (host order) */ 87617680Spst}; 87717680Spst 87817680Spst/* 87917680Spst * Map entries are kept in an array that we manage as a ring; 88017680Spst * new entries are always added at the tail of the ring. Initially, 88117680Spst * all the entries are zero and hence don't match anything. 88217680Spst */ 88317680Spst 88417680Spst#define XIDMAPSIZE 64 88517680Spst 88617680Spststruct xid_map_entry xid_map[XIDMAPSIZE]; 88717680Spst 88817680Spstint xid_map_next = 0; 88917680Spstint xid_map_hint = 0; 89017680Spst 89117680Spststatic void 892146778Ssamxid_map_enter(const struct sunrpc_msg *rp, const u_char *bp) 89317680Spst{ 89475118Sfenner struct ip *ip = NULL; 89575118Sfenner#ifdef INET6 89675118Sfenner struct ip6_hdr *ip6 = NULL; 89775118Sfenner#endif 89817680Spst struct xid_map_entry *xmep; 89917680Spst 90075118Sfenner switch (IP_V((struct ip *)bp)) { 90175118Sfenner case 4: 90275118Sfenner ip = (struct ip *)bp; 90375118Sfenner break; 90475118Sfenner#ifdef INET6 90575118Sfenner case 6: 90675118Sfenner ip6 = (struct ip6_hdr *)bp; 90775118Sfenner break; 90875118Sfenner#endif 90975118Sfenner default: 91075118Sfenner return; 91175118Sfenner } 91275118Sfenner 91317680Spst xmep = &xid_map[xid_map_next]; 91417680Spst 91517680Spst if (++xid_map_next >= XIDMAPSIZE) 91617680Spst xid_map_next = 0; 91717680Spst 91817680Spst xmep->xid = rp->rm_xid; 91975118Sfenner if (ip) { 92075118Sfenner xmep->ipver = 4; 92175118Sfenner memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 92275118Sfenner memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 92375118Sfenner } 92475118Sfenner#ifdef INET6 92575118Sfenner else if (ip6) { 92675118Sfenner xmep->ipver = 6; 92775118Sfenner memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 92875118Sfenner memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 92975118Sfenner } 93075118Sfenner#endif 931127675Sbms xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 932127675Sbms xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers); 93317680Spst} 93417680Spst 93526183Sfenner/* 93626183Sfenner * Returns 0 and puts NFSPROC_xxx in proc return and 93726183Sfenner * version in vers return, or returns -1 on failure 93826183Sfenner */ 93918976Sdfrstatic int 940146778Ssamxid_map_find(const struct sunrpc_msg *rp, const u_char *bp, u_int32_t *proc, 94118976Sdfr u_int32_t *vers) 94217680Spst{ 94317680Spst int i; 94417680Spst struct xid_map_entry *xmep; 94517680Spst u_int32_t xid = rp->rm_xid; 94675118Sfenner struct ip *ip = (struct ip *)bp; 94775118Sfenner#ifdef INET6 94875118Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 94975118Sfenner#endif 95075118Sfenner int cmp; 95117680Spst 95217680Spst /* Start searching from where we last left off */ 953127675Sbms i = xid_map_hint; 95417680Spst do { 95517680Spst xmep = &xid_map[i]; 95675118Sfenner cmp = 1; 95775118Sfenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 95875118Sfenner goto nextitem; 95975118Sfenner switch (xmep->ipver) { 96075118Sfenner case 4: 96175118Sfenner if (memcmp(&ip->ip_src, &xmep->server, 96275118Sfenner sizeof(ip->ip_src)) != 0 || 96375118Sfenner memcmp(&ip->ip_dst, &xmep->client, 96475118Sfenner sizeof(ip->ip_dst)) != 0) { 96575118Sfenner cmp = 0; 96675118Sfenner } 96775118Sfenner break; 96875118Sfenner#ifdef INET6 96975118Sfenner case 6: 97075118Sfenner if (memcmp(&ip6->ip6_src, &xmep->server, 97175118Sfenner sizeof(ip6->ip6_src)) != 0 || 97275118Sfenner memcmp(&ip6->ip6_dst, &xmep->client, 97375118Sfenner sizeof(ip6->ip6_dst)) != 0) { 97475118Sfenner cmp = 0; 97575118Sfenner } 97675118Sfenner break; 97775118Sfenner#endif 97875118Sfenner default: 97975118Sfenner cmp = 0; 98075118Sfenner break; 98175118Sfenner } 98275118Sfenner if (cmp) { 98317680Spst /* match */ 98417680Spst xid_map_hint = i; 98518976Sdfr *proc = xmep->proc; 98618976Sdfr *vers = xmep->vers; 98718976Sdfr return 0; 98817680Spst } 98975118Sfenner nextitem: 99017680Spst if (++i >= XIDMAPSIZE) 99117680Spst i = 0; 99217680Spst } while (i != xid_map_hint); 99317680Spst 99417680Spst /* search failed */ 99575118Sfenner return (-1); 99617680Spst} 99717680Spst 99817680Spst/* 99917680Spst * Routines for parsing reply packets 100017680Spst */ 100117680Spst 100217680Spst/* 100317680Spst * Return a pointer to the beginning of the actual results. 100475118Sfenner * If the packet was truncated, return 0. 100517680Spst */ 100617680Spststatic const u_int32_t * 1007146778Ssamparserep(register const struct sunrpc_msg *rp, register u_int length) 100817680Spst{ 100917680Spst register const u_int32_t *dp; 101075118Sfenner u_int len; 1011146778Ssam enum sunrpc_accept_stat astat; 101217680Spst 101317680Spst /* 101417680Spst * Portability note: 101517680Spst * Here we find the address of the ar_verf credentials. 101617680Spst * Originally, this calculation was 101717680Spst * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 101817680Spst * On the wire, the rp_acpt field starts immediately after 101917680Spst * the (32 bit) rp_stat field. However, rp_acpt (which is a 102017680Spst * "struct accepted_reply") contains a "struct opaque_auth", 102117680Spst * whose internal representation contains a pointer, so on a 102217680Spst * 64-bit machine the compiler inserts 32 bits of padding 102317680Spst * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 102417680Spst * the internal representation to parse the on-the-wire 102517680Spst * representation. Instead, we skip past the rp_stat field, 102617680Spst * which is an "enum" and so occupies one 32-bit word. 102717680Spst */ 102817680Spst dp = ((const u_int32_t *)&rp->rm_reply) + 1; 102975118Sfenner TCHECK(dp[1]); 1030127675Sbms len = EXTRACT_32BITS(&dp[1]); 103117680Spst if (len >= length) 103226183Sfenner return (NULL); 103317680Spst /* 103417680Spst * skip past the ar_verf credentials. 103517680Spst */ 103617680Spst dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 103726183Sfenner TCHECK2(dp[0], 0); 103817680Spst 103917680Spst /* 104017680Spst * now we can check the ar_stat field 104117680Spst */ 1042147904Ssam astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); 104317680Spst switch (astat) { 104417680Spst 1045146778Ssam case SUNRPC_SUCCESS: 104617680Spst break; 104717680Spst 1048146778Ssam case SUNRPC_PROG_UNAVAIL: 104917680Spst printf(" PROG_UNAVAIL"); 105026183Sfenner nfserr = 1; /* suppress trunc string */ 105126183Sfenner return (NULL); 105217680Spst 1053146778Ssam case SUNRPC_PROG_MISMATCH: 105417680Spst printf(" PROG_MISMATCH"); 105526183Sfenner nfserr = 1; /* suppress trunc string */ 105626183Sfenner return (NULL); 105717680Spst 1058146778Ssam case SUNRPC_PROC_UNAVAIL: 105917680Spst printf(" PROC_UNAVAIL"); 106026183Sfenner nfserr = 1; /* suppress trunc string */ 106126183Sfenner return (NULL); 106217680Spst 1063146778Ssam case SUNRPC_GARBAGE_ARGS: 106417680Spst printf(" GARBAGE_ARGS"); 106526183Sfenner nfserr = 1; /* suppress trunc string */ 106626183Sfenner return (NULL); 106717680Spst 1068146778Ssam case SUNRPC_SYSTEM_ERR: 106917680Spst printf(" SYSTEM_ERR"); 107026183Sfenner nfserr = 1; /* suppress trunc string */ 107126183Sfenner return (NULL); 107217680Spst 107317680Spst default: 107417680Spst printf(" ar_stat %d", astat); 107526183Sfenner nfserr = 1; /* suppress trunc string */ 107626183Sfenner return (NULL); 107717680Spst } 107817680Spst /* successful return */ 107975118Sfenner TCHECK2(*dp, sizeof(astat)); 108075118Sfenner return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 108126183Sfennertrunc: 108275118Sfenner return (0); 108317680Spst} 108417680Spst 108517680Spststatic const u_int32_t * 108618976Sdfrparsestatus(const u_int32_t *dp, int *er) 108717680Spst{ 108875118Sfenner int errnum; 108917680Spst 109026183Sfenner TCHECK(dp[0]); 109175118Sfenner 1092127675Sbms errnum = EXTRACT_32BITS(&dp[0]); 109318976Sdfr if (er) 109426183Sfenner *er = errnum; 109526183Sfenner if (errnum != 0) { 109626183Sfenner if (!qflag) 109775118Sfenner printf(" ERROR: %s", 109875118Sfenner tok2str(status2str, "unk %d", errnum)); 109926183Sfenner nfserr = 1; 110017680Spst } 110117680Spst return (dp + 1); 110226183Sfennertrunc: 110375118Sfenner return NULL; 110417680Spst} 110517680Spst 110617680Spststatic const u_int32_t * 110718976Sdfrparsefattr(const u_int32_t *dp, int verbose, int v3) 110817680Spst{ 110918976Sdfr const struct nfs_fattr *fap; 111017680Spst 111118976Sdfr fap = (const struct nfs_fattr *)dp; 111226184Sfenner TCHECK(fap->fa_gid); 111317680Spst if (verbose) { 111475118Sfenner printf(" %s %o ids %d/%d", 111575118Sfenner tok2str(type2str, "unk-ft %d ", 1116127675Sbms EXTRACT_32BITS(&fap->fa_type)), 1117127675Sbms EXTRACT_32BITS(&fap->fa_mode), 1118127675Sbms EXTRACT_32BITS(&fap->fa_uid), 1119127675Sbms EXTRACT_32BITS(&fap->fa_gid)); 112018976Sdfr if (v3) { 112126184Sfenner TCHECK(fap->fa3_size); 1122146778Ssam printf(" sz %" PRIu64, 1123146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_size)); 112426184Sfenner } else { 112526184Sfenner TCHECK(fap->fa2_size); 1126127675Sbms printf(" sz %d", EXTRACT_32BITS(&fap->fa2_size)); 112718976Sdfr } 112817680Spst } 112917680Spst /* print lots more stuff */ 113017680Spst if (verbose > 1) { 113118976Sdfr if (v3) { 113226184Sfenner TCHECK(fap->fa3_ctime); 1133127675Sbms printf(" nlink %d rdev %d/%d", 1134127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1135127675Sbms EXTRACT_32BITS(&fap->fa3_rdev.specdata1), 1136127675Sbms EXTRACT_32BITS(&fap->fa3_rdev.specdata2)); 1137146778Ssam printf(" fsid %" PRIx64, 1138146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_fsid)); 1139146778Ssam printf(" fileid %" PRIx64, 1140146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_fileid)); 1141127675Sbms printf(" a/m/ctime %u.%06u", 1142127675Sbms EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec), 1143127675Sbms EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)); 1144127675Sbms printf(" %u.%06u", 1145127675Sbms EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec), 1146127675Sbms EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)); 1147127675Sbms printf(" %u.%06u", 1148127675Sbms EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec), 1149127675Sbms EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)); 115018976Sdfr } else { 115126184Sfenner TCHECK(fap->fa2_ctime); 1152127675Sbms printf(" nlink %d rdev %x fsid %x nodeid %x a/m/ctime", 1153127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1154127675Sbms EXTRACT_32BITS(&fap->fa2_rdev), 1155127675Sbms EXTRACT_32BITS(&fap->fa2_fsid), 1156127675Sbms EXTRACT_32BITS(&fap->fa2_fileid)); 1157127675Sbms printf(" %u.%06u", 1158127675Sbms EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec), 1159127675Sbms EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)); 1160127675Sbms printf(" %u.%06u", 1161127675Sbms EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec), 1162127675Sbms EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)); 1163127675Sbms printf(" %u.%06u", 1164127675Sbms EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec), 1165127675Sbms EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)); 116618976Sdfr } 116717680Spst } 116818976Sdfr return ((const u_int32_t *)((unsigned char *)dp + 116918976Sdfr (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 117026184Sfennertrunc: 117126184Sfenner return (NULL); 117217680Spst} 117317680Spst 117417680Spststatic int 117518976Sdfrparseattrstat(const u_int32_t *dp, int verbose, int v3) 117617680Spst{ 117718976Sdfr int er; 117818976Sdfr 117918976Sdfr dp = parsestatus(dp, &er); 1180111729Sfenner if (dp == NULL) 118117680Spst return (0); 1182111729Sfenner if (er) 1183111729Sfenner return (1); 118417680Spst 118526183Sfenner return (parsefattr(dp, verbose, v3) != NULL); 118617680Spst} 118717680Spst 118817680Spststatic int 118917680Spstparsediropres(const u_int32_t *dp) 119017680Spst{ 119118976Sdfr int er; 119218976Sdfr 1193111729Sfenner if (!(dp = parsestatus(dp, &er))) 119417680Spst return (0); 1195111729Sfenner if (er) 1196111729Sfenner return (1); 119717680Spst 119818976Sdfr dp = parsefh(dp, 0); 119917680Spst if (dp == NULL) 120017680Spst return (0); 120117680Spst 120218976Sdfr return (parsefattr(dp, vflag, 0) != NULL); 120317680Spst} 120417680Spst 120517680Spststatic int 120618976Sdfrparselinkres(const u_int32_t *dp, int v3) 120717680Spst{ 120818976Sdfr int er; 120918976Sdfr 121018976Sdfr dp = parsestatus(dp, &er); 1211111729Sfenner if (dp == NULL) 121217680Spst return(0); 1213111729Sfenner if (er) 1214111729Sfenner return(1); 121575118Sfenner if (v3 && !(dp = parse_post_op_attr(dp, vflag))) 121618976Sdfr return (0); 121717680Spst putchar(' '); 121817680Spst return (parsefn(dp) != NULL); 121917680Spst} 122017680Spst 122117680Spststatic int 122218976Sdfrparsestatfs(const u_int32_t *dp, int v3) 122317680Spst{ 122418976Sdfr const struct nfs_statfs *sfsp; 122518976Sdfr int er; 122617680Spst 122718976Sdfr dp = parsestatus(dp, &er); 1228111729Sfenner if (dp == NULL) 122975118Sfenner return (0); 1230111729Sfenner if (!v3 && er) 1231111729Sfenner return (1); 123217680Spst 123318976Sdfr if (qflag) 123418976Sdfr return(1); 123518976Sdfr 123618976Sdfr if (v3) { 123718976Sdfr if (vflag) 123818976Sdfr printf(" POST:"); 123975118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 124018976Sdfr return (0); 124117680Spst } 124217680Spst 1243111729Sfenner TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 124418976Sdfr 124518976Sdfr sfsp = (const struct nfs_statfs *)dp; 124618976Sdfr 124718976Sdfr if (v3) { 1248146778Ssam printf(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64, 1249146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tbytes), 1250146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_fbytes), 1251146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_abytes)); 125218976Sdfr if (vflag) { 1253146778Ssam printf(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u", 1254146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tfiles), 1255146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_ffiles), 1256146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_afiles), 1257127675Sbms EXTRACT_32BITS(&sfsp->sf_invarsec)); 125818976Sdfr } 125918976Sdfr } else { 126075118Sfenner printf(" tsize %d bsize %d blocks %d bfree %d bavail %d", 1261127675Sbms EXTRACT_32BITS(&sfsp->sf_tsize), 1262127675Sbms EXTRACT_32BITS(&sfsp->sf_bsize), 1263127675Sbms EXTRACT_32BITS(&sfsp->sf_blocks), 1264127675Sbms EXTRACT_32BITS(&sfsp->sf_bfree), 1265127675Sbms EXTRACT_32BITS(&sfsp->sf_bavail)); 126618976Sdfr } 126718976Sdfr 126817680Spst return (1); 126926184Sfennertrunc: 127026184Sfenner return (0); 127117680Spst} 127217680Spst 127317680Spststatic int 127417680Spstparserddires(const u_int32_t *dp) 127517680Spst{ 127618976Sdfr int er; 127718976Sdfr 127818976Sdfr dp = parsestatus(dp, &er); 1279111729Sfenner if (dp == NULL) 128017680Spst return (0); 1281111729Sfenner if (er) 1282111729Sfenner return (1); 128318976Sdfr if (qflag) 128418976Sdfr return (1); 128518976Sdfr 128626184Sfenner TCHECK(dp[2]); 128775118Sfenner printf(" offset %x size %d ", 1288127675Sbms EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])); 128918976Sdfr if (dp[2] != 0) 129075118Sfenner printf(" eof"); 129118976Sdfr 129218976Sdfr return (1); 129326184Sfennertrunc: 129426184Sfenner return (0); 129518976Sdfr} 129618976Sdfr 129718976Sdfrstatic const u_int32_t * 129818976Sdfrparse_wcc_attr(const u_int32_t *dp) 129918976Sdfr{ 1300146778Ssam printf(" sz %" PRIu64, EXTRACT_64BITS(&dp[0])); 130175118Sfenner printf(" mtime %u.%06u ctime %u.%06u", 1302127675Sbms EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]), 1303127675Sbms EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])); 130418976Sdfr return (dp + 6); 130518976Sdfr} 130618976Sdfr 130718976Sdfr/* 130818976Sdfr * Pre operation attributes. Print only if vflag > 1. 130918976Sdfr */ 131018976Sdfrstatic const u_int32_t * 131118976Sdfrparse_pre_op_attr(const u_int32_t *dp, int verbose) 131218976Sdfr{ 131326184Sfenner TCHECK(dp[0]); 1314127675Sbms if (!EXTRACT_32BITS(&dp[0])) 131518976Sdfr return (dp + 1); 131618976Sdfr dp++; 1317111729Sfenner TCHECK2(*dp, 24); 131818976Sdfr if (verbose > 1) { 131918976Sdfr return parse_wcc_attr(dp); 132018976Sdfr } else { 132118976Sdfr /* If not verbose enough, just skip over wcc_attr */ 132218976Sdfr return (dp + 6); 132317680Spst } 132426184Sfennertrunc: 132526184Sfenner return (NULL); 132618976Sdfr} 132717680Spst 132818976Sdfr/* 132918976Sdfr * Post operation attributes are printed if vflag >= 1 133018976Sdfr */ 133118976Sdfrstatic const u_int32_t * 133218976Sdfrparse_post_op_attr(const u_int32_t *dp, int verbose) 133318976Sdfr{ 133426184Sfenner TCHECK(dp[0]); 1335127675Sbms if (!EXTRACT_32BITS(&dp[0])) 133618976Sdfr return (dp + 1); 133718976Sdfr dp++; 133818976Sdfr if (verbose) { 133918976Sdfr return parsefattr(dp, verbose, 1); 134018976Sdfr } else 134118976Sdfr return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 134226184Sfennertrunc: 134326184Sfenner return (NULL); 134418976Sdfr} 134518976Sdfr 134618976Sdfrstatic const u_int32_t * 134718976Sdfrparse_wcc_data(const u_int32_t *dp, int verbose) 134818976Sdfr{ 134918976Sdfr if (verbose > 1) 135018976Sdfr printf(" PRE:"); 135175118Sfenner if (!(dp = parse_pre_op_attr(dp, verbose))) 135275118Sfenner return (0); 135318976Sdfr 135418976Sdfr if (verbose) 135518976Sdfr printf(" POST:"); 135618976Sdfr return parse_post_op_attr(dp, verbose); 135718976Sdfr} 135818976Sdfr 135918976Sdfrstatic const u_int32_t * 136018976Sdfrparsecreateopres(const u_int32_t *dp, int verbose) 136118976Sdfr{ 136218976Sdfr int er; 136318976Sdfr 136475118Sfenner if (!(dp = parsestatus(dp, &er))) 136575118Sfenner return (0); 136618976Sdfr if (er) 136718976Sdfr dp = parse_wcc_data(dp, verbose); 136818976Sdfr else { 136926184Sfenner TCHECK(dp[0]); 1370127675Sbms if (!EXTRACT_32BITS(&dp[0])) 137118976Sdfr return (dp + 1); 137218976Sdfr dp++; 137375118Sfenner if (!(dp = parsefh(dp, 1))) 137475118Sfenner return (0); 137518976Sdfr if (verbose) { 137675118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 137775118Sfenner return (0); 137818976Sdfr if (vflag > 1) { 1379127675Sbms printf(" dir attr:"); 138018976Sdfr dp = parse_wcc_data(dp, verbose); 138118976Sdfr } 138218976Sdfr } 138318976Sdfr } 138418976Sdfr return (dp); 138526184Sfennertrunc: 138626184Sfenner return (NULL); 138718976Sdfr} 138818976Sdfr 138918976Sdfrstatic int 139018976Sdfrparsewccres(const u_int32_t *dp, int verbose) 139118976Sdfr{ 139218976Sdfr int er; 139318976Sdfr 139475118Sfenner if (!(dp = parsestatus(dp, &er))) 139518976Sdfr return (0); 139675118Sfenner return parse_wcc_data(dp, verbose) != 0; 139718976Sdfr} 139818976Sdfr 139918976Sdfrstatic const u_int32_t * 140018976Sdfrparsev3rddirres(const u_int32_t *dp, int verbose) 140118976Sdfr{ 140218976Sdfr int er; 140318976Sdfr 140475118Sfenner if (!(dp = parsestatus(dp, &er))) 140575118Sfenner return (0); 140618976Sdfr if (vflag) 140718976Sdfr printf(" POST:"); 140875118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 140975118Sfenner return (0); 141018976Sdfr if (er) 141118976Sdfr return dp; 141218976Sdfr if (vflag) { 141326184Sfenner TCHECK(dp[1]); 141426183Sfenner printf(" verf %08x%08x", dp[0], dp[1]); 141518976Sdfr dp += 2; 141618976Sdfr } 141718976Sdfr return dp; 141826184Sfennertrunc: 141926184Sfenner return (NULL); 142018976Sdfr} 142118976Sdfr 142218976Sdfrstatic int 142318976Sdfrparsefsinfo(const u_int32_t *dp) 142418976Sdfr{ 142518976Sdfr struct nfsv3_fsinfo *sfp; 142618976Sdfr int er; 142718976Sdfr 142875118Sfenner if (!(dp = parsestatus(dp, &er))) 142918976Sdfr return (0); 143018976Sdfr if (vflag) 143118976Sdfr printf(" POST:"); 143275118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 143318976Sdfr return (0); 143418976Sdfr if (er) 143518976Sdfr return (1); 143618976Sdfr 143718976Sdfr sfp = (struct nfsv3_fsinfo *)dp; 143826184Sfenner TCHECK(*sfp); 143975118Sfenner printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 1440127675Sbms EXTRACT_32BITS(&sfp->fs_rtmax), 1441127675Sbms EXTRACT_32BITS(&sfp->fs_rtpref), 1442127675Sbms EXTRACT_32BITS(&sfp->fs_wtmax), 1443127675Sbms EXTRACT_32BITS(&sfp->fs_wtpref), 1444127675Sbms EXTRACT_32BITS(&sfp->fs_dtpref)); 144518976Sdfr if (vflag) { 1446146778Ssam printf(" rtmult %u wtmult %u maxfsz %" PRIu64, 1447127675Sbms EXTRACT_32BITS(&sfp->fs_rtmult), 1448146778Ssam EXTRACT_32BITS(&sfp->fs_wtmult), 1449146778Ssam EXTRACT_64BITS((u_int32_t *)&sfp->fs_maxfilesize)); 145075118Sfenner printf(" delta %u.%06u ", 1451127675Sbms EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec), 1452127675Sbms EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)); 145318976Sdfr } 1454111729Sfenner return (1); 1455111729Sfennertrunc: 145675118Sfenner return (0); 145718976Sdfr} 145818976Sdfr 145918976Sdfrstatic int 146018976Sdfrparsepathconf(const u_int32_t *dp) 146118976Sdfr{ 146218976Sdfr int er; 146318976Sdfr struct nfsv3_pathconf *spp; 146418976Sdfr 146575118Sfenner if (!(dp = parsestatus(dp, &er))) 146618976Sdfr return (0); 146718976Sdfr if (vflag) 146818976Sdfr printf(" POST:"); 146975118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 147018976Sdfr return (0); 147118976Sdfr if (er) 147218976Sdfr return (1); 147318976Sdfr 147418976Sdfr spp = (struct nfsv3_pathconf *)dp; 147526184Sfenner TCHECK(*spp); 147618976Sdfr 147775118Sfenner printf(" linkmax %u namemax %u %s %s %s %s", 1478127675Sbms EXTRACT_32BITS(&spp->pc_linkmax), 1479127675Sbms EXTRACT_32BITS(&spp->pc_namemax), 1480127675Sbms EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "", 1481127675Sbms EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "", 1482127675Sbms EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "", 1483127675Sbms EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""); 1484111729Sfenner return (1); 1485111729Sfennertrunc: 148675118Sfenner return (0); 148717680Spst} 148875118Sfenner 148917680Spststatic void 1490146778Ssaminterp_reply(const struct sunrpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 149117680Spst{ 149217680Spst register const u_int32_t *dp; 149318976Sdfr register int v3; 149418976Sdfr int er; 149517680Spst 149618976Sdfr v3 = (vers == NFS_VER3); 149718976Sdfr 149818976Sdfr if (!v3 && proc < NFS_NPROCS) 149918976Sdfr proc = nfsv3_procid[proc]; 150018976Sdfr 150117680Spst switch (proc) { 150217680Spst 150317680Spst case NFSPROC_NOOP: 150417680Spst printf(" nop"); 150517680Spst return; 150618976Sdfr 150717680Spst case NFSPROC_NULL: 150817680Spst printf(" null"); 150917680Spst return; 151017680Spst 151117680Spst case NFSPROC_GETATTR: 151217680Spst printf(" getattr"); 151317680Spst dp = parserep(rp, length); 151426183Sfenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 151517680Spst return; 151617680Spst break; 151717680Spst 151817680Spst case NFSPROC_SETATTR: 151917680Spst printf(" setattr"); 152075118Sfenner if (!(dp = parserep(rp, length))) 152117680Spst return; 152218976Sdfr if (v3) { 152375118Sfenner if (parsewccres(dp, vflag)) 152418976Sdfr return; 152518976Sdfr } else { 152618976Sdfr if (parseattrstat(dp, !qflag, 0) != 0) 152718976Sdfr return; 152818976Sdfr } 152917680Spst break; 153017680Spst 153117680Spst case NFSPROC_LOOKUP: 153217680Spst printf(" lookup"); 153375118Sfenner if (!(dp = parserep(rp, length))) 153418976Sdfr break; 153518976Sdfr if (v3) { 153675118Sfenner if (!(dp = parsestatus(dp, &er))) 153718976Sdfr break; 153818976Sdfr if (er) { 153918976Sdfr if (vflag > 1) { 154018976Sdfr printf(" post dattr:"); 154118976Sdfr dp = parse_post_op_attr(dp, vflag); 154218976Sdfr } 154318976Sdfr } else { 154475118Sfenner if (!(dp = parsefh(dp, v3))) 154518976Sdfr break; 154675118Sfenner if ((dp = parse_post_op_attr(dp, vflag)) && 154775118Sfenner vflag > 1) { 154818976Sdfr printf(" post dattr:"); 154918976Sdfr dp = parse_post_op_attr(dp, vflag); 155018976Sdfr } 155118976Sdfr } 155275118Sfenner if (dp) 155318976Sdfr return; 155418976Sdfr } else { 155518976Sdfr if (parsediropres(dp) != 0) 155618976Sdfr return; 155718976Sdfr } 155817680Spst break; 155917680Spst 156018976Sdfr case NFSPROC_ACCESS: 156118976Sdfr printf(" access"); 156298527Sfenner if (!(dp = parserep(rp, length))) 156398527Sfenner break; 156475118Sfenner if (!(dp = parsestatus(dp, &er))) 156518976Sdfr break; 156618976Sdfr if (vflag) 156718976Sdfr printf(" attr:"); 156875118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 156918976Sdfr break; 157018976Sdfr if (!er) 1571127675Sbms printf(" c %04x", EXTRACT_32BITS(&dp[0])); 157218976Sdfr return; 157318976Sdfr 157417680Spst case NFSPROC_READLINK: 157517680Spst printf(" readlink"); 157617680Spst dp = parserep(rp, length); 157726183Sfenner if (dp != NULL && parselinkres(dp, v3) != 0) 157817680Spst return; 157917680Spst break; 158017680Spst 158117680Spst case NFSPROC_READ: 158217680Spst printf(" read"); 158375118Sfenner if (!(dp = parserep(rp, length))) 158418976Sdfr break; 158518976Sdfr if (v3) { 158675118Sfenner if (!(dp = parsestatus(dp, &er))) 158718976Sdfr break; 158875118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 158918976Sdfr break; 159018976Sdfr if (er) 159118976Sdfr return; 159218976Sdfr if (vflag) { 159375118Sfenner TCHECK(dp[1]); 1594127675Sbms printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 1595127675Sbms if (EXTRACT_32BITS(&dp[1])) 159618976Sdfr printf(" EOF"); 159718976Sdfr } 159817680Spst return; 159918976Sdfr } else { 160018976Sdfr if (parseattrstat(dp, vflag, 0) != 0) 160118976Sdfr return; 160218976Sdfr } 160317680Spst break; 160417680Spst 160517680Spst case NFSPROC_WRITE: 160617680Spst printf(" write"); 160775118Sfenner if (!(dp = parserep(rp, length))) 160818976Sdfr break; 160918976Sdfr if (v3) { 161075118Sfenner if (!(dp = parsestatus(dp, &er))) 161118976Sdfr break; 161275118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 161318976Sdfr break; 161418976Sdfr if (er) 161518976Sdfr return; 161618976Sdfr if (vflag) { 161775118Sfenner TCHECK(dp[0]); 1618127675Sbms printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 161918976Sdfr if (vflag > 1) { 162075118Sfenner TCHECK(dp[1]); 162118976Sdfr printf(" <%s>", 162275118Sfenner tok2str(nfsv3_writemodes, 1623127675Sbms NULL, EXTRACT_32BITS(&dp[1]))); 162418976Sdfr } 162518976Sdfr return; 162618976Sdfr } 162718976Sdfr } else { 162818976Sdfr if (parseattrstat(dp, vflag, v3) != 0) 162918976Sdfr return; 163018976Sdfr } 163117680Spst break; 163217680Spst 163317680Spst case NFSPROC_CREATE: 163417680Spst printf(" create"); 163575118Sfenner if (!(dp = parserep(rp, length))) 163618976Sdfr break; 163718976Sdfr if (v3) { 163875118Sfenner if (parsecreateopres(dp, vflag) != 0) 163918976Sdfr return; 164018976Sdfr } else { 164118976Sdfr if (parsediropres(dp) != 0) 164218976Sdfr return; 164318976Sdfr } 164418976Sdfr break; 164518976Sdfr 164618976Sdfr case NFSPROC_MKDIR: 164718976Sdfr printf(" mkdir"); 164875118Sfenner if (!(dp = parserep(rp, length))) 164918976Sdfr break; 165018976Sdfr if (v3) { 165175118Sfenner if (parsecreateopres(dp, vflag) != 0) 165218976Sdfr return; 165318976Sdfr } else { 165418976Sdfr if (parsediropres(dp) != 0) 165518976Sdfr return; 165618976Sdfr } 165718976Sdfr break; 165818976Sdfr 165918976Sdfr case NFSPROC_SYMLINK: 166018976Sdfr printf(" symlink"); 166175118Sfenner if (!(dp = parserep(rp, length))) 166218976Sdfr break; 166318976Sdfr if (v3) { 166475118Sfenner if (parsecreateopres(dp, vflag) != 0) 166518976Sdfr return; 166618976Sdfr } else { 166775118Sfenner if (parsestatus(dp, &er) != 0) 166818976Sdfr return; 166918976Sdfr } 167018976Sdfr break; 167118976Sdfr 167218976Sdfr case NFSPROC_MKNOD: 167318976Sdfr printf(" mknod"); 167475118Sfenner if (!(dp = parserep(rp, length))) 167518976Sdfr break; 167675118Sfenner if (parsecreateopres(dp, vflag) != 0) 167717680Spst return; 167817680Spst break; 167917680Spst 168017680Spst case NFSPROC_REMOVE: 168117680Spst printf(" remove"); 168275118Sfenner if (!(dp = parserep(rp, length))) 168318976Sdfr break; 168418976Sdfr if (v3) { 168575118Sfenner if (parsewccres(dp, vflag)) 168618976Sdfr return; 168718976Sdfr } else { 168875118Sfenner if (parsestatus(dp, &er) != 0) 168918976Sdfr return; 169018976Sdfr } 169117680Spst break; 169217680Spst 169318976Sdfr case NFSPROC_RMDIR: 169418976Sdfr printf(" rmdir"); 169575118Sfenner if (!(dp = parserep(rp, length))) 169618976Sdfr break; 169718976Sdfr if (v3) { 169875118Sfenner if (parsewccres(dp, vflag)) 169918976Sdfr return; 170018976Sdfr } else { 170175118Sfenner if (parsestatus(dp, &er) != 0) 170218976Sdfr return; 170318976Sdfr } 170418976Sdfr break; 170518976Sdfr 170617680Spst case NFSPROC_RENAME: 170717680Spst printf(" rename"); 170875118Sfenner if (!(dp = parserep(rp, length))) 170918976Sdfr break; 171018976Sdfr if (v3) { 171175118Sfenner if (!(dp = parsestatus(dp, &er))) 171218976Sdfr break; 171318976Sdfr if (vflag) { 171418976Sdfr printf(" from:"); 171575118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 171618976Sdfr break; 171718976Sdfr printf(" to:"); 171875118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 171918976Sdfr break; 172018976Sdfr } 172117680Spst return; 172218976Sdfr } else { 172375118Sfenner if (parsestatus(dp, &er) != 0) 172418976Sdfr return; 172518976Sdfr } 172617680Spst break; 172717680Spst 172817680Spst case NFSPROC_LINK: 172917680Spst printf(" link"); 173075118Sfenner if (!(dp = parserep(rp, length))) 173118976Sdfr break; 173218976Sdfr if (v3) { 173375118Sfenner if (!(dp = parsestatus(dp, &er))) 173418976Sdfr break; 173518976Sdfr if (vflag) { 173618976Sdfr printf(" file POST:"); 173775118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 173818976Sdfr break; 173918976Sdfr printf(" dir:"); 174075118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 174118976Sdfr break; 174218976Sdfr return; 174318976Sdfr } 174418976Sdfr } else { 174575118Sfenner if (parsestatus(dp, &er) != 0) 174618976Sdfr return; 174718976Sdfr } 174817680Spst break; 174917680Spst 175018976Sdfr case NFSPROC_READDIR: 175118976Sdfr printf(" readdir"); 175275118Sfenner if (!(dp = parserep(rp, length))) 175318976Sdfr break; 175418976Sdfr if (v3) { 175575118Sfenner if (parsev3rddirres(dp, vflag)) 175618976Sdfr return; 175718976Sdfr } else { 175818976Sdfr if (parserddires(dp) != 0) 175918976Sdfr return; 176018976Sdfr } 176118976Sdfr break; 176218976Sdfr 176318976Sdfr case NFSPROC_READDIRPLUS: 176418976Sdfr printf(" readdirplus"); 176575118Sfenner if (!(dp = parserep(rp, length))) 176618976Sdfr break; 176775118Sfenner if (parsev3rddirres(dp, vflag)) 176817680Spst return; 176917680Spst break; 177017680Spst 177118976Sdfr case NFSPROC_FSSTAT: 177218976Sdfr printf(" fsstat"); 177317680Spst dp = parserep(rp, length); 177475118Sfenner if (dp != NULL && parsestatfs(dp, v3) != 0) 177517680Spst return; 177617680Spst break; 177717680Spst 177818976Sdfr case NFSPROC_FSINFO: 177918976Sdfr printf(" fsinfo"); 178017680Spst dp = parserep(rp, length); 178175118Sfenner if (dp != NULL && parsefsinfo(dp) != 0) 178217680Spst return; 178317680Spst break; 178417680Spst 178518976Sdfr case NFSPROC_PATHCONF: 178618976Sdfr printf(" pathconf"); 178717680Spst dp = parserep(rp, length); 178826183Sfenner if (dp != NULL && parsepathconf(dp) != 0) 178917680Spst return; 179017680Spst break; 179117680Spst 179218976Sdfr case NFSPROC_COMMIT: 179318976Sdfr printf(" commit"); 179417680Spst dp = parserep(rp, length); 179526183Sfenner if (dp != NULL && parsewccres(dp, vflag) != 0) 179617680Spst return; 179717680Spst break; 179817680Spst 179917680Spst default: 180026183Sfenner printf(" proc-%u", proc); 180117680Spst return; 180217680Spst } 180318976Sdfrtrunc: 180426183Sfenner if (!nfserr) 180526183Sfenner fputs(" [|nfs]", stdout); 180617680Spst} 1807