print-nfs.c revision 190207
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 190207 2009-03-21 18:30:25Z rpaulo $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.110.2.1 2007-12-22 03:08:45 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); 54190207Srpaulostatic int 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 302190207Srpaulo TCHECK(rp->rm_xid); 30375118Sfenner if (!nflag) { 30475118Sfenner strlcpy(srcid, "nfs", sizeof(srcid)); 30575118Sfenner snprintf(dstid, sizeof(dstid), "%u", 306127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 30775118Sfenner } else { 30875118Sfenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 30975118Sfenner snprintf(dstid, sizeof(dstid), "%u", 310127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 31175118Sfenner } 31275118Sfenner print_nfsaddr(bp2, srcid, dstid); 313190207Srpaulo TCHECK(rp->rm_reply.rp_stat); 314172686Smlaier reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat); 315172686Smlaier switch (reply_stat) { 31617680Spst 317172686Smlaier case SUNRPC_MSG_ACCEPTED: 318172686Smlaier (void)printf("reply ok %u", length); 319172686Smlaier if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 320172686Smlaier interp_reply(rp, proc, vers, length); 321172686Smlaier break; 322172686Smlaier 323172686Smlaier case SUNRPC_MSG_DENIED: 324172686Smlaier (void)printf("reply ERR %u: ", length); 325190207Srpaulo TCHECK(rp->rm_reply.rp_reject.rj_stat); 326172686Smlaier rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat); 327172686Smlaier switch (rstat) { 328172686Smlaier 329172686Smlaier case SUNRPC_RPC_MISMATCH: 330190207Srpaulo TCHECK(rp->rm_reply.rp_reject.rj_vers.high); 331172686Smlaier rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low); 332172686Smlaier rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high); 333172686Smlaier (void)printf("RPC Version mismatch (%u-%u)", 334172686Smlaier rlow, rhigh); 335172686Smlaier break; 336172686Smlaier 337172686Smlaier case SUNRPC_AUTH_ERROR: 338190207Srpaulo TCHECK(rp->rm_reply.rp_reject.rj_why); 339172686Smlaier rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why); 340172686Smlaier (void)printf("Auth "); 341172686Smlaier switch (rwhy) { 342172686Smlaier 343172686Smlaier case SUNRPC_AUTH_OK: 344172686Smlaier (void)printf("OK"); 345172686Smlaier break; 346172686Smlaier 347172686Smlaier case SUNRPC_AUTH_BADCRED: 348172686Smlaier (void)printf("Bogus Credentials (seal broken)"); 349172686Smlaier break; 350172686Smlaier 351172686Smlaier case SUNRPC_AUTH_REJECTEDCRED: 352172686Smlaier (void)printf("Rejected Credentials (client should begin new session)"); 353172686Smlaier break; 354172686Smlaier 355172686Smlaier case SUNRPC_AUTH_BADVERF: 356172686Smlaier (void)printf("Bogus Verifier (seal broken)"); 357172686Smlaier break; 358172686Smlaier 359172686Smlaier case SUNRPC_AUTH_REJECTEDVERF: 360172686Smlaier (void)printf("Verifier expired or was replayed"); 361172686Smlaier break; 362172686Smlaier 363172686Smlaier case SUNRPC_AUTH_TOOWEAK: 364172686Smlaier (void)printf("Credentials are too weak"); 365172686Smlaier break; 366172686Smlaier 367172686Smlaier case SUNRPC_AUTH_INVALIDRESP: 368172686Smlaier (void)printf("Bogus response verifier"); 369172686Smlaier break; 370172686Smlaier 371172686Smlaier case SUNRPC_AUTH_FAILED: 372172686Smlaier (void)printf("Unknown failure"); 373172686Smlaier break; 374172686Smlaier 375172686Smlaier default: 376172686Smlaier (void)printf("Invalid failure code %u", 377172686Smlaier (unsigned int)rwhy); 378172686Smlaier break; 379172686Smlaier } 380172686Smlaier break; 381172686Smlaier 382172686Smlaier default: 383172686Smlaier (void)printf("Unknown reason for rejecting rpc message %u", 384172686Smlaier (unsigned int)rstat); 385172686Smlaier break; 386172686Smlaier } 387172686Smlaier break; 388172686Smlaier 389172686Smlaier default: 390172686Smlaier (void)printf("reply Unknown rpc response code=%u %u", 391172686Smlaier reply_stat, length); 392172686Smlaier break; 393172686Smlaier } 394190207Srpaulo return; 395190207Srpaulo 396190207Srpaulotrunc: 397190207Srpaulo if (!nfserr) 398190207Srpaulo fputs(" [|nfs]", stdout); 39917680Spst} 40017680Spst 40117680Spst/* 40217680Spst * Return a pointer to the first file handle in the packet. 40375118Sfenner * If the packet was truncated, return 0. 40417680Spst */ 40517680Spststatic const u_int32_t * 406146778Ssamparsereq(register const struct sunrpc_msg *rp, register u_int length) 40717680Spst{ 40826183Sfenner register const u_int32_t *dp; 40917680Spst register u_int len; 41017680Spst 41117680Spst /* 41217680Spst * find the start of the req data (if we captured it) 41317680Spst */ 41426183Sfenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 41526183Sfenner TCHECK(dp[1]); 416127675Sbms len = EXTRACT_32BITS(&dp[1]); 41726183Sfenner if (len < length) { 41826183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 41926183Sfenner TCHECK(dp[1]); 420127675Sbms len = EXTRACT_32BITS(&dp[1]); 42126183Sfenner if (len < length) { 42226183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 42326183Sfenner TCHECK2(dp[0], 0); 42426183Sfenner return (dp); 42517680Spst } 42617680Spst } 42726183Sfennertrunc: 42826183Sfenner return (NULL); 42917680Spst} 43017680Spst 43117680Spst/* 43217680Spst * Print out an NFS file handle and return a pointer to following word. 43375118Sfenner * If packet was truncated, return 0. 43417680Spst */ 43517680Spststatic const u_int32_t * 43618976Sdfrparsefh(register const u_int32_t *dp, int v3) 43717680Spst{ 438127675Sbms u_int len; 43918976Sdfr 44018976Sdfr if (v3) { 44126183Sfenner TCHECK(dp[0]); 442127675Sbms len = EXTRACT_32BITS(dp) / 4; 44318976Sdfr dp++; 44418976Sdfr } else 44518976Sdfr len = NFSX_V2FH / 4; 44618976Sdfr 44726183Sfenner if (TTEST2(*dp, len * sizeof(*dp))) { 44818976Sdfr nfs_printfh(dp, len); 44918976Sdfr return (dp + len); 45017680Spst } 45126183Sfennertrunc: 45226183Sfenner return (NULL); 45317680Spst} 45417680Spst 45517680Spst/* 45617680Spst * Print out a file name and return pointer to 32-bit word past it. 45775118Sfenner * If packet was truncated, return 0. 45817680Spst */ 45917680Spststatic const u_int32_t * 46017680Spstparsefn(register const u_int32_t *dp) 46117680Spst{ 46217680Spst register u_int32_t len; 46317680Spst register const u_char *cp; 46417680Spst 46517680Spst /* Bail if we don't have the string length */ 46675118Sfenner TCHECK(*dp); 46717680Spst 46817680Spst /* Fetch string length; convert to host order */ 46917680Spst len = *dp++; 47017680Spst NTOHL(len); 47117680Spst 47275118Sfenner TCHECK2(*dp, ((len + 3) & ~3)); 47375118Sfenner 47417680Spst cp = (u_char *)dp; 47517680Spst /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 47617680Spst dp += ((len + 3) & ~3) / sizeof(*dp); 47726183Sfenner putchar('"'); 478147904Ssam if (fn_printn(cp, len, snapend)) { 479147904Ssam putchar('"'); 480147904Ssam goto trunc; 481147904Ssam } 48226183Sfenner putchar('"'); 48317680Spst 48417680Spst return (dp); 48575118Sfennertrunc: 48675118Sfenner return NULL; 48717680Spst} 48817680Spst 48917680Spst/* 49017680Spst * Print out file handle and file name. 49117680Spst * Return pointer to 32-bit word past file name. 49275118Sfenner * If packet was truncated (or there was some other error), return 0. 49317680Spst */ 49417680Spststatic const u_int32_t * 49518976Sdfrparsefhn(register const u_int32_t *dp, int v3) 49617680Spst{ 49718976Sdfr dp = parsefh(dp, v3); 49826183Sfenner if (dp == NULL) 49926183Sfenner return (NULL); 50017680Spst putchar(' '); 50117680Spst return (parsefn(dp)); 50217680Spst} 50317680Spst 50417680Spstvoid 50517680Spstnfsreq_print(register const u_char *bp, u_int length, 50617680Spst register const u_char *bp2) 50717680Spst{ 508146778Ssam register const struct sunrpc_msg *rp; 50917680Spst register const u_int32_t *dp; 51075118Sfenner nfs_type type; 51175118Sfenner int v3; 51275118Sfenner u_int32_t proc; 51318976Sdfr struct nfsv3_sattr sa3; 51475118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 51517680Spst 51626183Sfenner nfserr = 0; /* assume no error */ 517146778Ssam rp = (const struct sunrpc_msg *)bp; 518190207Srpaulo 519190207Srpaulo TCHECK(rp->rm_xid); 52075118Sfenner if (!nflag) { 52175118Sfenner snprintf(srcid, sizeof(srcid), "%u", 522127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 52375118Sfenner strlcpy(dstid, "nfs", sizeof(dstid)); 52475118Sfenner } else { 52575118Sfenner snprintf(srcid, sizeof(srcid), "%u", 526127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 52775118Sfenner snprintf(dstid, sizeof(dstid), "%u", NFS_PORT); 52875118Sfenner } 52975118Sfenner print_nfsaddr(bp2, srcid, dstid); 53075118Sfenner (void)printf("%d", length); 53117680Spst 532190207Srpaulo if (!xid_map_enter(rp, bp2)) /* record proc number for later on */ 533190207Srpaulo goto trunc; 53417680Spst 535127675Sbms v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3); 536127675Sbms proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 53718976Sdfr 53818976Sdfr if (!v3 && proc < NFS_NPROCS) 53918976Sdfr proc = nfsv3_procid[proc]; 54018976Sdfr 54118976Sdfr switch (proc) { 54217680Spst case NFSPROC_NOOP: 54317680Spst printf(" nop"); 54417680Spst return; 54517680Spst case NFSPROC_NULL: 54617680Spst printf(" null"); 54717680Spst return; 54817680Spst 54917680Spst case NFSPROC_GETATTR: 55017680Spst printf(" getattr"); 55175118Sfenner if ((dp = parsereq(rp, length)) != NULL && 55275118Sfenner parsefh(dp, v3) != NULL) 55317680Spst return; 55417680Spst break; 55517680Spst 55617680Spst case NFSPROC_SETATTR: 55717680Spst printf(" setattr"); 55875118Sfenner if ((dp = parsereq(rp, length)) != NULL && 55975118Sfenner parsefh(dp, v3) != NULL) 56017680Spst return; 56117680Spst break; 56217680Spst 56317680Spst case NFSPROC_LOOKUP: 56417680Spst printf(" lookup"); 56575118Sfenner if ((dp = parsereq(rp, length)) != NULL && 56675118Sfenner parsefhn(dp, v3) != NULL) 56717680Spst return; 56817680Spst break; 56917680Spst 57018976Sdfr case NFSPROC_ACCESS: 57118976Sdfr printf(" access"); 57226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 57326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 57475118Sfenner TCHECK(dp[0]); 575127675Sbms printf(" %04x", EXTRACT_32BITS(&dp[0])); 57618976Sdfr return; 57718976Sdfr } 57818976Sdfr break; 57918976Sdfr 58017680Spst case NFSPROC_READLINK: 58117680Spst printf(" readlink"); 58275118Sfenner if ((dp = parsereq(rp, length)) != NULL && 58375118Sfenner parsefh(dp, v3) != NULL) 58417680Spst return; 58517680Spst break; 58617680Spst 58717680Spst case NFSPROC_READ: 58817680Spst printf(" read"); 58926183Sfenner if ((dp = parsereq(rp, length)) != NULL && 59026183Sfenner (dp = parsefh(dp, v3)) != NULL) { 59118976Sdfr if (v3) { 59275118Sfenner TCHECK(dp[2]); 593146778Ssam printf(" %u bytes @ %" PRIu64, 594146778Ssam EXTRACT_32BITS(&dp[2]), 595146778Ssam EXTRACT_64BITS(&dp[0])); 59618976Sdfr } else { 59775118Sfenner TCHECK(dp[1]); 59875118Sfenner printf(" %u bytes @ %u", 599127675Sbms EXTRACT_32BITS(&dp[1]), 600127675Sbms EXTRACT_32BITS(&dp[0])); 60118976Sdfr } 60217680Spst return; 60317680Spst } 60417680Spst break; 60517680Spst 60617680Spst case NFSPROC_WRITE: 60717680Spst printf(" write"); 60826183Sfenner if ((dp = parsereq(rp, length)) != NULL && 60926183Sfenner (dp = parsefh(dp, v3)) != NULL) { 61018976Sdfr if (v3) { 611146778Ssam TCHECK(dp[2]); 612146778Ssam printf(" %u (%u) bytes @ %" PRIu64, 613146778Ssam EXTRACT_32BITS(&dp[4]), 614146778Ssam EXTRACT_32BITS(&dp[2]), 615146778Ssam EXTRACT_64BITS(&dp[0])); 61618976Sdfr if (vflag) { 61718976Sdfr dp += 3; 61875118Sfenner TCHECK(dp[0]); 61918976Sdfr printf(" <%s>", 62075118Sfenner tok2str(nfsv3_writemodes, 621127675Sbms NULL, EXTRACT_32BITS(dp))); 62218976Sdfr } 62318976Sdfr } else { 62475118Sfenner TCHECK(dp[3]); 62575118Sfenner printf(" %u (%u) bytes @ %u (%u)", 626127675Sbms EXTRACT_32BITS(&dp[3]), 627127675Sbms EXTRACT_32BITS(&dp[2]), 628127675Sbms EXTRACT_32BITS(&dp[1]), 629127675Sbms EXTRACT_32BITS(&dp[0])); 63018976Sdfr } 63117680Spst return; 63217680Spst } 63317680Spst break; 63417680Spst 63517680Spst case NFSPROC_CREATE: 63617680Spst printf(" create"); 63775118Sfenner if ((dp = parsereq(rp, length)) != NULL && 63875118Sfenner parsefhn(dp, v3) != NULL) 63917680Spst return; 64017680Spst break; 64117680Spst 64218976Sdfr case NFSPROC_MKDIR: 64318976Sdfr printf(" mkdir"); 64475118Sfenner if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0) 64518976Sdfr return; 64618976Sdfr break; 64718976Sdfr 64818976Sdfr case NFSPROC_SYMLINK: 64918976Sdfr printf(" symlink"); 65075118Sfenner if ((dp = parsereq(rp, length)) != 0 && 65175118Sfenner (dp = parsefhn(dp, v3)) != 0) { 65275118Sfenner fputs(" ->", stdout); 65375118Sfenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0) 65418976Sdfr break; 65575118Sfenner if (parsefn(dp) == 0) 65618976Sdfr break; 65718976Sdfr if (v3 && vflag) 65818976Sdfr print_sattr3(&sa3, vflag); 65918976Sdfr return; 66018976Sdfr } 66118976Sdfr break; 66218976Sdfr 66318976Sdfr case NFSPROC_MKNOD: 66418976Sdfr printf(" mknod"); 66575118Sfenner if ((dp = parsereq(rp, length)) != 0 && 66675118Sfenner (dp = parsefhn(dp, v3)) != 0) { 66775118Sfenner TCHECK(*dp); 668127675Sbms type = (nfs_type)EXTRACT_32BITS(dp); 669127675Sbms dp++; 67075118Sfenner if ((dp = parse_sattr3(dp, &sa3)) == 0) 67118976Sdfr break; 67218976Sdfr printf(" %s", tok2str(type2str, "unk-ft %d", type)); 67318976Sdfr if (vflag && (type == NFCHR || type == NFBLK)) { 67475118Sfenner TCHECK(dp[1]); 67575118Sfenner printf(" %u/%u", 676127675Sbms EXTRACT_32BITS(&dp[0]), 677127675Sbms EXTRACT_32BITS(&dp[1])); 67818976Sdfr dp += 2; 67918976Sdfr } 68018976Sdfr if (vflag) 68118976Sdfr print_sattr3(&sa3, vflag); 68218976Sdfr return; 68318976Sdfr } 68418976Sdfr break; 68518976Sdfr 68617680Spst case NFSPROC_REMOVE: 68717680Spst printf(" remove"); 68875118Sfenner if ((dp = parsereq(rp, length)) != NULL && 68975118Sfenner parsefhn(dp, v3) != NULL) 69017680Spst return; 69117680Spst break; 69217680Spst 69318976Sdfr case NFSPROC_RMDIR: 69418976Sdfr printf(" rmdir"); 69575118Sfenner if ((dp = parsereq(rp, length)) != NULL && 69675118Sfenner parsefhn(dp, v3) != NULL) 69718976Sdfr return; 69818976Sdfr break; 69918976Sdfr 70017680Spst case NFSPROC_RENAME: 70117680Spst printf(" rename"); 70226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 70326183Sfenner (dp = parsefhn(dp, v3)) != NULL) { 70417680Spst fputs(" ->", stdout); 70526183Sfenner if (parsefhn(dp, v3) != NULL) 70617680Spst return; 70717680Spst } 70817680Spst break; 70917680Spst 71017680Spst case NFSPROC_LINK: 71117680Spst printf(" link"); 71226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 71326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 71417680Spst fputs(" ->", stdout); 71526183Sfenner if (parsefhn(dp, v3) != NULL) 71617680Spst return; 71717680Spst } 71817680Spst break; 71917680Spst 72018976Sdfr case NFSPROC_READDIR: 72118976Sdfr printf(" readdir"); 72226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 72326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 72418976Sdfr if (v3) { 72575118Sfenner TCHECK(dp[4]); 72618976Sdfr /* 72718976Sdfr * We shouldn't really try to interpret the 72818976Sdfr * offset cookie here. 72918976Sdfr */ 730146778Ssam printf(" %u bytes @ %" PRId64, 731146778Ssam EXTRACT_32BITS(&dp[4]), 732146778Ssam EXTRACT_64BITS(&dp[0])); 73318976Sdfr if (vflag) 73426183Sfenner printf(" verf %08x%08x", dp[2], 73518976Sdfr dp[3]); 73618976Sdfr } else { 73775118Sfenner TCHECK(dp[1]); 73818976Sdfr /* 73918976Sdfr * Print the offset as signed, since -1 is 74018976Sdfr * common, but offsets > 2^31 aren't. 74118976Sdfr */ 74275118Sfenner printf(" %u bytes @ %d", 743127675Sbms EXTRACT_32BITS(&dp[1]), 744127675Sbms EXTRACT_32BITS(&dp[0])); 74518976Sdfr } 74618976Sdfr return; 74717680Spst } 74817680Spst break; 74917680Spst 75018976Sdfr case NFSPROC_READDIRPLUS: 75118976Sdfr printf(" readdirplus"); 75226183Sfenner if ((dp = parsereq(rp, length)) != NULL && 75326183Sfenner (dp = parsefh(dp, v3)) != NULL) { 75475118Sfenner TCHECK(dp[4]); 75518976Sdfr /* 75618976Sdfr * We don't try to interpret the offset 75718976Sdfr * cookie here. 75818976Sdfr */ 759146778Ssam printf(" %u bytes @ %" PRId64, 760146778Ssam EXTRACT_32BITS(&dp[4]), 761146778Ssam EXTRACT_64BITS(&dp[0])); 762146778Ssam if (vflag) { 763146778Ssam TCHECK(dp[5]); 76475118Sfenner printf(" max %u verf %08x%08x", 765127675Sbms EXTRACT_32BITS(&dp[5]), dp[2], dp[3]); 766146778Ssam } 76717680Spst return; 76818976Sdfr } 76917680Spst break; 77017680Spst 77118976Sdfr case NFSPROC_FSSTAT: 77218976Sdfr printf(" fsstat"); 77375118Sfenner if ((dp = parsereq(rp, length)) != NULL && 77475118Sfenner parsefh(dp, v3) != NULL) 77517680Spst return; 77617680Spst break; 77717680Spst 77818976Sdfr case NFSPROC_FSINFO: 77918976Sdfr printf(" fsinfo"); 780111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 781111729Sfenner parsefh(dp, v3) != NULL) 782111729Sfenner return; 78318976Sdfr break; 78418976Sdfr 78518976Sdfr case NFSPROC_PATHCONF: 78618976Sdfr printf(" pathconf"); 787111729Sfenner if ((dp = parsereq(rp, length)) != NULL && 788111729Sfenner parsefh(dp, v3) != NULL) 789111729Sfenner return; 79018976Sdfr break; 79118976Sdfr 79218976Sdfr case NFSPROC_COMMIT: 79318976Sdfr printf(" commit"); 79426183Sfenner if ((dp = parsereq(rp, length)) != NULL && 79526183Sfenner (dp = parsefh(dp, v3)) != NULL) { 796146778Ssam TCHECK(dp[2]); 797146778Ssam printf(" %u bytes @ %" PRIu64, 798146778Ssam EXTRACT_32BITS(&dp[2]), 799146778Ssam EXTRACT_64BITS(&dp[0])); 80017680Spst return; 80117680Spst } 80217680Spst break; 80317680Spst 80417680Spst default: 805127675Sbms printf(" proc-%u", EXTRACT_32BITS(&rp->rm_call.cb_proc)); 80617680Spst return; 80717680Spst } 80875118Sfenner 80917680Spsttrunc: 81026183Sfenner if (!nfserr) 81126183Sfenner fputs(" [|nfs]", stdout); 81217680Spst} 81317680Spst 81417680Spst/* 81517680Spst * Print out an NFS file handle. 81617680Spst * We assume packet was not truncated before the end of the 81717680Spst * file handle pointed to by dp. 81817680Spst * 81917680Spst * Note: new version (using portable file-handle parser) doesn't produce 82017680Spst * generation number. It probably could be made to do that, with some 82117680Spst * additional hacking on the parser code. 82217680Spst */ 82317680Spststatic void 82475118Sfennernfs_printfh(register const u_int32_t *dp, const u_int len) 82517680Spst{ 82617680Spst my_fsid fsid; 82717680Spst ino_t ino; 828127675Sbms const char *sfsname = NULL; 829127675Sbms char *spacep; 83017680Spst 831127675Sbms if (uflag) { 832127675Sbms u_int i; 833127675Sbms char const *sep = ""; 83417680Spst 835127675Sbms printf(" fh["); 836127675Sbms for (i=0; i<len; i++) { 837127675Sbms (void)printf("%s%x", sep, dp[i]); 838127675Sbms sep = ":"; 839127675Sbms } 840127675Sbms printf("]"); 841127675Sbms return; 842127675Sbms } 843127675Sbms 844127675Sbms Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0); 845127675Sbms 84617680Spst if (sfsname) { 84726183Sfenner /* file system ID is ASCII, not numeric, for this server OS */ 84826183Sfenner static char temp[NFSX_V3FHMAX+1]; 84917680Spst 85026183Sfenner /* Make sure string is null-terminated */ 85126183Sfenner strncpy(temp, sfsname, NFSX_V3FHMAX); 85275118Sfenner temp[sizeof(temp) - 1] = '\0'; 85326183Sfenner /* Remove trailing spaces */ 854127675Sbms spacep = strchr(temp, ' '); 855127675Sbms if (spacep) 856127675Sbms *spacep = '\0'; 85717680Spst 85875118Sfenner (void)printf(" fh %s/", temp); 85926183Sfenner } else { 86075118Sfenner (void)printf(" fh %d,%d/", 86175118Sfenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor); 86217680Spst } 86375118Sfenner 864127675Sbms if(fsid.Fsid_dev.Minor == 257) 865127675Sbms /* Print the undecoded handle */ 86675118Sfenner (void)printf("%s", fsid.Opaque_Handle); 86775118Sfenner else 86875118Sfenner (void)printf("%ld", (long) ino); 86917680Spst} 87017680Spst 87117680Spst/* 87217680Spst * Maintain a small cache of recent client.XID.server/proc pairs, to allow 87317680Spst * us to match up replies with requests and thus to know how to parse 87417680Spst * the reply. 87517680Spst */ 87617680Spst 87717680Spststruct xid_map_entry { 87875118Sfenner u_int32_t xid; /* transaction ID (net order) */ 87975118Sfenner int ipver; /* IP version (4 or 6) */ 88075118Sfenner#ifdef INET6 88175118Sfenner struct in6_addr client; /* client IP address (net order) */ 88275118Sfenner struct in6_addr server; /* server IP address (net order) */ 88375118Sfenner#else 88417680Spst struct in_addr client; /* client IP address (net order) */ 88517680Spst struct in_addr server; /* server IP address (net order) */ 88675118Sfenner#endif 88775118Sfenner u_int32_t proc; /* call proc number (host order) */ 88875118Sfenner u_int32_t vers; /* program version (host order) */ 88917680Spst}; 89017680Spst 89117680Spst/* 89217680Spst * Map entries are kept in an array that we manage as a ring; 89317680Spst * new entries are always added at the tail of the ring. Initially, 89417680Spst * all the entries are zero and hence don't match anything. 89517680Spst */ 89617680Spst 89717680Spst#define XIDMAPSIZE 64 89817680Spst 89917680Spststruct xid_map_entry xid_map[XIDMAPSIZE]; 90017680Spst 90117680Spstint xid_map_next = 0; 90217680Spstint xid_map_hint = 0; 90317680Spst 904190207Srpaulostatic int 905146778Ssamxid_map_enter(const struct sunrpc_msg *rp, const u_char *bp) 90617680Spst{ 90775118Sfenner struct ip *ip = NULL; 90875118Sfenner#ifdef INET6 90975118Sfenner struct ip6_hdr *ip6 = NULL; 91075118Sfenner#endif 91117680Spst struct xid_map_entry *xmep; 91217680Spst 913190207Srpaulo if (!TTEST(rp->rm_call.cb_vers)) 914190207Srpaulo return (0); 91575118Sfenner switch (IP_V((struct ip *)bp)) { 91675118Sfenner case 4: 91775118Sfenner ip = (struct ip *)bp; 91875118Sfenner break; 91975118Sfenner#ifdef INET6 92075118Sfenner case 6: 92175118Sfenner ip6 = (struct ip6_hdr *)bp; 92275118Sfenner break; 92375118Sfenner#endif 92475118Sfenner default: 925190207Srpaulo return (1); 92675118Sfenner } 92775118Sfenner 92817680Spst xmep = &xid_map[xid_map_next]; 92917680Spst 93017680Spst if (++xid_map_next >= XIDMAPSIZE) 93117680Spst xid_map_next = 0; 93217680Spst 93317680Spst xmep->xid = rp->rm_xid; 93475118Sfenner if (ip) { 93575118Sfenner xmep->ipver = 4; 93675118Sfenner memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 93775118Sfenner memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 93875118Sfenner } 93975118Sfenner#ifdef INET6 94075118Sfenner else if (ip6) { 94175118Sfenner xmep->ipver = 6; 94275118Sfenner memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 94375118Sfenner memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 94475118Sfenner } 94575118Sfenner#endif 946127675Sbms xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 947127675Sbms xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers); 948190207Srpaulo return (1); 94917680Spst} 95017680Spst 95126183Sfenner/* 95226183Sfenner * Returns 0 and puts NFSPROC_xxx in proc return and 95326183Sfenner * version in vers return, or returns -1 on failure 95426183Sfenner */ 95518976Sdfrstatic int 956146778Ssamxid_map_find(const struct sunrpc_msg *rp, const u_char *bp, u_int32_t *proc, 95718976Sdfr u_int32_t *vers) 95817680Spst{ 95917680Spst int i; 96017680Spst struct xid_map_entry *xmep; 96117680Spst u_int32_t xid = rp->rm_xid; 96275118Sfenner struct ip *ip = (struct ip *)bp; 96375118Sfenner#ifdef INET6 96475118Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 96575118Sfenner#endif 96675118Sfenner int cmp; 96717680Spst 96817680Spst /* Start searching from where we last left off */ 969127675Sbms i = xid_map_hint; 97017680Spst do { 97117680Spst xmep = &xid_map[i]; 97275118Sfenner cmp = 1; 97375118Sfenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 97475118Sfenner goto nextitem; 97575118Sfenner switch (xmep->ipver) { 97675118Sfenner case 4: 97775118Sfenner if (memcmp(&ip->ip_src, &xmep->server, 97875118Sfenner sizeof(ip->ip_src)) != 0 || 97975118Sfenner memcmp(&ip->ip_dst, &xmep->client, 98075118Sfenner sizeof(ip->ip_dst)) != 0) { 98175118Sfenner cmp = 0; 98275118Sfenner } 98375118Sfenner break; 98475118Sfenner#ifdef INET6 98575118Sfenner case 6: 98675118Sfenner if (memcmp(&ip6->ip6_src, &xmep->server, 98775118Sfenner sizeof(ip6->ip6_src)) != 0 || 98875118Sfenner memcmp(&ip6->ip6_dst, &xmep->client, 98975118Sfenner sizeof(ip6->ip6_dst)) != 0) { 99075118Sfenner cmp = 0; 99175118Sfenner } 99275118Sfenner break; 99375118Sfenner#endif 99475118Sfenner default: 99575118Sfenner cmp = 0; 99675118Sfenner break; 99775118Sfenner } 99875118Sfenner if (cmp) { 99917680Spst /* match */ 100017680Spst xid_map_hint = i; 100118976Sdfr *proc = xmep->proc; 100218976Sdfr *vers = xmep->vers; 100318976Sdfr return 0; 100417680Spst } 100575118Sfenner nextitem: 100617680Spst if (++i >= XIDMAPSIZE) 100717680Spst i = 0; 100817680Spst } while (i != xid_map_hint); 100917680Spst 101017680Spst /* search failed */ 101175118Sfenner return (-1); 101217680Spst} 101317680Spst 101417680Spst/* 101517680Spst * Routines for parsing reply packets 101617680Spst */ 101717680Spst 101817680Spst/* 101917680Spst * Return a pointer to the beginning of the actual results. 102075118Sfenner * If the packet was truncated, return 0. 102117680Spst */ 102217680Spststatic const u_int32_t * 1023146778Ssamparserep(register const struct sunrpc_msg *rp, register u_int length) 102417680Spst{ 102517680Spst register const u_int32_t *dp; 102675118Sfenner u_int len; 1027146778Ssam enum sunrpc_accept_stat astat; 102817680Spst 102917680Spst /* 103017680Spst * Portability note: 103117680Spst * Here we find the address of the ar_verf credentials. 103217680Spst * Originally, this calculation was 103317680Spst * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 103417680Spst * On the wire, the rp_acpt field starts immediately after 103517680Spst * the (32 bit) rp_stat field. However, rp_acpt (which is a 103617680Spst * "struct accepted_reply") contains a "struct opaque_auth", 103717680Spst * whose internal representation contains a pointer, so on a 103817680Spst * 64-bit machine the compiler inserts 32 bits of padding 103917680Spst * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 104017680Spst * the internal representation to parse the on-the-wire 104117680Spst * representation. Instead, we skip past the rp_stat field, 104217680Spst * which is an "enum" and so occupies one 32-bit word. 104317680Spst */ 104417680Spst dp = ((const u_int32_t *)&rp->rm_reply) + 1; 104575118Sfenner TCHECK(dp[1]); 1046127675Sbms len = EXTRACT_32BITS(&dp[1]); 104717680Spst if (len >= length) 104826183Sfenner return (NULL); 104917680Spst /* 105017680Spst * skip past the ar_verf credentials. 105117680Spst */ 105217680Spst dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 105326183Sfenner TCHECK2(dp[0], 0); 105417680Spst 105517680Spst /* 105617680Spst * now we can check the ar_stat field 105717680Spst */ 1058147904Ssam astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); 105917680Spst switch (astat) { 106017680Spst 1061146778Ssam case SUNRPC_SUCCESS: 106217680Spst break; 106317680Spst 1064146778Ssam case SUNRPC_PROG_UNAVAIL: 106517680Spst printf(" PROG_UNAVAIL"); 106626183Sfenner nfserr = 1; /* suppress trunc string */ 106726183Sfenner return (NULL); 106817680Spst 1069146778Ssam case SUNRPC_PROG_MISMATCH: 107017680Spst printf(" PROG_MISMATCH"); 107126183Sfenner nfserr = 1; /* suppress trunc string */ 107226183Sfenner return (NULL); 107317680Spst 1074146778Ssam case SUNRPC_PROC_UNAVAIL: 107517680Spst printf(" PROC_UNAVAIL"); 107626183Sfenner nfserr = 1; /* suppress trunc string */ 107726183Sfenner return (NULL); 107817680Spst 1079146778Ssam case SUNRPC_GARBAGE_ARGS: 108017680Spst printf(" GARBAGE_ARGS"); 108126183Sfenner nfserr = 1; /* suppress trunc string */ 108226183Sfenner return (NULL); 108317680Spst 1084146778Ssam case SUNRPC_SYSTEM_ERR: 108517680Spst printf(" SYSTEM_ERR"); 108626183Sfenner nfserr = 1; /* suppress trunc string */ 108726183Sfenner return (NULL); 108817680Spst 108917680Spst default: 109017680Spst printf(" ar_stat %d", astat); 109126183Sfenner nfserr = 1; /* suppress trunc string */ 109226183Sfenner return (NULL); 109317680Spst } 109417680Spst /* successful return */ 109575118Sfenner TCHECK2(*dp, sizeof(astat)); 109675118Sfenner return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 109726183Sfennertrunc: 109875118Sfenner return (0); 109917680Spst} 110017680Spst 110117680Spststatic const u_int32_t * 110218976Sdfrparsestatus(const u_int32_t *dp, int *er) 110317680Spst{ 110475118Sfenner int errnum; 110517680Spst 110626183Sfenner TCHECK(dp[0]); 110775118Sfenner 1108127675Sbms errnum = EXTRACT_32BITS(&dp[0]); 110918976Sdfr if (er) 111026183Sfenner *er = errnum; 111126183Sfenner if (errnum != 0) { 111226183Sfenner if (!qflag) 111375118Sfenner printf(" ERROR: %s", 111475118Sfenner tok2str(status2str, "unk %d", errnum)); 111526183Sfenner nfserr = 1; 111617680Spst } 111717680Spst return (dp + 1); 111826183Sfennertrunc: 111975118Sfenner return NULL; 112017680Spst} 112117680Spst 112217680Spststatic const u_int32_t * 112318976Sdfrparsefattr(const u_int32_t *dp, int verbose, int v3) 112417680Spst{ 112518976Sdfr const struct nfs_fattr *fap; 112617680Spst 112718976Sdfr fap = (const struct nfs_fattr *)dp; 112826184Sfenner TCHECK(fap->fa_gid); 112917680Spst if (verbose) { 113075118Sfenner printf(" %s %o ids %d/%d", 113175118Sfenner tok2str(type2str, "unk-ft %d ", 1132127675Sbms EXTRACT_32BITS(&fap->fa_type)), 1133127675Sbms EXTRACT_32BITS(&fap->fa_mode), 1134127675Sbms EXTRACT_32BITS(&fap->fa_uid), 1135127675Sbms EXTRACT_32BITS(&fap->fa_gid)); 113618976Sdfr if (v3) { 113726184Sfenner TCHECK(fap->fa3_size); 1138146778Ssam printf(" sz %" PRIu64, 1139146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_size)); 114026184Sfenner } else { 114126184Sfenner TCHECK(fap->fa2_size); 1142127675Sbms printf(" sz %d", EXTRACT_32BITS(&fap->fa2_size)); 114318976Sdfr } 114417680Spst } 114517680Spst /* print lots more stuff */ 114617680Spst if (verbose > 1) { 114718976Sdfr if (v3) { 114826184Sfenner TCHECK(fap->fa3_ctime); 1149127675Sbms printf(" nlink %d rdev %d/%d", 1150127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1151127675Sbms EXTRACT_32BITS(&fap->fa3_rdev.specdata1), 1152127675Sbms EXTRACT_32BITS(&fap->fa3_rdev.specdata2)); 1153146778Ssam printf(" fsid %" PRIx64, 1154146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_fsid)); 1155146778Ssam printf(" fileid %" PRIx64, 1156146778Ssam EXTRACT_64BITS((u_int32_t *)&fap->fa3_fileid)); 1157127675Sbms printf(" a/m/ctime %u.%06u", 1158127675Sbms EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec), 1159127675Sbms EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)); 1160127675Sbms printf(" %u.%06u", 1161127675Sbms EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec), 1162127675Sbms EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)); 1163127675Sbms printf(" %u.%06u", 1164127675Sbms EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec), 1165127675Sbms EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)); 116618976Sdfr } else { 116726184Sfenner TCHECK(fap->fa2_ctime); 1168127675Sbms printf(" nlink %d rdev %x fsid %x nodeid %x a/m/ctime", 1169127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1170127675Sbms EXTRACT_32BITS(&fap->fa2_rdev), 1171127675Sbms EXTRACT_32BITS(&fap->fa2_fsid), 1172127675Sbms EXTRACT_32BITS(&fap->fa2_fileid)); 1173127675Sbms printf(" %u.%06u", 1174127675Sbms EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec), 1175127675Sbms EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)); 1176127675Sbms printf(" %u.%06u", 1177127675Sbms EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec), 1178127675Sbms EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)); 1179127675Sbms printf(" %u.%06u", 1180127675Sbms EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec), 1181127675Sbms EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)); 118218976Sdfr } 118317680Spst } 118418976Sdfr return ((const u_int32_t *)((unsigned char *)dp + 118518976Sdfr (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 118626184Sfennertrunc: 118726184Sfenner return (NULL); 118817680Spst} 118917680Spst 119017680Spststatic int 119118976Sdfrparseattrstat(const u_int32_t *dp, int verbose, int v3) 119217680Spst{ 119318976Sdfr int er; 119418976Sdfr 119518976Sdfr dp = parsestatus(dp, &er); 1196111729Sfenner if (dp == NULL) 119717680Spst return (0); 1198111729Sfenner if (er) 1199111729Sfenner return (1); 120017680Spst 120126183Sfenner return (parsefattr(dp, verbose, v3) != NULL); 120217680Spst} 120317680Spst 120417680Spststatic int 120517680Spstparsediropres(const u_int32_t *dp) 120617680Spst{ 120718976Sdfr int er; 120818976Sdfr 1209111729Sfenner if (!(dp = parsestatus(dp, &er))) 121017680Spst return (0); 1211111729Sfenner if (er) 1212111729Sfenner return (1); 121317680Spst 121418976Sdfr dp = parsefh(dp, 0); 121517680Spst if (dp == NULL) 121617680Spst return (0); 121717680Spst 121818976Sdfr return (parsefattr(dp, vflag, 0) != NULL); 121917680Spst} 122017680Spst 122117680Spststatic int 122218976Sdfrparselinkres(const u_int32_t *dp, int v3) 122317680Spst{ 122418976Sdfr int er; 122518976Sdfr 122618976Sdfr dp = parsestatus(dp, &er); 1227111729Sfenner if (dp == NULL) 122817680Spst return(0); 1229111729Sfenner if (er) 1230111729Sfenner return(1); 123175118Sfenner if (v3 && !(dp = parse_post_op_attr(dp, vflag))) 123218976Sdfr return (0); 123317680Spst putchar(' '); 123417680Spst return (parsefn(dp) != NULL); 123517680Spst} 123617680Spst 123717680Spststatic int 123818976Sdfrparsestatfs(const u_int32_t *dp, int v3) 123917680Spst{ 124018976Sdfr const struct nfs_statfs *sfsp; 124118976Sdfr int er; 124217680Spst 124318976Sdfr dp = parsestatus(dp, &er); 1244111729Sfenner if (dp == NULL) 124575118Sfenner return (0); 1246111729Sfenner if (!v3 && er) 1247111729Sfenner return (1); 124817680Spst 124918976Sdfr if (qflag) 125018976Sdfr return(1); 125118976Sdfr 125218976Sdfr if (v3) { 125318976Sdfr if (vflag) 125418976Sdfr printf(" POST:"); 125575118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 125618976Sdfr return (0); 125717680Spst } 125817680Spst 1259111729Sfenner TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 126018976Sdfr 126118976Sdfr sfsp = (const struct nfs_statfs *)dp; 126218976Sdfr 126318976Sdfr if (v3) { 1264146778Ssam printf(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64, 1265146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tbytes), 1266146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_fbytes), 1267146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_abytes)); 126818976Sdfr if (vflag) { 1269146778Ssam printf(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u", 1270146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_tfiles), 1271146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_ffiles), 1272146778Ssam EXTRACT_64BITS((u_int32_t *)&sfsp->sf_afiles), 1273127675Sbms EXTRACT_32BITS(&sfsp->sf_invarsec)); 127418976Sdfr } 127518976Sdfr } else { 127675118Sfenner printf(" tsize %d bsize %d blocks %d bfree %d bavail %d", 1277127675Sbms EXTRACT_32BITS(&sfsp->sf_tsize), 1278127675Sbms EXTRACT_32BITS(&sfsp->sf_bsize), 1279127675Sbms EXTRACT_32BITS(&sfsp->sf_blocks), 1280127675Sbms EXTRACT_32BITS(&sfsp->sf_bfree), 1281127675Sbms EXTRACT_32BITS(&sfsp->sf_bavail)); 128218976Sdfr } 128318976Sdfr 128417680Spst return (1); 128526184Sfennertrunc: 128626184Sfenner return (0); 128717680Spst} 128817680Spst 128917680Spststatic int 129017680Spstparserddires(const u_int32_t *dp) 129117680Spst{ 129218976Sdfr int er; 129318976Sdfr 129418976Sdfr dp = parsestatus(dp, &er); 1295111729Sfenner if (dp == NULL) 129617680Spst return (0); 1297111729Sfenner if (er) 1298111729Sfenner return (1); 129918976Sdfr if (qflag) 130018976Sdfr return (1); 130118976Sdfr 130226184Sfenner TCHECK(dp[2]); 130375118Sfenner printf(" offset %x size %d ", 1304127675Sbms EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])); 130518976Sdfr if (dp[2] != 0) 130675118Sfenner printf(" eof"); 130718976Sdfr 130818976Sdfr return (1); 130926184Sfennertrunc: 131026184Sfenner return (0); 131118976Sdfr} 131218976Sdfr 131318976Sdfrstatic const u_int32_t * 131418976Sdfrparse_wcc_attr(const u_int32_t *dp) 131518976Sdfr{ 1316146778Ssam printf(" sz %" PRIu64, EXTRACT_64BITS(&dp[0])); 131775118Sfenner printf(" mtime %u.%06u ctime %u.%06u", 1318127675Sbms EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]), 1319127675Sbms EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])); 132018976Sdfr return (dp + 6); 132118976Sdfr} 132218976Sdfr 132318976Sdfr/* 132418976Sdfr * Pre operation attributes. Print only if vflag > 1. 132518976Sdfr */ 132618976Sdfrstatic const u_int32_t * 132718976Sdfrparse_pre_op_attr(const u_int32_t *dp, int verbose) 132818976Sdfr{ 132926184Sfenner TCHECK(dp[0]); 1330127675Sbms if (!EXTRACT_32BITS(&dp[0])) 133118976Sdfr return (dp + 1); 133218976Sdfr dp++; 1333111729Sfenner TCHECK2(*dp, 24); 133418976Sdfr if (verbose > 1) { 133518976Sdfr return parse_wcc_attr(dp); 133618976Sdfr } else { 133718976Sdfr /* If not verbose enough, just skip over wcc_attr */ 133818976Sdfr return (dp + 6); 133917680Spst } 134026184Sfennertrunc: 134126184Sfenner return (NULL); 134218976Sdfr} 134317680Spst 134418976Sdfr/* 134518976Sdfr * Post operation attributes are printed if vflag >= 1 134618976Sdfr */ 134718976Sdfrstatic const u_int32_t * 134818976Sdfrparse_post_op_attr(const u_int32_t *dp, int verbose) 134918976Sdfr{ 135026184Sfenner TCHECK(dp[0]); 1351127675Sbms if (!EXTRACT_32BITS(&dp[0])) 135218976Sdfr return (dp + 1); 135318976Sdfr dp++; 135418976Sdfr if (verbose) { 135518976Sdfr return parsefattr(dp, verbose, 1); 135618976Sdfr } else 135718976Sdfr return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 135826184Sfennertrunc: 135926184Sfenner return (NULL); 136018976Sdfr} 136118976Sdfr 136218976Sdfrstatic const u_int32_t * 136318976Sdfrparse_wcc_data(const u_int32_t *dp, int verbose) 136418976Sdfr{ 136518976Sdfr if (verbose > 1) 136618976Sdfr printf(" PRE:"); 136775118Sfenner if (!(dp = parse_pre_op_attr(dp, verbose))) 136875118Sfenner return (0); 136918976Sdfr 137018976Sdfr if (verbose) 137118976Sdfr printf(" POST:"); 137218976Sdfr return parse_post_op_attr(dp, verbose); 137318976Sdfr} 137418976Sdfr 137518976Sdfrstatic const u_int32_t * 137618976Sdfrparsecreateopres(const u_int32_t *dp, int verbose) 137718976Sdfr{ 137818976Sdfr int er; 137918976Sdfr 138075118Sfenner if (!(dp = parsestatus(dp, &er))) 138175118Sfenner return (0); 138218976Sdfr if (er) 138318976Sdfr dp = parse_wcc_data(dp, verbose); 138418976Sdfr else { 138526184Sfenner TCHECK(dp[0]); 1386127675Sbms if (!EXTRACT_32BITS(&dp[0])) 138718976Sdfr return (dp + 1); 138818976Sdfr dp++; 138975118Sfenner if (!(dp = parsefh(dp, 1))) 139075118Sfenner return (0); 139118976Sdfr if (verbose) { 139275118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 139375118Sfenner return (0); 139418976Sdfr if (vflag > 1) { 1395127675Sbms printf(" dir attr:"); 139618976Sdfr dp = parse_wcc_data(dp, verbose); 139718976Sdfr } 139818976Sdfr } 139918976Sdfr } 140018976Sdfr return (dp); 140126184Sfennertrunc: 140226184Sfenner return (NULL); 140318976Sdfr} 140418976Sdfr 140518976Sdfrstatic int 140618976Sdfrparsewccres(const u_int32_t *dp, int verbose) 140718976Sdfr{ 140818976Sdfr int er; 140918976Sdfr 141075118Sfenner if (!(dp = parsestatus(dp, &er))) 141118976Sdfr return (0); 141275118Sfenner return parse_wcc_data(dp, verbose) != 0; 141318976Sdfr} 141418976Sdfr 141518976Sdfrstatic const u_int32_t * 141618976Sdfrparsev3rddirres(const u_int32_t *dp, int verbose) 141718976Sdfr{ 141818976Sdfr int er; 141918976Sdfr 142075118Sfenner if (!(dp = parsestatus(dp, &er))) 142175118Sfenner return (0); 142218976Sdfr if (vflag) 142318976Sdfr printf(" POST:"); 142475118Sfenner if (!(dp = parse_post_op_attr(dp, verbose))) 142575118Sfenner return (0); 142618976Sdfr if (er) 142718976Sdfr return dp; 142818976Sdfr if (vflag) { 142926184Sfenner TCHECK(dp[1]); 143026183Sfenner printf(" verf %08x%08x", dp[0], dp[1]); 143118976Sdfr dp += 2; 143218976Sdfr } 143318976Sdfr return dp; 143426184Sfennertrunc: 143526184Sfenner return (NULL); 143618976Sdfr} 143718976Sdfr 143818976Sdfrstatic int 143918976Sdfrparsefsinfo(const u_int32_t *dp) 144018976Sdfr{ 144118976Sdfr struct nfsv3_fsinfo *sfp; 144218976Sdfr int er; 144318976Sdfr 144475118Sfenner if (!(dp = parsestatus(dp, &er))) 144518976Sdfr return (0); 144618976Sdfr if (vflag) 144718976Sdfr printf(" POST:"); 144875118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 144918976Sdfr return (0); 145018976Sdfr if (er) 145118976Sdfr return (1); 145218976Sdfr 145318976Sdfr sfp = (struct nfsv3_fsinfo *)dp; 145426184Sfenner TCHECK(*sfp); 145575118Sfenner printf(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 1456127675Sbms EXTRACT_32BITS(&sfp->fs_rtmax), 1457127675Sbms EXTRACT_32BITS(&sfp->fs_rtpref), 1458127675Sbms EXTRACT_32BITS(&sfp->fs_wtmax), 1459127675Sbms EXTRACT_32BITS(&sfp->fs_wtpref), 1460127675Sbms EXTRACT_32BITS(&sfp->fs_dtpref)); 146118976Sdfr if (vflag) { 1462146778Ssam printf(" rtmult %u wtmult %u maxfsz %" PRIu64, 1463127675Sbms EXTRACT_32BITS(&sfp->fs_rtmult), 1464146778Ssam EXTRACT_32BITS(&sfp->fs_wtmult), 1465146778Ssam EXTRACT_64BITS((u_int32_t *)&sfp->fs_maxfilesize)); 146675118Sfenner printf(" delta %u.%06u ", 1467127675Sbms EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec), 1468127675Sbms EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)); 146918976Sdfr } 1470111729Sfenner return (1); 1471111729Sfennertrunc: 147275118Sfenner return (0); 147318976Sdfr} 147418976Sdfr 147518976Sdfrstatic int 147618976Sdfrparsepathconf(const u_int32_t *dp) 147718976Sdfr{ 147818976Sdfr int er; 147918976Sdfr struct nfsv3_pathconf *spp; 148018976Sdfr 148175118Sfenner if (!(dp = parsestatus(dp, &er))) 148218976Sdfr return (0); 148318976Sdfr if (vflag) 148418976Sdfr printf(" POST:"); 148575118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 148618976Sdfr return (0); 148718976Sdfr if (er) 148818976Sdfr return (1); 148918976Sdfr 149018976Sdfr spp = (struct nfsv3_pathconf *)dp; 149126184Sfenner TCHECK(*spp); 149218976Sdfr 149375118Sfenner printf(" linkmax %u namemax %u %s %s %s %s", 1494127675Sbms EXTRACT_32BITS(&spp->pc_linkmax), 1495127675Sbms EXTRACT_32BITS(&spp->pc_namemax), 1496127675Sbms EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "", 1497127675Sbms EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "", 1498127675Sbms EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "", 1499127675Sbms EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""); 1500111729Sfenner return (1); 1501111729Sfennertrunc: 150275118Sfenner return (0); 150317680Spst} 150475118Sfenner 150517680Spststatic void 1506146778Ssaminterp_reply(const struct sunrpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 150717680Spst{ 150817680Spst register const u_int32_t *dp; 150918976Sdfr register int v3; 151018976Sdfr int er; 151117680Spst 151218976Sdfr v3 = (vers == NFS_VER3); 151318976Sdfr 151418976Sdfr if (!v3 && proc < NFS_NPROCS) 151518976Sdfr proc = nfsv3_procid[proc]; 151618976Sdfr 151717680Spst switch (proc) { 151817680Spst 151917680Spst case NFSPROC_NOOP: 152017680Spst printf(" nop"); 152117680Spst return; 152218976Sdfr 152317680Spst case NFSPROC_NULL: 152417680Spst printf(" null"); 152517680Spst return; 152617680Spst 152717680Spst case NFSPROC_GETATTR: 152817680Spst printf(" getattr"); 152917680Spst dp = parserep(rp, length); 153026183Sfenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 153117680Spst return; 153217680Spst break; 153317680Spst 153417680Spst case NFSPROC_SETATTR: 153517680Spst printf(" setattr"); 153675118Sfenner if (!(dp = parserep(rp, length))) 153717680Spst return; 153818976Sdfr if (v3) { 153975118Sfenner if (parsewccres(dp, vflag)) 154018976Sdfr return; 154118976Sdfr } else { 154218976Sdfr if (parseattrstat(dp, !qflag, 0) != 0) 154318976Sdfr return; 154418976Sdfr } 154517680Spst break; 154617680Spst 154717680Spst case NFSPROC_LOOKUP: 154817680Spst printf(" lookup"); 154975118Sfenner if (!(dp = parserep(rp, length))) 155018976Sdfr break; 155118976Sdfr if (v3) { 155275118Sfenner if (!(dp = parsestatus(dp, &er))) 155318976Sdfr break; 155418976Sdfr if (er) { 155518976Sdfr if (vflag > 1) { 155618976Sdfr printf(" post dattr:"); 155718976Sdfr dp = parse_post_op_attr(dp, vflag); 155818976Sdfr } 155918976Sdfr } else { 156075118Sfenner if (!(dp = parsefh(dp, v3))) 156118976Sdfr break; 156275118Sfenner if ((dp = parse_post_op_attr(dp, vflag)) && 156375118Sfenner vflag > 1) { 156418976Sdfr printf(" post dattr:"); 156518976Sdfr dp = parse_post_op_attr(dp, vflag); 156618976Sdfr } 156718976Sdfr } 156875118Sfenner if (dp) 156918976Sdfr return; 157018976Sdfr } else { 157118976Sdfr if (parsediropres(dp) != 0) 157218976Sdfr return; 157318976Sdfr } 157417680Spst break; 157517680Spst 157618976Sdfr case NFSPROC_ACCESS: 157718976Sdfr printf(" access"); 157898527Sfenner if (!(dp = parserep(rp, length))) 157998527Sfenner break; 158075118Sfenner if (!(dp = parsestatus(dp, &er))) 158118976Sdfr break; 158218976Sdfr if (vflag) 158318976Sdfr printf(" attr:"); 158475118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 158518976Sdfr break; 158618976Sdfr if (!er) 1587127675Sbms printf(" c %04x", EXTRACT_32BITS(&dp[0])); 158818976Sdfr return; 158918976Sdfr 159017680Spst case NFSPROC_READLINK: 159117680Spst printf(" readlink"); 159217680Spst dp = parserep(rp, length); 159326183Sfenner if (dp != NULL && parselinkres(dp, v3) != 0) 159417680Spst return; 159517680Spst break; 159617680Spst 159717680Spst case NFSPROC_READ: 159817680Spst printf(" read"); 159975118Sfenner if (!(dp = parserep(rp, length))) 160018976Sdfr break; 160118976Sdfr if (v3) { 160275118Sfenner if (!(dp = parsestatus(dp, &er))) 160318976Sdfr break; 160475118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 160518976Sdfr break; 160618976Sdfr if (er) 160718976Sdfr return; 160818976Sdfr if (vflag) { 160975118Sfenner TCHECK(dp[1]); 1610127675Sbms printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 1611127675Sbms if (EXTRACT_32BITS(&dp[1])) 161218976Sdfr printf(" EOF"); 161318976Sdfr } 161417680Spst return; 161518976Sdfr } else { 161618976Sdfr if (parseattrstat(dp, vflag, 0) != 0) 161718976Sdfr return; 161818976Sdfr } 161917680Spst break; 162017680Spst 162117680Spst case NFSPROC_WRITE: 162217680Spst printf(" write"); 162375118Sfenner if (!(dp = parserep(rp, length))) 162418976Sdfr break; 162518976Sdfr if (v3) { 162675118Sfenner if (!(dp = parsestatus(dp, &er))) 162718976Sdfr break; 162875118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 162918976Sdfr break; 163018976Sdfr if (er) 163118976Sdfr return; 163218976Sdfr if (vflag) { 163375118Sfenner TCHECK(dp[0]); 1634127675Sbms printf(" %u bytes", EXTRACT_32BITS(&dp[0])); 163518976Sdfr if (vflag > 1) { 163675118Sfenner TCHECK(dp[1]); 163718976Sdfr printf(" <%s>", 163875118Sfenner tok2str(nfsv3_writemodes, 1639127675Sbms NULL, EXTRACT_32BITS(&dp[1]))); 164018976Sdfr } 164118976Sdfr return; 164218976Sdfr } 164318976Sdfr } else { 164418976Sdfr if (parseattrstat(dp, vflag, v3) != 0) 164518976Sdfr return; 164618976Sdfr } 164717680Spst break; 164817680Spst 164917680Spst case NFSPROC_CREATE: 165017680Spst printf(" create"); 165175118Sfenner if (!(dp = parserep(rp, length))) 165218976Sdfr break; 165318976Sdfr if (v3) { 165475118Sfenner if (parsecreateopres(dp, vflag) != 0) 165518976Sdfr return; 165618976Sdfr } else { 165718976Sdfr if (parsediropres(dp) != 0) 165818976Sdfr return; 165918976Sdfr } 166018976Sdfr break; 166118976Sdfr 166218976Sdfr case NFSPROC_MKDIR: 166318976Sdfr printf(" mkdir"); 166475118Sfenner if (!(dp = parserep(rp, length))) 166518976Sdfr break; 166618976Sdfr if (v3) { 166775118Sfenner if (parsecreateopres(dp, vflag) != 0) 166818976Sdfr return; 166918976Sdfr } else { 167018976Sdfr if (parsediropres(dp) != 0) 167118976Sdfr return; 167218976Sdfr } 167318976Sdfr break; 167418976Sdfr 167518976Sdfr case NFSPROC_SYMLINK: 167618976Sdfr printf(" symlink"); 167775118Sfenner if (!(dp = parserep(rp, length))) 167818976Sdfr break; 167918976Sdfr if (v3) { 168075118Sfenner if (parsecreateopres(dp, vflag) != 0) 168118976Sdfr return; 168218976Sdfr } else { 168375118Sfenner if (parsestatus(dp, &er) != 0) 168418976Sdfr return; 168518976Sdfr } 168618976Sdfr break; 168718976Sdfr 168818976Sdfr case NFSPROC_MKNOD: 168918976Sdfr printf(" mknod"); 169075118Sfenner if (!(dp = parserep(rp, length))) 169118976Sdfr break; 169275118Sfenner if (parsecreateopres(dp, vflag) != 0) 169317680Spst return; 169417680Spst break; 169517680Spst 169617680Spst case NFSPROC_REMOVE: 169717680Spst printf(" remove"); 169875118Sfenner if (!(dp = parserep(rp, length))) 169918976Sdfr break; 170018976Sdfr if (v3) { 170175118Sfenner if (parsewccres(dp, vflag)) 170218976Sdfr return; 170318976Sdfr } else { 170475118Sfenner if (parsestatus(dp, &er) != 0) 170518976Sdfr return; 170618976Sdfr } 170717680Spst break; 170817680Spst 170918976Sdfr case NFSPROC_RMDIR: 171018976Sdfr printf(" rmdir"); 171175118Sfenner if (!(dp = parserep(rp, length))) 171218976Sdfr break; 171318976Sdfr if (v3) { 171475118Sfenner if (parsewccres(dp, vflag)) 171518976Sdfr return; 171618976Sdfr } else { 171775118Sfenner if (parsestatus(dp, &er) != 0) 171818976Sdfr return; 171918976Sdfr } 172018976Sdfr break; 172118976Sdfr 172217680Spst case NFSPROC_RENAME: 172317680Spst printf(" rename"); 172475118Sfenner if (!(dp = parserep(rp, length))) 172518976Sdfr break; 172618976Sdfr if (v3) { 172775118Sfenner if (!(dp = parsestatus(dp, &er))) 172818976Sdfr break; 172918976Sdfr if (vflag) { 173018976Sdfr printf(" from:"); 173175118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 173218976Sdfr break; 173318976Sdfr printf(" to:"); 173475118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 173518976Sdfr break; 173618976Sdfr } 173717680Spst return; 173818976Sdfr } else { 173975118Sfenner if (parsestatus(dp, &er) != 0) 174018976Sdfr return; 174118976Sdfr } 174217680Spst break; 174317680Spst 174417680Spst case NFSPROC_LINK: 174517680Spst printf(" link"); 174675118Sfenner if (!(dp = parserep(rp, length))) 174718976Sdfr break; 174818976Sdfr if (v3) { 174975118Sfenner if (!(dp = parsestatus(dp, &er))) 175018976Sdfr break; 175118976Sdfr if (vflag) { 175218976Sdfr printf(" file POST:"); 175375118Sfenner if (!(dp = parse_post_op_attr(dp, vflag))) 175418976Sdfr break; 175518976Sdfr printf(" dir:"); 175675118Sfenner if (!(dp = parse_wcc_data(dp, vflag))) 175718976Sdfr break; 175818976Sdfr return; 175918976Sdfr } 176018976Sdfr } else { 176175118Sfenner if (parsestatus(dp, &er) != 0) 176218976Sdfr return; 176318976Sdfr } 176417680Spst break; 176517680Spst 176618976Sdfr case NFSPROC_READDIR: 176718976Sdfr printf(" readdir"); 176875118Sfenner if (!(dp = parserep(rp, length))) 176918976Sdfr break; 177018976Sdfr if (v3) { 177175118Sfenner if (parsev3rddirres(dp, vflag)) 177218976Sdfr return; 177318976Sdfr } else { 177418976Sdfr if (parserddires(dp) != 0) 177518976Sdfr return; 177618976Sdfr } 177718976Sdfr break; 177818976Sdfr 177918976Sdfr case NFSPROC_READDIRPLUS: 178018976Sdfr printf(" readdirplus"); 178175118Sfenner if (!(dp = parserep(rp, length))) 178218976Sdfr break; 178375118Sfenner if (parsev3rddirres(dp, vflag)) 178417680Spst return; 178517680Spst break; 178617680Spst 178718976Sdfr case NFSPROC_FSSTAT: 178818976Sdfr printf(" fsstat"); 178917680Spst dp = parserep(rp, length); 179075118Sfenner if (dp != NULL && parsestatfs(dp, v3) != 0) 179117680Spst return; 179217680Spst break; 179317680Spst 179418976Sdfr case NFSPROC_FSINFO: 179518976Sdfr printf(" fsinfo"); 179617680Spst dp = parserep(rp, length); 179775118Sfenner if (dp != NULL && parsefsinfo(dp) != 0) 179817680Spst return; 179917680Spst break; 180017680Spst 180118976Sdfr case NFSPROC_PATHCONF: 180218976Sdfr printf(" pathconf"); 180317680Spst dp = parserep(rp, length); 180426183Sfenner if (dp != NULL && parsepathconf(dp) != 0) 180517680Spst return; 180617680Spst break; 180717680Spst 180818976Sdfr case NFSPROC_COMMIT: 180918976Sdfr printf(" commit"); 181017680Spst dp = parserep(rp, length); 181126183Sfenner if (dp != NULL && parsewccres(dp, vflag) != 0) 181217680Spst return; 181317680Spst break; 181417680Spst 181517680Spst default: 181626183Sfenner printf(" proc-%u", proc); 181717680Spst return; 181817680Spst } 181918976Sdfrtrunc: 182026183Sfenner if (!nfserr) 182126183Sfenner fputs(" [|nfs]", stdout); 182217680Spst} 1823