14edb46e9SPaul Traina /* 24edb46e9SPaul Traina * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 204edb46e9SPaul Traina */ 214edb46e9SPaul Traina 224edb46e9SPaul Traina #ifndef lint 234edb46e9SPaul Traina static char rcsid[] = 244edb46e9SPaul Traina "@(#) $Header: print-nfs.c,v 1.56 96/07/23 14:17:25 leres Exp $ (LBL)"; 254edb46e9SPaul Traina #endif 264edb46e9SPaul Traina 274edb46e9SPaul Traina #include <sys/param.h> 284edb46e9SPaul Traina #include <sys/time.h> 294edb46e9SPaul Traina #include <sys/socket.h> 304edb46e9SPaul Traina 314edb46e9SPaul Traina #if __STDC__ 324edb46e9SPaul Traina struct mbuf; 334edb46e9SPaul Traina struct rtentry; 344edb46e9SPaul Traina #endif 354edb46e9SPaul Traina #include <net/if.h> 364edb46e9SPaul Traina 374edb46e9SPaul Traina #include <netinet/in.h> 384edb46e9SPaul Traina #include <netinet/if_ether.h> 394edb46e9SPaul Traina #include <netinet/in_systm.h> 404edb46e9SPaul Traina #include <netinet/ip.h> 414edb46e9SPaul Traina #include <netinet/ip_var.h> 424edb46e9SPaul Traina 434edb46e9SPaul Traina #include <rpc/rpc.h> 444edb46e9SPaul Traina 454edb46e9SPaul Traina #include <ctype.h> 464edb46e9SPaul Traina #include <pcap.h> 474edb46e9SPaul Traina #include <stdio.h> 484edb46e9SPaul Traina #include <string.h> 494edb46e9SPaul Traina 504edb46e9SPaul Traina #include "interface.h" 514edb46e9SPaul Traina #include "addrtoname.h" 524edb46e9SPaul Traina 534edb46e9SPaul Traina #include "nfsv2.h" 544edb46e9SPaul Traina #include "nfsfh.h" 554edb46e9SPaul Traina 564edb46e9SPaul Traina static void nfs_printfh(const u_int32_t *); 574edb46e9SPaul Traina static void xid_map_enter(const struct rpc_msg *, const struct ip *); 584edb46e9SPaul Traina static int32_t xid_map_find(const struct rpc_msg *, const struct ip *); 594edb46e9SPaul Traina static void interp_reply(const struct rpc_msg *, u_int32_t, u_int); 604edb46e9SPaul Traina 614edb46e9SPaul Traina void 624edb46e9SPaul Traina nfsreply_print(register const u_char *bp, u_int length, 634edb46e9SPaul Traina register const u_char *bp2) 644edb46e9SPaul Traina { 654edb46e9SPaul Traina register const struct rpc_msg *rp; 664edb46e9SPaul Traina register const struct ip *ip; 674edb46e9SPaul Traina int32_t proc; 684edb46e9SPaul Traina 694edb46e9SPaul Traina rp = (const struct rpc_msg *)bp; 704edb46e9SPaul Traina ip = (const struct ip *)bp2; 714edb46e9SPaul Traina 724edb46e9SPaul Traina if (!nflag) 734edb46e9SPaul Traina (void)printf("%s.nfs > %s.%x: reply %s %d", 744edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 754edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 764edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 774edb46e9SPaul Traina ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 784edb46e9SPaul Traina "ok":"ERR", 794edb46e9SPaul Traina length); 804edb46e9SPaul Traina else 814edb46e9SPaul Traina (void)printf("%s.%x > %s.%x: reply %s %d", 824edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 834edb46e9SPaul Traina NFS_PORT, 844edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 854edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 864edb46e9SPaul Traina ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 874edb46e9SPaul Traina "ok":"ERR", 884edb46e9SPaul Traina length); 894edb46e9SPaul Traina 904edb46e9SPaul Traina proc = xid_map_find(rp, ip); 914edb46e9SPaul Traina if (proc >= 0) 924edb46e9SPaul Traina interp_reply(rp, (u_int32_t)proc, length); 934edb46e9SPaul Traina } 944edb46e9SPaul Traina 954edb46e9SPaul Traina /* 964edb46e9SPaul Traina * Return a pointer to the first file handle in the packet. 974edb46e9SPaul Traina * If the packet was truncated, return 0. 984edb46e9SPaul Traina */ 994edb46e9SPaul Traina static const u_int32_t * 1004edb46e9SPaul Traina parsereq(register const struct rpc_msg *rp, register u_int length) 1014edb46e9SPaul Traina { 1024edb46e9SPaul Traina register const u_int32_t *dp; 1034edb46e9SPaul Traina register u_int len; 1044edb46e9SPaul Traina 1054edb46e9SPaul Traina /* 1064edb46e9SPaul Traina * find the start of the req data (if we captured it) 1074edb46e9SPaul Traina */ 1084edb46e9SPaul Traina dp = (u_int32_t *)&rp->rm_call.cb_cred; 1094edb46e9SPaul Traina TCHECK(dp[1]); 1104edb46e9SPaul Traina len = ntohl(dp[1]); 1114edb46e9SPaul Traina if (len < length) { 1124edb46e9SPaul Traina dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 1134edb46e9SPaul Traina TCHECK(dp[1]); 1144edb46e9SPaul Traina len = ntohl(dp[1]); 1154edb46e9SPaul Traina if (len < length) { 1164edb46e9SPaul Traina dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 1174edb46e9SPaul Traina TCHECK2(dp[0], 0); 1184edb46e9SPaul Traina return (dp); 1194edb46e9SPaul Traina } 1204edb46e9SPaul Traina } 1214edb46e9SPaul Traina trunc: 1224edb46e9SPaul Traina return (0); 1234edb46e9SPaul Traina } 1244edb46e9SPaul Traina 1254edb46e9SPaul Traina /* 1264edb46e9SPaul Traina * Print out an NFS file handle and return a pointer to following word. 1274edb46e9SPaul Traina * If packet was truncated, return 0. 1284edb46e9SPaul Traina */ 1294edb46e9SPaul Traina static const u_int32_t * 1304edb46e9SPaul Traina parsefh(register const u_int32_t *dp) 1314edb46e9SPaul Traina { 1324edb46e9SPaul Traina if (dp + 8 <= (u_int32_t *)snapend) { 1334edb46e9SPaul Traina nfs_printfh(dp); 1344edb46e9SPaul Traina return (dp + 8); 1354edb46e9SPaul Traina } 1364edb46e9SPaul Traina return (0); 1374edb46e9SPaul Traina } 1384edb46e9SPaul Traina 1394edb46e9SPaul Traina /* 1404edb46e9SPaul Traina * Print out a file name and return pointer to 32-bit word past it. 1414edb46e9SPaul Traina * If packet was truncated, return 0. 1424edb46e9SPaul Traina */ 1434edb46e9SPaul Traina static const u_int32_t * 1444edb46e9SPaul Traina parsefn(register const u_int32_t *dp) 1454edb46e9SPaul Traina { 1464edb46e9SPaul Traina register u_int32_t len; 1474edb46e9SPaul Traina register const u_char *cp; 1484edb46e9SPaul Traina 1494edb46e9SPaul Traina /* Bail if we don't have the string length */ 1504edb46e9SPaul Traina if ((u_char *)dp > snapend - sizeof(*dp)) 1514edb46e9SPaul Traina return(0); 1524edb46e9SPaul Traina 1534edb46e9SPaul Traina /* Fetch string length; convert to host order */ 1544edb46e9SPaul Traina len = *dp++; 1554edb46e9SPaul Traina NTOHL(len); 1564edb46e9SPaul Traina 1574edb46e9SPaul Traina cp = (u_char *)dp; 1584edb46e9SPaul Traina /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 1594edb46e9SPaul Traina dp += ((len + 3) & ~3) / sizeof(*dp); 1604edb46e9SPaul Traina if ((u_char *)dp > snapend) 1614edb46e9SPaul Traina return (0); 1624edb46e9SPaul Traina /* XXX seems like we should be checking the length */ 1634edb46e9SPaul Traina putchar('"'); 1644edb46e9SPaul Traina (void) fn_printn(cp, len, NULL); 1654edb46e9SPaul Traina putchar('"'); 1664edb46e9SPaul Traina 1674edb46e9SPaul Traina return (dp); 1684edb46e9SPaul Traina } 1694edb46e9SPaul Traina 1704edb46e9SPaul Traina /* 1714edb46e9SPaul Traina * Print out file handle and file name. 1724edb46e9SPaul Traina * Return pointer to 32-bit word past file name. 1734edb46e9SPaul Traina * If packet was truncated (or there was some other error), return 0. 1744edb46e9SPaul Traina */ 1754edb46e9SPaul Traina static const u_int32_t * 1764edb46e9SPaul Traina parsefhn(register const u_int32_t *dp) 1774edb46e9SPaul Traina { 1784edb46e9SPaul Traina dp = parsefh(dp); 1794edb46e9SPaul Traina if (dp == 0) 1804edb46e9SPaul Traina return (0); 1814edb46e9SPaul Traina putchar(' '); 1824edb46e9SPaul Traina return (parsefn(dp)); 1834edb46e9SPaul Traina } 1844edb46e9SPaul Traina 1854edb46e9SPaul Traina void 1864edb46e9SPaul Traina nfsreq_print(register const u_char *bp, u_int length, 1874edb46e9SPaul Traina register const u_char *bp2) 1884edb46e9SPaul Traina { 1894edb46e9SPaul Traina register const struct rpc_msg *rp; 1904edb46e9SPaul Traina register const struct ip *ip; 1914edb46e9SPaul Traina register const u_int32_t *dp; 1924edb46e9SPaul Traina 1934edb46e9SPaul Traina rp = (const struct rpc_msg *)bp; 1944edb46e9SPaul Traina ip = (const struct ip *)bp2; 1954edb46e9SPaul Traina if (!nflag) 1964edb46e9SPaul Traina (void)printf("%s.%x > %s.nfs: %d", 1974edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 1984edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 1994edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 2004edb46e9SPaul Traina length); 2014edb46e9SPaul Traina else 2024edb46e9SPaul Traina (void)printf("%s.%x > %s.%x: %d", 2034edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 2044edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 2054edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 2064edb46e9SPaul Traina NFS_PORT, 2074edb46e9SPaul Traina length); 2084edb46e9SPaul Traina 2094edb46e9SPaul Traina xid_map_enter(rp, ip); /* record proc number for later on */ 2104edb46e9SPaul Traina 2114edb46e9SPaul Traina switch (ntohl(rp->rm_call.cb_proc)) { 2124edb46e9SPaul Traina #ifdef NFSPROC_NOOP 2134edb46e9SPaul Traina case NFSPROC_NOOP: 2144edb46e9SPaul Traina printf(" nop"); 2154edb46e9SPaul Traina return; 2164edb46e9SPaul Traina #else 2174edb46e9SPaul Traina #define NFSPROC_NOOP -1 2184edb46e9SPaul Traina #endif 2194edb46e9SPaul Traina case NFSPROC_NULL: 2204edb46e9SPaul Traina printf(" null"); 2214edb46e9SPaul Traina return; 2224edb46e9SPaul Traina 2234edb46e9SPaul Traina case NFSPROC_GETATTR: 2244edb46e9SPaul Traina printf(" getattr"); 2254edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) 2264edb46e9SPaul Traina return; 2274edb46e9SPaul Traina break; 2284edb46e9SPaul Traina 2294edb46e9SPaul Traina case NFSPROC_SETATTR: 2304edb46e9SPaul Traina printf(" setattr"); 2314edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) 2324edb46e9SPaul Traina return; 2334edb46e9SPaul Traina break; 2344edb46e9SPaul Traina 2354edb46e9SPaul Traina #if NFSPROC_ROOT != NFSPROC_NOOP 2364edb46e9SPaul Traina case NFSPROC_ROOT: 2374edb46e9SPaul Traina printf(" root"); 2384edb46e9SPaul Traina break; 2394edb46e9SPaul Traina #endif 2404edb46e9SPaul Traina case NFSPROC_LOOKUP: 2414edb46e9SPaul Traina printf(" lookup"); 2424edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) 2434edb46e9SPaul Traina return; 2444edb46e9SPaul Traina break; 2454edb46e9SPaul Traina 2464edb46e9SPaul Traina case NFSPROC_READLINK: 2474edb46e9SPaul Traina printf(" readlink"); 2484edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) 2494edb46e9SPaul Traina return; 2504edb46e9SPaul Traina break; 2514edb46e9SPaul Traina 2524edb46e9SPaul Traina case NFSPROC_READ: 2534edb46e9SPaul Traina printf(" read"); 2544edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 2554edb46e9SPaul Traina (dp = parsefh(dp)) != 0) { 2564edb46e9SPaul Traina TCHECK2(dp[0], 3 * sizeof(*dp)); 2574edb46e9SPaul Traina printf(" %u bytes @ %u", 2584edb46e9SPaul Traina (u_int32_t)ntohl(dp[1]), 2594edb46e9SPaul Traina (u_int32_t)ntohl(dp[0])); 2604edb46e9SPaul Traina return; 2614edb46e9SPaul Traina } 2624edb46e9SPaul Traina break; 2634edb46e9SPaul Traina 2644edb46e9SPaul Traina #if NFSPROC_WRITECACHE != NFSPROC_NOOP 2654edb46e9SPaul Traina case NFSPROC_WRITECACHE: 2664edb46e9SPaul Traina printf(" writecache"); 2674edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 2684edb46e9SPaul Traina (dp = parsefh(dp)) != 0) { 2694edb46e9SPaul Traina TCHECK2(dp[0], 4 * sizeof(*dp)); 2704edb46e9SPaul Traina printf(" %u (%u) bytes @ %u (%u)", 2714edb46e9SPaul Traina (u_int32_t)ntohl(dp[3]), 2724edb46e9SPaul Traina (u_int32_t)ntohl(dp[2]), 2734edb46e9SPaul Traina (u_int32_t)ntohl(dp[1]), 2744edb46e9SPaul Traina (u_int32_t)ntohl(dp[0])); 2754edb46e9SPaul Traina return; 2764edb46e9SPaul Traina } 2774edb46e9SPaul Traina break; 2784edb46e9SPaul Traina #endif 2794edb46e9SPaul Traina case NFSPROC_WRITE: 2804edb46e9SPaul Traina printf(" write"); 2814edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 2824edb46e9SPaul Traina (dp = parsefh(dp)) != 0) { 2834edb46e9SPaul Traina TCHECK2(dp[0], 4 * sizeof(*dp)); 2844edb46e9SPaul Traina printf(" %u (%u) bytes @ %u (%u)", 2854edb46e9SPaul Traina (u_int32_t)ntohl(dp[3]), 2864edb46e9SPaul Traina (u_int32_t)ntohl(dp[2]), 2874edb46e9SPaul Traina (u_int32_t)ntohl(dp[1]), 2884edb46e9SPaul Traina (u_int32_t)ntohl(dp[0])); 2894edb46e9SPaul Traina return; 2904edb46e9SPaul Traina } 2914edb46e9SPaul Traina break; 2924edb46e9SPaul Traina 2934edb46e9SPaul Traina case NFSPROC_CREATE: 2944edb46e9SPaul Traina printf(" create"); 2954edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) 2964edb46e9SPaul Traina return; 2974edb46e9SPaul Traina break; 2984edb46e9SPaul Traina 2994edb46e9SPaul Traina case NFSPROC_REMOVE: 3004edb46e9SPaul Traina printf(" remove"); 3014edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) 3024edb46e9SPaul Traina return; 3034edb46e9SPaul Traina break; 3044edb46e9SPaul Traina 3054edb46e9SPaul Traina case NFSPROC_RENAME: 3064edb46e9SPaul Traina printf(" rename"); 3074edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 3084edb46e9SPaul Traina (dp = parsefhn(dp)) != 0) { 3094edb46e9SPaul Traina fputs(" ->", stdout); 3104edb46e9SPaul Traina if (parsefhn(dp) != 0) 3114edb46e9SPaul Traina return; 3124edb46e9SPaul Traina } 3134edb46e9SPaul Traina break; 3144edb46e9SPaul Traina 3154edb46e9SPaul Traina case NFSPROC_LINK: 3164edb46e9SPaul Traina printf(" link"); 3174edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 3184edb46e9SPaul Traina (dp = parsefh(dp)) != 0) { 3194edb46e9SPaul Traina fputs(" ->", stdout); 3204edb46e9SPaul Traina if (parsefhn(dp) != 0) 3214edb46e9SPaul Traina return; 3224edb46e9SPaul Traina } 3234edb46e9SPaul Traina break; 3244edb46e9SPaul Traina 3254edb46e9SPaul Traina case NFSPROC_SYMLINK: 3264edb46e9SPaul Traina printf(" symlink"); 3274edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 3284edb46e9SPaul Traina (dp = parsefhn(dp)) != 0) { 3294edb46e9SPaul Traina fputs(" -> ", stdout); 3304edb46e9SPaul Traina if (parsefn(dp) != 0) 3314edb46e9SPaul Traina return; 3324edb46e9SPaul Traina } 3334edb46e9SPaul Traina break; 3344edb46e9SPaul Traina 3354edb46e9SPaul Traina case NFSPROC_MKDIR: 3364edb46e9SPaul Traina printf(" mkdir"); 3374edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) 3384edb46e9SPaul Traina return; 3394edb46e9SPaul Traina break; 3404edb46e9SPaul Traina 3414edb46e9SPaul Traina case NFSPROC_RMDIR: 3424edb46e9SPaul Traina printf(" rmdir"); 3434edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) 3444edb46e9SPaul Traina return; 3454edb46e9SPaul Traina break; 3464edb46e9SPaul Traina 3474edb46e9SPaul Traina case NFSPROC_READDIR: 3484edb46e9SPaul Traina printf(" readdir"); 3494edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && 3504edb46e9SPaul Traina (dp = parsefh(dp)) != 0) { 3514edb46e9SPaul Traina TCHECK2(dp[0], 2 * sizeof(*dp)); 3524edb46e9SPaul Traina /* 3534edb46e9SPaul Traina * Print the offset as signed, since -1 is common, 3544edb46e9SPaul Traina * but offsets > 2^31 aren't. 3554edb46e9SPaul Traina */ 3564edb46e9SPaul Traina printf(" %u bytes @ %d", 3574edb46e9SPaul Traina (u_int32_t)ntohl(dp[1]), 3584edb46e9SPaul Traina (u_int32_t)ntohl(dp[0])); 3594edb46e9SPaul Traina return; 3604edb46e9SPaul Traina } 3614edb46e9SPaul Traina break; 3624edb46e9SPaul Traina 3634edb46e9SPaul Traina case NFSPROC_STATFS: 3644edb46e9SPaul Traina printf(" statfs"); 3654edb46e9SPaul Traina if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) 3664edb46e9SPaul Traina return; 3674edb46e9SPaul Traina break; 3684edb46e9SPaul Traina 3694edb46e9SPaul Traina default: 3704edb46e9SPaul Traina printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc)); 3714edb46e9SPaul Traina return; 3724edb46e9SPaul Traina } 3734edb46e9SPaul Traina trunc: 3744edb46e9SPaul Traina fputs(" [|nfs]", stdout); 3754edb46e9SPaul Traina } 3764edb46e9SPaul Traina 3774edb46e9SPaul Traina /* 3784edb46e9SPaul Traina * Print out an NFS file handle. 3794edb46e9SPaul Traina * We assume packet was not truncated before the end of the 3804edb46e9SPaul Traina * file handle pointed to by dp. 3814edb46e9SPaul Traina * 3824edb46e9SPaul Traina * Note: new version (using portable file-handle parser) doesn't produce 3834edb46e9SPaul Traina * generation number. It probably could be made to do that, with some 3844edb46e9SPaul Traina * additional hacking on the parser code. 3854edb46e9SPaul Traina */ 3864edb46e9SPaul Traina static void 3874edb46e9SPaul Traina nfs_printfh(register const u_int32_t *dp) 3884edb46e9SPaul Traina { 3894edb46e9SPaul Traina my_fsid fsid; 3904edb46e9SPaul Traina ino_t ino; 3914edb46e9SPaul Traina char *sfsname = NULL; 3924edb46e9SPaul Traina 3934edb46e9SPaul Traina Parse_fh((caddr_t*)dp, &fsid, &ino, NULL, &sfsname, 0); 3944edb46e9SPaul Traina 3954edb46e9SPaul Traina if (sfsname) { 3964edb46e9SPaul Traina /* file system ID is ASCII, not numeric, for this server OS */ 3974edb46e9SPaul Traina static char temp[NFS_FHSIZE+1]; 3984edb46e9SPaul Traina 3994edb46e9SPaul Traina /* Make sure string is null-terminated */ 4004edb46e9SPaul Traina strncpy(temp, sfsname, NFS_FHSIZE); 4014edb46e9SPaul Traina /* Remove trailing spaces */ 4024edb46e9SPaul Traina sfsname = strchr(temp, ' '); 4034edb46e9SPaul Traina if (sfsname) 4044edb46e9SPaul Traina *sfsname = 0; 4054edb46e9SPaul Traina 4064edb46e9SPaul Traina (void)printf(" fh %s/%u", temp, (u_int32_t)ino); 4074edb46e9SPaul Traina } 4084edb46e9SPaul Traina else { 4094edb46e9SPaul Traina (void)printf(" fh %u,%u/%u", 4104edb46e9SPaul Traina fsid.fsid_dev.Major, 4114edb46e9SPaul Traina fsid.fsid_dev.Minor, 4124edb46e9SPaul Traina (u_int32_t)ino); 4134edb46e9SPaul Traina } 4144edb46e9SPaul Traina } 4154edb46e9SPaul Traina 4164edb46e9SPaul Traina /* 4174edb46e9SPaul Traina * Maintain a small cache of recent client.XID.server/proc pairs, to allow 4184edb46e9SPaul Traina * us to match up replies with requests and thus to know how to parse 4194edb46e9SPaul Traina * the reply. 4204edb46e9SPaul Traina */ 4214edb46e9SPaul Traina 4224edb46e9SPaul Traina struct xid_map_entry { 4234edb46e9SPaul Traina u_int32_t xid; /* transaction ID (net order) */ 4244edb46e9SPaul Traina struct in_addr client; /* client IP address (net order) */ 4254edb46e9SPaul Traina struct in_addr server; /* server IP address (net order) */ 4264edb46e9SPaul Traina u_int32_t proc; /* call proc number (host order) */ 4274edb46e9SPaul Traina }; 4284edb46e9SPaul Traina 4294edb46e9SPaul Traina /* 4304edb46e9SPaul Traina * Map entries are kept in an array that we manage as a ring; 4314edb46e9SPaul Traina * new entries are always added at the tail of the ring. Initially, 4324edb46e9SPaul Traina * all the entries are zero and hence don't match anything. 4334edb46e9SPaul Traina */ 4344edb46e9SPaul Traina 4354edb46e9SPaul Traina #define XIDMAPSIZE 64 4364edb46e9SPaul Traina 4374edb46e9SPaul Traina struct xid_map_entry xid_map[XIDMAPSIZE]; 4384edb46e9SPaul Traina 4394edb46e9SPaul Traina int xid_map_next = 0; 4404edb46e9SPaul Traina int xid_map_hint = 0; 4414edb46e9SPaul Traina 4424edb46e9SPaul Traina static void 4434edb46e9SPaul Traina xid_map_enter(const struct rpc_msg *rp, const struct ip *ip) 4444edb46e9SPaul Traina { 4454edb46e9SPaul Traina struct xid_map_entry *xmep; 4464edb46e9SPaul Traina 4474edb46e9SPaul Traina xmep = &xid_map[xid_map_next]; 4484edb46e9SPaul Traina 4494edb46e9SPaul Traina if (++xid_map_next >= XIDMAPSIZE) 4504edb46e9SPaul Traina xid_map_next = 0; 4514edb46e9SPaul Traina 4524edb46e9SPaul Traina xmep->xid = rp->rm_xid; 4534edb46e9SPaul Traina xmep->client = ip->ip_src; 4544edb46e9SPaul Traina xmep->server = ip->ip_dst; 4554edb46e9SPaul Traina xmep->proc = ntohl(rp->rm_call.cb_proc); 4564edb46e9SPaul Traina } 4574edb46e9SPaul Traina 4584edb46e9SPaul Traina /* Returns NFSPROC_xxx or -1 on failure */ 4594edb46e9SPaul Traina static int32_t 4604edb46e9SPaul Traina xid_map_find(const struct rpc_msg *rp, const struct ip *ip) 4614edb46e9SPaul Traina { 4624edb46e9SPaul Traina int i; 4634edb46e9SPaul Traina struct xid_map_entry *xmep; 4644edb46e9SPaul Traina u_int32_t xid = rp->rm_xid; 4654edb46e9SPaul Traina u_int32_t clip = ip->ip_dst.s_addr; 4664edb46e9SPaul Traina u_int32_t sip = ip->ip_src.s_addr; 4674edb46e9SPaul Traina 4684edb46e9SPaul Traina /* Start searching from where we last left off */ 4694edb46e9SPaul Traina i = xid_map_hint; 4704edb46e9SPaul Traina do { 4714edb46e9SPaul Traina xmep = &xid_map[i]; 4724edb46e9SPaul Traina if (xmep->xid == xid && xmep->client.s_addr == clip && 4734edb46e9SPaul Traina xmep->server.s_addr == sip) { 4744edb46e9SPaul Traina /* match */ 4754edb46e9SPaul Traina xid_map_hint = i; 4764edb46e9SPaul Traina return ((int32_t)xmep->proc); 4774edb46e9SPaul Traina } 4784edb46e9SPaul Traina if (++i >= XIDMAPSIZE) 4794edb46e9SPaul Traina i = 0; 4804edb46e9SPaul Traina } while (i != xid_map_hint); 4814edb46e9SPaul Traina 4824edb46e9SPaul Traina /* search failed */ 4834edb46e9SPaul Traina return(-1); 4844edb46e9SPaul Traina } 4854edb46e9SPaul Traina 4864edb46e9SPaul Traina /* 4874edb46e9SPaul Traina * Routines for parsing reply packets 4884edb46e9SPaul Traina */ 4894edb46e9SPaul Traina 4904edb46e9SPaul Traina /* 4914edb46e9SPaul Traina * Return a pointer to the beginning of the actual results. 4924edb46e9SPaul Traina * If the packet was truncated, return 0. 4934edb46e9SPaul Traina */ 4944edb46e9SPaul Traina static const u_int32_t * 4954edb46e9SPaul Traina parserep(register const struct rpc_msg *rp, register u_int length) 4964edb46e9SPaul Traina { 4974edb46e9SPaul Traina register const u_int32_t *dp; 4984edb46e9SPaul Traina u_int len; 4994edb46e9SPaul Traina enum accept_stat astat; 5004edb46e9SPaul Traina 5014edb46e9SPaul Traina /* 5024edb46e9SPaul Traina * Portability note: 5034edb46e9SPaul Traina * Here we find the address of the ar_verf credentials. 5044edb46e9SPaul Traina * Originally, this calculation was 5054edb46e9SPaul Traina * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 5064edb46e9SPaul Traina * On the wire, the rp_acpt field starts immediately after 5074edb46e9SPaul Traina * the (32 bit) rp_stat field. However, rp_acpt (which is a 5084edb46e9SPaul Traina * "struct accepted_reply") contains a "struct opaque_auth", 5094edb46e9SPaul Traina * whose internal representation contains a pointer, so on a 5104edb46e9SPaul Traina * 64-bit machine the compiler inserts 32 bits of padding 5114edb46e9SPaul Traina * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 5124edb46e9SPaul Traina * the internal representation to parse the on-the-wire 5134edb46e9SPaul Traina * representation. Instead, we skip past the rp_stat field, 5144edb46e9SPaul Traina * which is an "enum" and so occupies one 32-bit word. 5154edb46e9SPaul Traina */ 5164edb46e9SPaul Traina dp = ((const u_int32_t *)&rp->rm_reply) + 1; 5174edb46e9SPaul Traina TCHECK2(dp[0], 1); 5184edb46e9SPaul Traina return(0); 5194edb46e9SPaul Traina len = ntohl(dp[1]); 5204edb46e9SPaul Traina if (len >= length) 5214edb46e9SPaul Traina return(0); 5224edb46e9SPaul Traina /* 5234edb46e9SPaul Traina * skip past the ar_verf credentials. 5244edb46e9SPaul Traina */ 5254edb46e9SPaul Traina dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 5264edb46e9SPaul Traina TCHECK2(dp[0], 0); 5274edb46e9SPaul Traina 5284edb46e9SPaul Traina /* 5294edb46e9SPaul Traina * now we can check the ar_stat field 5304edb46e9SPaul Traina */ 5314edb46e9SPaul Traina astat = ntohl(*(enum accept_stat *)dp); 5324edb46e9SPaul Traina switch (astat) { 5334edb46e9SPaul Traina 5344edb46e9SPaul Traina case SUCCESS: 5354edb46e9SPaul Traina break; 5364edb46e9SPaul Traina 5374edb46e9SPaul Traina case PROG_UNAVAIL: 5384edb46e9SPaul Traina printf(" PROG_UNAVAIL"); 5394edb46e9SPaul Traina return(0); 5404edb46e9SPaul Traina 5414edb46e9SPaul Traina case PROG_MISMATCH: 5424edb46e9SPaul Traina printf(" PROG_MISMATCH"); 5434edb46e9SPaul Traina return(0); 5444edb46e9SPaul Traina 5454edb46e9SPaul Traina case PROC_UNAVAIL: 5464edb46e9SPaul Traina printf(" PROC_UNAVAIL"); 5474edb46e9SPaul Traina return(0); 5484edb46e9SPaul Traina 5494edb46e9SPaul Traina case GARBAGE_ARGS: 5504edb46e9SPaul Traina printf(" GARBAGE_ARGS"); 5514edb46e9SPaul Traina return(0); 5524edb46e9SPaul Traina 5534edb46e9SPaul Traina case SYSTEM_ERR: 5544edb46e9SPaul Traina printf(" SYSTEM_ERR"); 5554edb46e9SPaul Traina return(0); 5564edb46e9SPaul Traina 5574edb46e9SPaul Traina default: 5584edb46e9SPaul Traina printf(" ar_stat %d", astat); 5594edb46e9SPaul Traina return(0); 5604edb46e9SPaul Traina } 5614edb46e9SPaul Traina /* successful return */ 5624edb46e9SPaul Traina if ((sizeof(astat) + ((u_char *)dp)) < snapend) 5634edb46e9SPaul Traina return((u_int32_t *) (sizeof(astat) + ((char *)dp))); 5644edb46e9SPaul Traina 5654edb46e9SPaul Traina trunc: 5664edb46e9SPaul Traina return (0); 5674edb46e9SPaul Traina } 5684edb46e9SPaul Traina 5694edb46e9SPaul Traina static const u_int32_t * 5704edb46e9SPaul Traina parsestatus(const u_int32_t *dp) 5714edb46e9SPaul Traina { 5724edb46e9SPaul Traina int errnum; 5734edb46e9SPaul Traina 5744edb46e9SPaul Traina TCHECK(dp[0]); 5754edb46e9SPaul Traina errnum = ntohl(dp[0]); 5764edb46e9SPaul Traina if (errnum != 0) { 5774edb46e9SPaul Traina char *errmsg; 5784edb46e9SPaul Traina 5794edb46e9SPaul Traina if (qflag) 5804edb46e9SPaul Traina return(0); 5814edb46e9SPaul Traina 5824edb46e9SPaul Traina errmsg = pcap_strerror(errnum); 5834edb46e9SPaul Traina printf(" ERROR: %s", errmsg); 5844edb46e9SPaul Traina return(0); 5854edb46e9SPaul Traina } 5864edb46e9SPaul Traina return (dp + 1); 5874edb46e9SPaul Traina trunc: 5884edb46e9SPaul Traina return (0); 5894edb46e9SPaul Traina } 5904edb46e9SPaul Traina 5914edb46e9SPaul Traina static struct tok type2str[] = { 5924edb46e9SPaul Traina { NFNON, "NON" }, 5934edb46e9SPaul Traina { NFREG, "REG" }, 5944edb46e9SPaul Traina { NFDIR, "DIR" }, 5954edb46e9SPaul Traina { NFBLK, "BLK" }, 5964edb46e9SPaul Traina { NFCHR, "CHR" }, 5974edb46e9SPaul Traina { NFLNK, "LNK" }, 5984edb46e9SPaul Traina { 0, NULL } 5994edb46e9SPaul Traina }; 6004edb46e9SPaul Traina 6014edb46e9SPaul Traina static const u_int32_t * 6024edb46e9SPaul Traina parsefattr(const u_int32_t *dp, int verbose) 6034edb46e9SPaul Traina { 6044edb46e9SPaul Traina const struct nfsv2_fattr *fap; 6054edb46e9SPaul Traina 6064edb46e9SPaul Traina fap = (const struct nfsv2_fattr *)dp; 6074edb46e9SPaul Traina if (verbose) { 6084edb46e9SPaul Traina TCHECK(fap->fa_nfssize); 6094edb46e9SPaul Traina printf(" %s %o ids %u/%u sz %u ", 6104edb46e9SPaul Traina tok2str(type2str, "unk-ft %d ", 6114edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_type)), 6124edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_mode), 6134edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_uid), 6144edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_gid), 6154edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfssize)); 6164edb46e9SPaul Traina } 6174edb46e9SPaul Traina /* print lots more stuff */ 6184edb46e9SPaul Traina if (verbose > 1) { 6194edb46e9SPaul Traina TCHECK(fap->fa_nfsfileid); 6204edb46e9SPaul Traina printf("nlink %u rdev %x fsid %x nodeid %x a/m/ctime ", 6214edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nlink), 6224edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsrdev), 6234edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsfsid), 6244edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsfileid)); 6254edb46e9SPaul Traina TCHECK(fap->fa_nfsatime); 6264edb46e9SPaul Traina printf("%u.%06u ", 6274edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsatime.nfs_sec), 6284edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsatime.nfs_usec)); 6294edb46e9SPaul Traina TCHECK(fap->fa_nfsmtime); 6304edb46e9SPaul Traina printf("%u.%06u ", 6314edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_sec), 6324edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_usec)); 6334edb46e9SPaul Traina TCHECK(fap->fa_nfsctime); 6344edb46e9SPaul Traina printf("%u.%06u ", 6354edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsctime.nfs_sec), 6364edb46e9SPaul Traina (u_int32_t)ntohl(fap->fa_nfsctime.nfs_usec)); 6374edb46e9SPaul Traina } 6384edb46e9SPaul Traina return ((const u_int32_t *)&fap[1]); 6394edb46e9SPaul Traina trunc: 6404edb46e9SPaul Traina return (NULL); 6414edb46e9SPaul Traina } 6424edb46e9SPaul Traina 6434edb46e9SPaul Traina static int 6444edb46e9SPaul Traina parseattrstat(const u_int32_t *dp, int verbose) 6454edb46e9SPaul Traina { 6464edb46e9SPaul Traina dp = parsestatus(dp); 6474edb46e9SPaul Traina if (dp == NULL) 6484edb46e9SPaul Traina return (0); 6494edb46e9SPaul Traina 6504edb46e9SPaul Traina return (parsefattr(dp, verbose) != NULL); 6514edb46e9SPaul Traina } 6524edb46e9SPaul Traina 6534edb46e9SPaul Traina static int 6544edb46e9SPaul Traina parsediropres(const u_int32_t *dp) 6554edb46e9SPaul Traina { 6564edb46e9SPaul Traina dp = parsestatus(dp); 6574edb46e9SPaul Traina if (dp == NULL) 6584edb46e9SPaul Traina return (0); 6594edb46e9SPaul Traina 6604edb46e9SPaul Traina dp = parsefh(dp); 6614edb46e9SPaul Traina if (dp == NULL) 6624edb46e9SPaul Traina return (0); 6634edb46e9SPaul Traina 6644edb46e9SPaul Traina return (parsefattr(dp, vflag) != NULL); 6654edb46e9SPaul Traina } 6664edb46e9SPaul Traina 6674edb46e9SPaul Traina static int 6684edb46e9SPaul Traina parselinkres(const u_int32_t *dp) 6694edb46e9SPaul Traina { 6704edb46e9SPaul Traina dp = parsestatus(dp); 6714edb46e9SPaul Traina if (dp == NULL) 6724edb46e9SPaul Traina return(0); 6734edb46e9SPaul Traina 6744edb46e9SPaul Traina putchar(' '); 6754edb46e9SPaul Traina return (parsefn(dp) != NULL); 6764edb46e9SPaul Traina } 6774edb46e9SPaul Traina 6784edb46e9SPaul Traina static int 6794edb46e9SPaul Traina parsestatfs(const u_int32_t *dp) 6804edb46e9SPaul Traina { 6814edb46e9SPaul Traina const struct nfsv2_statfs *sfsp; 6824edb46e9SPaul Traina 6834edb46e9SPaul Traina dp = parsestatus(dp); 6844edb46e9SPaul Traina if (dp == NULL) 6854edb46e9SPaul Traina return(0); 6864edb46e9SPaul Traina 6874edb46e9SPaul Traina if (!qflag) { 6884edb46e9SPaul Traina sfsp = (const struct nfsv2_statfs *)dp; 6894edb46e9SPaul Traina TCHECK(sfsp->sf_bavail); 6904edb46e9SPaul Traina printf(" tsize %u bsize %u blocks %u bfree %u bavail %u", 6914edb46e9SPaul Traina (u_int32_t)ntohl(sfsp->sf_tsize), 6924edb46e9SPaul Traina (u_int32_t)ntohl(sfsp->sf_bsize), 6934edb46e9SPaul Traina (u_int32_t)ntohl(sfsp->sf_blocks), 6944edb46e9SPaul Traina (u_int32_t)ntohl(sfsp->sf_bfree), 6954edb46e9SPaul Traina (u_int32_t)ntohl(sfsp->sf_bavail)); 6964edb46e9SPaul Traina } 6974edb46e9SPaul Traina 6984edb46e9SPaul Traina return (1); 6994edb46e9SPaul Traina trunc: 7004edb46e9SPaul Traina return (0); 7014edb46e9SPaul Traina } 7024edb46e9SPaul Traina 7034edb46e9SPaul Traina static int 7044edb46e9SPaul Traina parserddires(const u_int32_t *dp) 7054edb46e9SPaul Traina { 7064edb46e9SPaul Traina dp = parsestatus(dp); 7074edb46e9SPaul Traina if (dp == 0) 7084edb46e9SPaul Traina return (0); 7094edb46e9SPaul Traina if (!qflag) { 7104edb46e9SPaul Traina TCHECK(dp[0]); 7114edb46e9SPaul Traina printf(" offset %x", (u_int32_t)ntohl(dp[0])); 7124edb46e9SPaul Traina TCHECK(dp[1]); 7134edb46e9SPaul Traina printf(" size %u", (u_int32_t)ntohl(dp[1])); 7144edb46e9SPaul Traina TCHECK(dp[2]); 7154edb46e9SPaul Traina if (dp[2] != 0) 7164edb46e9SPaul Traina printf(" eof"); 7174edb46e9SPaul Traina } 7184edb46e9SPaul Traina 7194edb46e9SPaul Traina return (1); 7204edb46e9SPaul Traina trunc: 7214edb46e9SPaul Traina return (0); 7224edb46e9SPaul Traina } 7234edb46e9SPaul Traina 7244edb46e9SPaul Traina static void 7254edb46e9SPaul Traina interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int length) 7264edb46e9SPaul Traina { 7274edb46e9SPaul Traina register const u_int32_t *dp; 7284edb46e9SPaul Traina 7294edb46e9SPaul Traina switch (proc) { 7304edb46e9SPaul Traina 7314edb46e9SPaul Traina #ifdef NFSPROC_NOOP 7324edb46e9SPaul Traina case NFSPROC_NOOP: 7334edb46e9SPaul Traina printf(" nop"); 7344edb46e9SPaul Traina return; 7354edb46e9SPaul Traina #else 7364edb46e9SPaul Traina #define NFSPROC_NOOP -1 7374edb46e9SPaul Traina #endif 7384edb46e9SPaul Traina case NFSPROC_NULL: 7394edb46e9SPaul Traina printf(" null"); 7404edb46e9SPaul Traina return; 7414edb46e9SPaul Traina 7424edb46e9SPaul Traina case NFSPROC_GETATTR: 7434edb46e9SPaul Traina printf(" getattr"); 7444edb46e9SPaul Traina dp = parserep(rp, length); 7454edb46e9SPaul Traina if (dp != 0 && parseattrstat(dp, !qflag) != 0) 7464edb46e9SPaul Traina return; 7474edb46e9SPaul Traina break; 7484edb46e9SPaul Traina 7494edb46e9SPaul Traina case NFSPROC_SETATTR: 7504edb46e9SPaul Traina printf(" setattr"); 7514edb46e9SPaul Traina dp = parserep(rp, length); 7524edb46e9SPaul Traina if (dp != 0 && parseattrstat(dp, !qflag) != 0) 7534edb46e9SPaul Traina return; 7544edb46e9SPaul Traina break; 7554edb46e9SPaul Traina 7564edb46e9SPaul Traina #if NFSPROC_ROOT != NFSPROC_NOOP 7574edb46e9SPaul Traina case NFSPROC_ROOT: 7584edb46e9SPaul Traina printf(" root"); 7594edb46e9SPaul Traina break; 7604edb46e9SPaul Traina #endif 7614edb46e9SPaul Traina case NFSPROC_LOOKUP: 7624edb46e9SPaul Traina printf(" lookup"); 7634edb46e9SPaul Traina dp = parserep(rp, length); 7644edb46e9SPaul Traina if (dp != 0 && parsediropres(dp) != 0) 7654edb46e9SPaul Traina return; 7664edb46e9SPaul Traina break; 7674edb46e9SPaul Traina 7684edb46e9SPaul Traina case NFSPROC_READLINK: 7694edb46e9SPaul Traina printf(" readlink"); 7704edb46e9SPaul Traina dp = parserep(rp, length); 7714edb46e9SPaul Traina if (dp != 0 && parselinkres(dp) != 0) 7724edb46e9SPaul Traina return; 7734edb46e9SPaul Traina break; 7744edb46e9SPaul Traina 7754edb46e9SPaul Traina case NFSPROC_READ: 7764edb46e9SPaul Traina printf(" read"); 7774edb46e9SPaul Traina dp = parserep(rp, length); 7784edb46e9SPaul Traina if (dp != 0 && parseattrstat(dp, vflag) != 0) 7794edb46e9SPaul Traina return; 7804edb46e9SPaul Traina break; 7814edb46e9SPaul Traina 7824edb46e9SPaul Traina #if NFSPROC_WRITECACHE != NFSPROC_NOOP 7834edb46e9SPaul Traina case NFSPROC_WRITECACHE: 7844edb46e9SPaul Traina printf(" writecache"); 7854edb46e9SPaul Traina break; 7864edb46e9SPaul Traina #endif 7874edb46e9SPaul Traina case NFSPROC_WRITE: 7884edb46e9SPaul Traina printf(" write"); 7894edb46e9SPaul Traina dp = parserep(rp, length); 7904edb46e9SPaul Traina if (dp != 0 && parseattrstat(dp, vflag) != 0) 7914edb46e9SPaul Traina return; 7924edb46e9SPaul Traina break; 7934edb46e9SPaul Traina 7944edb46e9SPaul Traina case NFSPROC_CREATE: 7954edb46e9SPaul Traina printf(" create"); 7964edb46e9SPaul Traina dp = parserep(rp, length); 7974edb46e9SPaul Traina if (dp != 0 && parsediropres(dp) != 0) 7984edb46e9SPaul Traina return; 7994edb46e9SPaul Traina break; 8004edb46e9SPaul Traina 8014edb46e9SPaul Traina case NFSPROC_REMOVE: 8024edb46e9SPaul Traina printf(" remove"); 8034edb46e9SPaul Traina dp = parserep(rp, length); 8044edb46e9SPaul Traina if (dp != 0 && parsestatus(dp) != 0) 8054edb46e9SPaul Traina return; 8064edb46e9SPaul Traina break; 8074edb46e9SPaul Traina 8084edb46e9SPaul Traina case NFSPROC_RENAME: 8094edb46e9SPaul Traina printf(" rename"); 8104edb46e9SPaul Traina dp = parserep(rp, length); 8114edb46e9SPaul Traina if (dp != 0 && parsestatus(dp) != 0) 8124edb46e9SPaul Traina return; 8134edb46e9SPaul Traina break; 8144edb46e9SPaul Traina 8154edb46e9SPaul Traina case NFSPROC_LINK: 8164edb46e9SPaul Traina printf(" link"); 8174edb46e9SPaul Traina dp = parserep(rp, length); 8184edb46e9SPaul Traina if (dp != 0 && parsestatus(dp) != 0) 8194edb46e9SPaul Traina return; 8204edb46e9SPaul Traina break; 8214edb46e9SPaul Traina 8224edb46e9SPaul Traina case NFSPROC_SYMLINK: 8234edb46e9SPaul Traina printf(" symlink"); 8244edb46e9SPaul Traina dp = parserep(rp, length); 8254edb46e9SPaul Traina if (dp != 0 && parsestatus(dp) != 0) 8264edb46e9SPaul Traina return; 8274edb46e9SPaul Traina break; 8284edb46e9SPaul Traina 8294edb46e9SPaul Traina case NFSPROC_MKDIR: 8304edb46e9SPaul Traina printf(" mkdir"); 8314edb46e9SPaul Traina dp = parserep(rp, length); 8324edb46e9SPaul Traina if (dp != 0 && parsediropres(dp) != 0) 8334edb46e9SPaul Traina return; 8344edb46e9SPaul Traina break; 8354edb46e9SPaul Traina 8364edb46e9SPaul Traina case NFSPROC_RMDIR: 8374edb46e9SPaul Traina printf(" rmdir"); 8384edb46e9SPaul Traina dp = parserep(rp, length); 8394edb46e9SPaul Traina if (dp != 0 && parsestatus(dp) != 0) 8404edb46e9SPaul Traina return; 8414edb46e9SPaul Traina break; 8424edb46e9SPaul Traina 8434edb46e9SPaul Traina case NFSPROC_READDIR: 8444edb46e9SPaul Traina printf(" readdir"); 8454edb46e9SPaul Traina dp = parserep(rp, length); 8464edb46e9SPaul Traina if (dp != 0 && parserddires(dp) != 0) 8474edb46e9SPaul Traina return; 8484edb46e9SPaul Traina break; 8494edb46e9SPaul Traina 8504edb46e9SPaul Traina case NFSPROC_STATFS: 8514edb46e9SPaul Traina printf(" statfs"); 8524edb46e9SPaul Traina dp = parserep(rp, length); 8534edb46e9SPaul Traina if (dp != 0 && parsestatfs(dp) != 0) 8544edb46e9SPaul Traina return; 8554edb46e9SPaul Traina break; 8564edb46e9SPaul Traina 8574edb46e9SPaul Traina default: 8584edb46e9SPaul Traina printf(" proc-%u", proc); 8594edb46e9SPaul Traina return; 8604edb46e9SPaul Traina } 8614edb46e9SPaul Traina fputs(" [|nfs]", stdout); 8624edb46e9SPaul Traina } 863