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 232ebf6c05SBill Fenner static const char rcsid[] = 242ebf6c05SBill Fenner "@(#) $Header: print-nfs.c,v 1.63 96/12/10 23:18:07 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 #include <net/if.h> 324edb46e9SPaul Traina 334edb46e9SPaul Traina #include <netinet/in.h> 34ee3e7633SGarrett Wollman #include <net/ethernet.h> 354edb46e9SPaul Traina #include <netinet/in_systm.h> 364edb46e9SPaul Traina #include <netinet/ip.h> 374edb46e9SPaul Traina #include <netinet/ip_var.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include <rpc/rpc.h> 404edb46e9SPaul Traina 414edb46e9SPaul Traina #include <ctype.h> 422ebf6c05SBill Fenner #include <pcap.h> 434edb46e9SPaul Traina #include <stdio.h> 444edb46e9SPaul Traina #include <string.h> 454edb46e9SPaul Traina 464edb46e9SPaul Traina #include "interface.h" 474edb46e9SPaul Traina #include "addrtoname.h" 48647f50c3SDoug Rabson #include "extract.h" /* must come after interface.h */ 494edb46e9SPaul Traina 50647f50c3SDoug Rabson #include "nfs.h" 514edb46e9SPaul Traina #include "nfsfh.h" 524edb46e9SPaul Traina 53647f50c3SDoug Rabson static void nfs_printfh(const u_int32_t *, const int); 544edb46e9SPaul Traina static void xid_map_enter(const struct rpc_msg *, const struct ip *); 55647f50c3SDoug Rabson static int32_t xid_map_find(const struct rpc_msg *, const struct ip *, u_int32_t *, 56647f50c3SDoug Rabson u_int32_t *); 57647f50c3SDoug Rabson static void interp_reply(const struct rpc_msg *, u_int32_t, u_int32_t, int); 58647f50c3SDoug Rabson static const u_int32_t *parse_post_op_attr(const u_int32_t *, int); 59647f50c3SDoug Rabson 602ebf6c05SBill Fenner static int nfserr; /* true if we error rather than trunc */ 612ebf6c05SBill Fenner 62647f50c3SDoug Rabson /* 63647f50c3SDoug Rabson * Mapping of old NFS Version 2 RPC numbers to generic numbers. 64647f50c3SDoug Rabson */ 65647f50c3SDoug Rabson u_int32_t nfsv3_procid[NFS_NPROCS] = { 66647f50c3SDoug Rabson NFSPROC_NULL, 67647f50c3SDoug Rabson NFSPROC_GETATTR, 68647f50c3SDoug Rabson NFSPROC_SETATTR, 69647f50c3SDoug Rabson NFSPROC_NOOP, 70647f50c3SDoug Rabson NFSPROC_LOOKUP, 71647f50c3SDoug Rabson NFSPROC_READLINK, 72647f50c3SDoug Rabson NFSPROC_READ, 73647f50c3SDoug Rabson NFSPROC_NOOP, 74647f50c3SDoug Rabson NFSPROC_WRITE, 75647f50c3SDoug Rabson NFSPROC_CREATE, 76647f50c3SDoug Rabson NFSPROC_REMOVE, 77647f50c3SDoug Rabson NFSPROC_RENAME, 78647f50c3SDoug Rabson NFSPROC_LINK, 79647f50c3SDoug Rabson NFSPROC_SYMLINK, 80647f50c3SDoug Rabson NFSPROC_MKDIR, 81647f50c3SDoug Rabson NFSPROC_RMDIR, 82647f50c3SDoug Rabson NFSPROC_READDIR, 83647f50c3SDoug Rabson NFSPROC_FSSTAT, 84647f50c3SDoug Rabson NFSPROC_NOOP, 85647f50c3SDoug Rabson NFSPROC_NOOP, 86647f50c3SDoug Rabson NFSPROC_NOOP, 87647f50c3SDoug Rabson NFSPROC_NOOP, 88647f50c3SDoug Rabson NFSPROC_NOOP, 89647f50c3SDoug Rabson NFSPROC_NOOP, 90647f50c3SDoug Rabson NFSPROC_NOOP, 91647f50c3SDoug Rabson NFSPROC_NOOP 92647f50c3SDoug Rabson }; 93647f50c3SDoug Rabson 94647f50c3SDoug Rabson const char *nfsv3_writemodes[NFSV3WRITE_NMODES] = { 95647f50c3SDoug Rabson "unstable", 96647f50c3SDoug Rabson "datasync", 97647f50c3SDoug Rabson "filesync" 98647f50c3SDoug Rabson }; 99647f50c3SDoug Rabson 100647f50c3SDoug Rabson static struct tok type2str[] = { 101647f50c3SDoug Rabson { NFNON, "NON" }, 102647f50c3SDoug Rabson { NFREG, "REG" }, 103647f50c3SDoug Rabson { NFDIR, "DIR" }, 104647f50c3SDoug Rabson { NFBLK, "BLK" }, 105647f50c3SDoug Rabson { NFCHR, "CHR" }, 106647f50c3SDoug Rabson { NFLNK, "LNK" }, 107647f50c3SDoug Rabson { NFFIFO, "FIFO" }, 108647f50c3SDoug Rabson { 0, NULL } 109647f50c3SDoug Rabson }; 110647f50c3SDoug Rabson 111647f50c3SDoug Rabson /* 112647f50c3SDoug Rabson * Print out a 64-bit integer. This appears to be different on each system, 113647f50c3SDoug Rabson * try to make the best of it. The integer stored as 2 consecutive XDR 114647f50c3SDoug Rabson * encoded 32-bit integers, to which a pointer is passed. 115647f50c3SDoug Rabson * 116647f50c3SDoug Rabson * Assume that a system that has INT64_FORMAT defined, has a 64-bit 117647f50c3SDoug Rabson * integer datatype and can print it. 118647f50c3SDoug Rabson */ 119647f50c3SDoug Rabson 120647f50c3SDoug Rabson #define UNSIGNED 0 121647f50c3SDoug Rabson #define SIGNED 1 122647f50c3SDoug Rabson #define HEX 2 123647f50c3SDoug Rabson 124647f50c3SDoug Rabson #define INT64_FORMAT "%qd" 125647f50c3SDoug Rabson #define U_INT64_FORMAT "%qu" 126647f50c3SDoug Rabson #define HEX_INT64_FORMAT "%qx" 127647f50c3SDoug Rabson 128647f50c3SDoug Rabson int print_int64(const u_int32_t *dp, int how) 129647f50c3SDoug Rabson { 130647f50c3SDoug Rabson #ifdef INT64_FORMAT 131647f50c3SDoug Rabson u_int64_t res; 132647f50c3SDoug Rabson 133647f50c3SDoug Rabson res = ((u_int64_t)ntohl(dp[0]) << 32) | (u_int64_t)ntohl(dp[1]); 134647f50c3SDoug Rabson switch (how) { 135647f50c3SDoug Rabson case SIGNED: 136647f50c3SDoug Rabson printf(INT64_FORMAT, res); 137647f50c3SDoug Rabson break; 138647f50c3SDoug Rabson case UNSIGNED: 139647f50c3SDoug Rabson printf(U_INT64_FORMAT, res); 140647f50c3SDoug Rabson break; 141647f50c3SDoug Rabson case HEX: 142647f50c3SDoug Rabson printf(HEX_INT64_FORMAT, res); 143647f50c3SDoug Rabson break; 144647f50c3SDoug Rabson default: 145647f50c3SDoug Rabson return (0); 146647f50c3SDoug Rabson } 147647f50c3SDoug Rabson #else 148647f50c3SDoug Rabson /* 149647f50c3SDoug Rabson * XXX - throw upper 32 bits away. 150647f50c3SDoug Rabson * Could also go for hex: printf("0x%x%x", dp[0], dp[1]); 151647f50c3SDoug Rabson */ 152647f50c3SDoug Rabson if (how == SIGNED) 153647f50c3SDoug Rabson printf("%ld", (int)dp[1]); 154647f50c3SDoug Rabson else 155647f50c3SDoug Rabson printf("%lu", (unsigned int)dp[1]); 156647f50c3SDoug Rabson #endif 157647f50c3SDoug Rabson return 1; 158647f50c3SDoug Rabson } 159647f50c3SDoug Rabson 160647f50c3SDoug Rabson static const u_int32_t * 161647f50c3SDoug Rabson parse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3) 162647f50c3SDoug Rabson { 163647f50c3SDoug Rabson register const u_int32_t *ep = (u_int32_t *)snapend; 164647f50c3SDoug Rabson 165647f50c3SDoug Rabson if (dp + 1 > ep) 1662ebf6c05SBill Fenner return (NULL); 167647f50c3SDoug Rabson if ((sa3->sa_modeset = ntohl(*dp++))) { 168647f50c3SDoug Rabson if (dp + 1 > ep) 1692ebf6c05SBill Fenner return (NULL); 170647f50c3SDoug Rabson sa3->sa_mode = ntohl(*dp++); 171647f50c3SDoug Rabson } 172647f50c3SDoug Rabson 173647f50c3SDoug Rabson if (dp + 1 > ep) 1742ebf6c05SBill Fenner return (NULL); 175647f50c3SDoug Rabson if ((sa3->sa_uidset = ntohl(*dp++))) { 176647f50c3SDoug Rabson if (dp + 1 > ep) 1772ebf6c05SBill Fenner return (NULL); 178647f50c3SDoug Rabson sa3->sa_uid = ntohl(*dp++); 179647f50c3SDoug Rabson } 180647f50c3SDoug Rabson 181647f50c3SDoug Rabson if (dp + 1 > ep) 1822ebf6c05SBill Fenner return (NULL); 183647f50c3SDoug Rabson if ((sa3->sa_gidset = ntohl(*dp++))) { 184647f50c3SDoug Rabson if (dp + 1 > ep) 1852ebf6c05SBill Fenner return (NULL); 186647f50c3SDoug Rabson sa3->sa_gid = ntohl(*dp++); 187647f50c3SDoug Rabson } 188647f50c3SDoug Rabson 189647f50c3SDoug Rabson if (dp + 1 > ep) 1902ebf6c05SBill Fenner return (NULL); 191647f50c3SDoug Rabson if ((sa3->sa_sizeset = ntohl(*dp++))) { 192647f50c3SDoug Rabson if (dp + 1 > ep) 1932ebf6c05SBill Fenner return (NULL); 194647f50c3SDoug Rabson sa3->sa_size = ntohl(*dp++); 195647f50c3SDoug Rabson } 196647f50c3SDoug Rabson 197647f50c3SDoug Rabson if (dp + 1 > ep) 1982ebf6c05SBill Fenner return (NULL); 199647f50c3SDoug Rabson if ((sa3->sa_atimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 200647f50c3SDoug Rabson if (dp + 2 > ep) 2012ebf6c05SBill Fenner return (NULL); 202647f50c3SDoug Rabson sa3->sa_atime.nfsv3_sec = ntohl(*dp++); 203647f50c3SDoug Rabson sa3->sa_atime.nfsv3_nsec = ntohl(*dp++); 204647f50c3SDoug Rabson } 205647f50c3SDoug Rabson 206647f50c3SDoug Rabson if (dp + 1 > ep) 2072ebf6c05SBill Fenner return (NULL); 208647f50c3SDoug Rabson if ((sa3->sa_mtimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) { 209647f50c3SDoug Rabson if (dp + 2 > ep) 2102ebf6c05SBill Fenner return (NULL); 211647f50c3SDoug Rabson sa3->sa_mtime.nfsv3_sec = ntohl(*dp++); 212647f50c3SDoug Rabson sa3->sa_mtime.nfsv3_nsec = ntohl(*dp++); 213647f50c3SDoug Rabson } 214647f50c3SDoug Rabson 215647f50c3SDoug Rabson return dp; 216647f50c3SDoug Rabson } 217647f50c3SDoug Rabson 218647f50c3SDoug Rabson void 219647f50c3SDoug Rabson print_sattr3(const struct nfsv3_sattr *sa3, int verbose) 220647f50c3SDoug Rabson { 221647f50c3SDoug Rabson if (sa3->sa_modeset) 222647f50c3SDoug Rabson printf(" mode %o", sa3->sa_mode); 223647f50c3SDoug Rabson if (sa3->sa_uidset) 224647f50c3SDoug Rabson printf(" uid %u", sa3->sa_uid); 225647f50c3SDoug Rabson if (sa3->sa_gidset) 226647f50c3SDoug Rabson printf(" gid %u", sa3->sa_gid); 227647f50c3SDoug Rabson if (verbose > 1) { 228647f50c3SDoug Rabson if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 229647f50c3SDoug Rabson printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec, 230647f50c3SDoug Rabson sa3->sa_atime.nfsv3_nsec); 231647f50c3SDoug Rabson if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 232647f50c3SDoug Rabson printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 233647f50c3SDoug Rabson sa3->sa_mtime.nfsv3_nsec); 234647f50c3SDoug Rabson } 235647f50c3SDoug Rabson } 2364edb46e9SPaul Traina 2374edb46e9SPaul Traina void 2384edb46e9SPaul Traina nfsreply_print(register const u_char *bp, u_int length, 2394edb46e9SPaul Traina register const u_char *bp2) 2404edb46e9SPaul Traina { 2414edb46e9SPaul Traina register const struct rpc_msg *rp; 2424edb46e9SPaul Traina register const struct ip *ip; 243647f50c3SDoug Rabson u_int32_t proc, vers; 2444edb46e9SPaul Traina 2452ebf6c05SBill Fenner nfserr = 0; /* assume no error */ 2464edb46e9SPaul Traina rp = (const struct rpc_msg *)bp; 2474edb46e9SPaul Traina ip = (const struct ip *)bp2; 2484edb46e9SPaul Traina 2494edb46e9SPaul Traina if (!nflag) 2504edb46e9SPaul Traina (void)printf("%s.nfs > %s.%x: reply %s %d", 2514edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 2524edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 2534edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 2544edb46e9SPaul Traina ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 2554edb46e9SPaul Traina "ok":"ERR", 2564edb46e9SPaul Traina length); 2574edb46e9SPaul Traina else 2584edb46e9SPaul Traina (void)printf("%s.%x > %s.%x: reply %s %d", 2594edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 2604edb46e9SPaul Traina NFS_PORT, 2614edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 2624edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 2634edb46e9SPaul Traina ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? 2644edb46e9SPaul Traina "ok":"ERR", 2654edb46e9SPaul Traina length); 2664edb46e9SPaul Traina 267647f50c3SDoug Rabson if (xid_map_find(rp, ip, &proc, &vers) >= 0) 268647f50c3SDoug Rabson interp_reply(rp, proc, vers, length); 2694edb46e9SPaul Traina } 2704edb46e9SPaul Traina 2714edb46e9SPaul Traina /* 2724edb46e9SPaul Traina * Return a pointer to the first file handle in the packet. 2732ebf6c05SBill Fenner * If the packet was truncated, return NULL. 2744edb46e9SPaul Traina */ 2754edb46e9SPaul Traina static const u_int32_t * 276647f50c3SDoug Rabson parsereq(register const struct rpc_msg *rp, register int length) 2774edb46e9SPaul Traina { 2782ebf6c05SBill Fenner register const u_int32_t *dp; 2794edb46e9SPaul Traina register u_int len; 2804edb46e9SPaul Traina 2814edb46e9SPaul Traina /* 2824edb46e9SPaul Traina * find the start of the req data (if we captured it) 2834edb46e9SPaul Traina */ 2842ebf6c05SBill Fenner dp = (u_int32_t *)&rp->rm_call.cb_cred; 2852ebf6c05SBill Fenner TCHECK(dp[1]); 2864edb46e9SPaul Traina len = ntohl(dp[1]); 2872ebf6c05SBill Fenner if (len < length) { 2882ebf6c05SBill Fenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 2892ebf6c05SBill Fenner TCHECK(dp[1]); 2904edb46e9SPaul Traina len = ntohl(dp[1]); 2912ebf6c05SBill Fenner if (len < length) { 2922ebf6c05SBill Fenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 2932ebf6c05SBill Fenner TCHECK2(dp[0], 0); 2944edb46e9SPaul Traina return (dp); 2954edb46e9SPaul Traina } 2964edb46e9SPaul Traina } 2972ebf6c05SBill Fenner trunc: 2982ebf6c05SBill Fenner return (NULL); 2994edb46e9SPaul Traina } 3004edb46e9SPaul Traina 3014edb46e9SPaul Traina /* 3024edb46e9SPaul Traina * Print out an NFS file handle and return a pointer to following word. 3032ebf6c05SBill Fenner * If packet was truncated, return NULL. 3044edb46e9SPaul Traina */ 3054edb46e9SPaul Traina static const u_int32_t * 306647f50c3SDoug Rabson parsefh(register const u_int32_t *dp, int v3) 3074edb46e9SPaul Traina { 308647f50c3SDoug Rabson int len; 309647f50c3SDoug Rabson 310647f50c3SDoug Rabson if (v3) { 3112ebf6c05SBill Fenner TCHECK(dp[0]); 312647f50c3SDoug Rabson len = (int)ntohl(*dp) / 4; 313647f50c3SDoug Rabson dp++; 314647f50c3SDoug Rabson } else 315647f50c3SDoug Rabson len = NFSX_V2FH / 4; 316647f50c3SDoug Rabson 3172ebf6c05SBill Fenner if (TTEST2(*dp, len * sizeof(*dp))) { 318647f50c3SDoug Rabson nfs_printfh(dp, len); 319647f50c3SDoug Rabson return (dp + len); 3204edb46e9SPaul Traina } 3212ebf6c05SBill Fenner trunc: 3222ebf6c05SBill Fenner return (NULL); 3234edb46e9SPaul Traina } 3244edb46e9SPaul Traina 3254edb46e9SPaul Traina /* 3264edb46e9SPaul Traina * Print out a file name and return pointer to 32-bit word past it. 3272ebf6c05SBill Fenner * If packet was truncated, return NULL. 3284edb46e9SPaul Traina */ 3294edb46e9SPaul Traina static const u_int32_t * 3304edb46e9SPaul Traina parsefn(register const u_int32_t *dp) 3314edb46e9SPaul Traina { 3324edb46e9SPaul Traina register u_int32_t len; 3334edb46e9SPaul Traina register const u_char *cp; 3344edb46e9SPaul Traina 3354edb46e9SPaul Traina /* Bail if we don't have the string length */ 3364edb46e9SPaul Traina if ((u_char *)dp > snapend - sizeof(*dp)) 3372ebf6c05SBill Fenner return (NULL); 3384edb46e9SPaul Traina 3394edb46e9SPaul Traina /* Fetch string length; convert to host order */ 3404edb46e9SPaul Traina len = *dp++; 3414edb46e9SPaul Traina NTOHL(len); 3424edb46e9SPaul Traina 3434edb46e9SPaul Traina cp = (u_char *)dp; 3444edb46e9SPaul Traina /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 3454edb46e9SPaul Traina dp += ((len + 3) & ~3) / sizeof(*dp); 3464edb46e9SPaul Traina if ((u_char *)dp > snapend) 3472ebf6c05SBill Fenner return (NULL); 3484edb46e9SPaul Traina /* XXX seems like we should be checking the length */ 3492ebf6c05SBill Fenner putchar('"'); 3504edb46e9SPaul Traina (void) fn_printn(cp, len, NULL); 3512ebf6c05SBill Fenner putchar('"'); 3524edb46e9SPaul Traina 3534edb46e9SPaul Traina return (dp); 3544edb46e9SPaul Traina } 3554edb46e9SPaul Traina 3564edb46e9SPaul Traina /* 3574edb46e9SPaul Traina * Print out file handle and file name. 3584edb46e9SPaul Traina * Return pointer to 32-bit word past file name. 3592ebf6c05SBill Fenner * If packet was truncated (or there was some other error), return NULL. 3604edb46e9SPaul Traina */ 3614edb46e9SPaul Traina static const u_int32_t * 362647f50c3SDoug Rabson parsefhn(register const u_int32_t *dp, int v3) 3634edb46e9SPaul Traina { 364647f50c3SDoug Rabson dp = parsefh(dp, v3); 3652ebf6c05SBill Fenner if (dp == NULL) 3662ebf6c05SBill Fenner return (NULL); 3674edb46e9SPaul Traina putchar(' '); 3684edb46e9SPaul Traina return (parsefn(dp)); 3694edb46e9SPaul Traina } 3704edb46e9SPaul Traina 3714edb46e9SPaul Traina void 3724edb46e9SPaul Traina nfsreq_print(register const u_char *bp, u_int length, 3734edb46e9SPaul Traina register const u_char *bp2) 3744edb46e9SPaul Traina { 3754edb46e9SPaul Traina register const struct rpc_msg *rp; 3764edb46e9SPaul Traina register const struct ip *ip; 3774edb46e9SPaul Traina register const u_int32_t *dp; 378647f50c3SDoug Rabson nfstype type; 379647f50c3SDoug Rabson int proc, v3; 380647f50c3SDoug Rabson struct nfsv3_sattr sa3; 3814edb46e9SPaul Traina 3822ebf6c05SBill Fenner nfserr = 0; /* assume no error */ 3834edb46e9SPaul Traina rp = (const struct rpc_msg *)bp; 3844edb46e9SPaul Traina ip = (const struct ip *)bp2; 3854edb46e9SPaul Traina if (!nflag) 3864edb46e9SPaul Traina (void)printf("%s.%x > %s.nfs: %d", 3874edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 3884edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 3894edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 3904edb46e9SPaul Traina length); 3914edb46e9SPaul Traina else 3924edb46e9SPaul Traina (void)printf("%s.%x > %s.%x: %d", 3934edb46e9SPaul Traina ipaddr_string(&ip->ip_src), 3944edb46e9SPaul Traina (u_int32_t)ntohl(rp->rm_xid), 3954edb46e9SPaul Traina ipaddr_string(&ip->ip_dst), 3964edb46e9SPaul Traina NFS_PORT, 3974edb46e9SPaul Traina length); 3984edb46e9SPaul Traina 3994edb46e9SPaul Traina xid_map_enter(rp, ip); /* record proc number for later on */ 4004edb46e9SPaul Traina 401647f50c3SDoug Rabson v3 = (ntohl(rp->rm_call.cb_vers) == NFS_VER3); 402647f50c3SDoug Rabson proc = ntohl(rp->rm_call.cb_proc); 403647f50c3SDoug Rabson 404647f50c3SDoug Rabson if (!v3 && proc < NFS_NPROCS) 405647f50c3SDoug Rabson proc = nfsv3_procid[proc]; 406647f50c3SDoug Rabson 407647f50c3SDoug Rabson switch (proc) { 4084edb46e9SPaul Traina case NFSPROC_NOOP: 4094edb46e9SPaul Traina printf(" nop"); 4104edb46e9SPaul Traina return; 4114edb46e9SPaul Traina case NFSPROC_NULL: 4124edb46e9SPaul Traina printf(" null"); 4134edb46e9SPaul Traina return; 4144edb46e9SPaul Traina 4154edb46e9SPaul Traina case NFSPROC_GETATTR: 4164edb46e9SPaul Traina printf(" getattr"); 4172ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) 4184edb46e9SPaul Traina return; 4194edb46e9SPaul Traina break; 4204edb46e9SPaul Traina 4214edb46e9SPaul Traina case NFSPROC_SETATTR: 4224edb46e9SPaul Traina printf(" setattr"); 4232ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) 4244edb46e9SPaul Traina return; 4254edb46e9SPaul Traina break; 4264edb46e9SPaul Traina 4274edb46e9SPaul Traina case NFSPROC_LOOKUP: 4284edb46e9SPaul Traina printf(" lookup"); 4292ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) 4304edb46e9SPaul Traina return; 4314edb46e9SPaul Traina break; 4324edb46e9SPaul Traina 433647f50c3SDoug Rabson case NFSPROC_ACCESS: 434647f50c3SDoug Rabson printf(" access"); 4352ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 4362ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 437647f50c3SDoug Rabson TCHECK(*dp); 4382ebf6c05SBill Fenner printf(" %04lx", ntohl(dp[0])); 439647f50c3SDoug Rabson return; 440647f50c3SDoug Rabson } 441647f50c3SDoug Rabson break; 442647f50c3SDoug Rabson 4434edb46e9SPaul Traina case NFSPROC_READLINK: 4444edb46e9SPaul Traina printf(" readlink"); 4452ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) 4464edb46e9SPaul Traina return; 4474edb46e9SPaul Traina break; 4484edb46e9SPaul Traina 4494edb46e9SPaul Traina case NFSPROC_READ: 4504edb46e9SPaul Traina printf(" read"); 4512ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 4522ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 453647f50c3SDoug Rabson if (v3) { 454647f50c3SDoug Rabson TCHECK2(*dp, 3 * sizeof(*dp)); 455647f50c3SDoug Rabson printf(" %lu bytes @ ", ntohl(dp[2])); 456647f50c3SDoug Rabson print_int64(dp, UNSIGNED); 457647f50c3SDoug Rabson } else { 458647f50c3SDoug Rabson TCHECK2(*dp, 2 * sizeof(*dp)); 459647f50c3SDoug Rabson printf(" %lu bytes @ %lu", 460647f50c3SDoug Rabson ntohl(dp[1]), ntohl(dp[0])); 461647f50c3SDoug Rabson } 4624edb46e9SPaul Traina return; 4634edb46e9SPaul Traina } 4644edb46e9SPaul Traina break; 4654edb46e9SPaul Traina 4664edb46e9SPaul Traina case NFSPROC_WRITE: 4674edb46e9SPaul Traina printf(" write"); 4682ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 4692ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 470647f50c3SDoug Rabson if (v3) { 471647f50c3SDoug Rabson TCHECK2(*dp, 3 * sizeof(*dp)); 472647f50c3SDoug Rabson printf(" %lu bytes @ ", ntohl(dp[4])); 473647f50c3SDoug Rabson print_int64(dp, UNSIGNED); 474647f50c3SDoug Rabson if (vflag) { 475647f50c3SDoug Rabson dp += 3; 476647f50c3SDoug Rabson TCHECK2(*dp, sizeof(*dp)); 477647f50c3SDoug Rabson printf(" <%s>", 478647f50c3SDoug Rabson nfsv3_writemodes[ntohl(*dp)]); 479647f50c3SDoug Rabson } 480647f50c3SDoug Rabson } else { 481647f50c3SDoug Rabson TCHECK2(*dp, 4 * sizeof(*dp)); 482647f50c3SDoug Rabson printf(" %lu (%lu) bytes @ %lu (%lu)", 483647f50c3SDoug Rabson ntohl(dp[3]), ntohl(dp[2]), 484647f50c3SDoug Rabson ntohl(dp[1]), ntohl(dp[0])); 485647f50c3SDoug Rabson } 4864edb46e9SPaul Traina return; 4874edb46e9SPaul Traina } 4884edb46e9SPaul Traina break; 4894edb46e9SPaul Traina 4904edb46e9SPaul Traina case NFSPROC_CREATE: 4914edb46e9SPaul Traina printf(" create"); 4922ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) 4934edb46e9SPaul Traina return; 4944edb46e9SPaul Traina break; 4954edb46e9SPaul Traina 496647f50c3SDoug Rabson case NFSPROC_MKDIR: 497647f50c3SDoug Rabson printf(" mkdir"); 4982ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) 499647f50c3SDoug Rabson return; 500647f50c3SDoug Rabson break; 501647f50c3SDoug Rabson 502647f50c3SDoug Rabson case NFSPROC_SYMLINK: 503647f50c3SDoug Rabson printf(" symlink"); 5042ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5052ebf6c05SBill Fenner (dp = parsefhn(dp, v3)) != NULL) { 506647f50c3SDoug Rabson fputs(" -> ", stdout); 5072ebf6c05SBill Fenner if (v3 && (dp = parse_sattr3(dp, &sa3)) == NULL) 508647f50c3SDoug Rabson break; 5092ebf6c05SBill Fenner if (parsefn(dp) == NULL) 510647f50c3SDoug Rabson break; 511647f50c3SDoug Rabson if (v3 && vflag) 512647f50c3SDoug Rabson print_sattr3(&sa3, vflag); 513647f50c3SDoug Rabson return; 514647f50c3SDoug Rabson } 515647f50c3SDoug Rabson break; 516647f50c3SDoug Rabson 517647f50c3SDoug Rabson case NFSPROC_MKNOD: 518647f50c3SDoug Rabson printf(" mknod"); 5192ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5202ebf6c05SBill Fenner (dp = parsefhn(dp, v3)) != NULL) { 521647f50c3SDoug Rabson if (dp + 1 > (u_int32_t *)snapend) 522647f50c3SDoug Rabson break; 523647f50c3SDoug Rabson type = (nfstype)ntohl(*dp++); 5242ebf6c05SBill Fenner if ((dp = parse_sattr3(dp, &sa3)) == NULL) 525647f50c3SDoug Rabson break; 526647f50c3SDoug Rabson printf(" %s", tok2str(type2str, "unk-ft %d", type)); 527647f50c3SDoug Rabson if (vflag && (type == NFCHR || type == NFBLK)) { 528647f50c3SDoug Rabson if (dp + 2 > (u_int32_t *)snapend) 529647f50c3SDoug Rabson break; 5302ebf6c05SBill Fenner printf(" %lu/%lu", ntohl(dp[0]), ntohl(dp[1])); 531647f50c3SDoug Rabson dp += 2; 532647f50c3SDoug Rabson } 533647f50c3SDoug Rabson if (vflag) 534647f50c3SDoug Rabson print_sattr3(&sa3, vflag); 535647f50c3SDoug Rabson return; 536647f50c3SDoug Rabson } 537647f50c3SDoug Rabson break; 538647f50c3SDoug Rabson 5394edb46e9SPaul Traina case NFSPROC_REMOVE: 5404edb46e9SPaul Traina printf(" remove"); 5412ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) 542647f50c3SDoug Rabson return; 543647f50c3SDoug Rabson break; 544647f50c3SDoug Rabson 545647f50c3SDoug Rabson case NFSPROC_RMDIR: 546647f50c3SDoug Rabson printf(" rmdir"); 5472ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp, v3) != NULL) 5484edb46e9SPaul Traina return; 5494edb46e9SPaul Traina break; 5504edb46e9SPaul Traina 5514edb46e9SPaul Traina case NFSPROC_RENAME: 5524edb46e9SPaul Traina printf(" rename"); 5532ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5542ebf6c05SBill Fenner (dp = parsefhn(dp, v3)) != NULL) { 5554edb46e9SPaul Traina fputs(" ->", stdout); 5562ebf6c05SBill Fenner if (parsefhn(dp, v3) != NULL) 5574edb46e9SPaul Traina return; 5584edb46e9SPaul Traina } 5594edb46e9SPaul Traina break; 5604edb46e9SPaul Traina 5614edb46e9SPaul Traina case NFSPROC_LINK: 5624edb46e9SPaul Traina printf(" link"); 5632ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5642ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 5654edb46e9SPaul Traina fputs(" ->", stdout); 5662ebf6c05SBill Fenner if (parsefhn(dp, v3) != NULL) 5674edb46e9SPaul Traina return; 5684edb46e9SPaul Traina } 5694edb46e9SPaul Traina break; 5704edb46e9SPaul Traina 5714edb46e9SPaul Traina case NFSPROC_READDIR: 5724edb46e9SPaul Traina printf(" readdir"); 5732ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 5742ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 575647f50c3SDoug Rabson if (v3) { 576647f50c3SDoug Rabson TCHECK2(*dp, 20); 5774edb46e9SPaul Traina /* 578647f50c3SDoug Rabson * We shouldn't really try to interpret the 579647f50c3SDoug Rabson * offset cookie here. 5804edb46e9SPaul Traina */ 581647f50c3SDoug Rabson printf(" %lu bytes @ ", ntohl(dp[4])); 582647f50c3SDoug Rabson print_int64(dp, SIGNED); 583647f50c3SDoug Rabson if (vflag) 5842ebf6c05SBill Fenner printf(" verf %08x%08x", dp[2], 585647f50c3SDoug Rabson dp[3]); 586647f50c3SDoug Rabson } else { 587647f50c3SDoug Rabson TCHECK2(*dp, 2 * sizeof(*dp)); 588647f50c3SDoug Rabson /* 589647f50c3SDoug Rabson * Print the offset as signed, since -1 is 590647f50c3SDoug Rabson * common, but offsets > 2^31 aren't. 591647f50c3SDoug Rabson */ 592647f50c3SDoug Rabson printf(" %lu bytes @ %ld", ntohl(dp[1]), 593647f50c3SDoug Rabson ntohl(dp[0])); 594647f50c3SDoug Rabson } 5954edb46e9SPaul Traina return; 5964edb46e9SPaul Traina } 5974edb46e9SPaul Traina break; 5984edb46e9SPaul Traina 599647f50c3SDoug Rabson case NFSPROC_READDIRPLUS: 600647f50c3SDoug Rabson printf(" readdirplus"); 6012ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6022ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 603647f50c3SDoug Rabson TCHECK2(*dp, 20); 604647f50c3SDoug Rabson /* 605647f50c3SDoug Rabson * We don't try to interpret the offset 606647f50c3SDoug Rabson * cookie here. 607647f50c3SDoug Rabson */ 608647f50c3SDoug Rabson printf(" %lu bytes @ ", ntohl(dp[4])); 609647f50c3SDoug Rabson print_int64(dp, SIGNED); 610647f50c3SDoug Rabson if (vflag) 6112ebf6c05SBill Fenner printf(" max %lu verf %08x%08x", 612647f50c3SDoug Rabson ntohl(dp[5]), dp[2], dp[3]); 613647f50c3SDoug Rabson return; 614647f50c3SDoug Rabson } 615647f50c3SDoug Rabson break; 616647f50c3SDoug Rabson 617647f50c3SDoug Rabson case NFSPROC_FSSTAT: 618647f50c3SDoug Rabson printf(" fsstat"); 6192ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && parsefh(dp, v3) != NULL) 6204edb46e9SPaul Traina return; 6214edb46e9SPaul Traina break; 6224edb46e9SPaul Traina 623647f50c3SDoug Rabson case NFSPROC_FSINFO: 624647f50c3SDoug Rabson printf(" fsinfo"); 625647f50c3SDoug Rabson break; 626647f50c3SDoug Rabson 627647f50c3SDoug Rabson case NFSPROC_PATHCONF: 628647f50c3SDoug Rabson printf(" pathconf"); 629647f50c3SDoug Rabson break; 630647f50c3SDoug Rabson 631647f50c3SDoug Rabson case NFSPROC_COMMIT: 632647f50c3SDoug Rabson printf(" commit"); 6332ebf6c05SBill Fenner if ((dp = parsereq(rp, length)) != NULL && 6342ebf6c05SBill Fenner (dp = parsefh(dp, v3)) != NULL) { 635647f50c3SDoug Rabson printf(" %lu bytes @ ", ntohl(dp[2])); 636647f50c3SDoug Rabson print_int64(dp, UNSIGNED); 637647f50c3SDoug Rabson return; 638647f50c3SDoug Rabson } 639647f50c3SDoug Rabson break; 640647f50c3SDoug Rabson 6414edb46e9SPaul Traina default: 642647f50c3SDoug Rabson printf(" proc-%lu", ntohl(rp->rm_call.cb_proc)); 6434edb46e9SPaul Traina return; 6444edb46e9SPaul Traina } 6454edb46e9SPaul Traina trunc: 6462ebf6c05SBill Fenner if (!nfserr) 6474edb46e9SPaul Traina fputs(" [|nfs]", stdout); 6484edb46e9SPaul Traina } 6494edb46e9SPaul Traina 6504edb46e9SPaul Traina /* 6514edb46e9SPaul Traina * Print out an NFS file handle. 6524edb46e9SPaul Traina * We assume packet was not truncated before the end of the 6534edb46e9SPaul Traina * file handle pointed to by dp. 6544edb46e9SPaul Traina * 6554edb46e9SPaul Traina * Note: new version (using portable file-handle parser) doesn't produce 6564edb46e9SPaul Traina * generation number. It probably could be made to do that, with some 6574edb46e9SPaul Traina * additional hacking on the parser code. 6584edb46e9SPaul Traina */ 6594edb46e9SPaul Traina static void 660647f50c3SDoug Rabson nfs_printfh(register const u_int32_t *dp, const int len) 6614edb46e9SPaul Traina { 6624edb46e9SPaul Traina my_fsid fsid; 6634edb46e9SPaul Traina ino_t ino; 6644edb46e9SPaul Traina char *sfsname = NULL; 6654edb46e9SPaul Traina 666647f50c3SDoug Rabson Parse_fh((caddr_t *)dp, len, &fsid, &ino, NULL, &sfsname, 0); 6674edb46e9SPaul Traina 6684edb46e9SPaul Traina if (sfsname) { 6694edb46e9SPaul Traina /* file system ID is ASCII, not numeric, for this server OS */ 670647f50c3SDoug Rabson static char temp[NFSX_V3FHMAX+1]; 6714edb46e9SPaul Traina 6724edb46e9SPaul Traina /* Make sure string is null-terminated */ 673647f50c3SDoug Rabson strncpy(temp, sfsname, NFSX_V3FHMAX); 6744edb46e9SPaul Traina /* Remove trailing spaces */ 6754edb46e9SPaul Traina sfsname = strchr(temp, ' '); 6764edb46e9SPaul Traina if (sfsname) 6774edb46e9SPaul Traina *sfsname = 0; 6784edb46e9SPaul Traina 6794edb46e9SPaul Traina (void)printf(" fh %s/%u", temp, (u_int32_t)ino); 6802ebf6c05SBill Fenner } else { 6814edb46e9SPaul Traina (void)printf(" fh %u,%u/%u", 6822ebf6c05SBill Fenner fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor, (u_int32_t)ino); 6834edb46e9SPaul Traina } 6844edb46e9SPaul Traina } 6854edb46e9SPaul Traina 6864edb46e9SPaul Traina /* 6874edb46e9SPaul Traina * Maintain a small cache of recent client.XID.server/proc pairs, to allow 6884edb46e9SPaul Traina * us to match up replies with requests and thus to know how to parse 6894edb46e9SPaul Traina * the reply. 6904edb46e9SPaul Traina */ 6914edb46e9SPaul Traina 6924edb46e9SPaul Traina struct xid_map_entry { 6934edb46e9SPaul Traina u_int32_t xid; /* transaction ID (net order) */ 6944edb46e9SPaul Traina struct in_addr client; /* client IP address (net order) */ 6954edb46e9SPaul Traina struct in_addr server; /* server IP address (net order) */ 6964edb46e9SPaul Traina u_int32_t proc; /* call proc number (host order) */ 697647f50c3SDoug Rabson u_int32_t vers; /* program version (host order) */ 6984edb46e9SPaul Traina }; 6994edb46e9SPaul Traina 7004edb46e9SPaul Traina /* 7014edb46e9SPaul Traina * Map entries are kept in an array that we manage as a ring; 7024edb46e9SPaul Traina * new entries are always added at the tail of the ring. Initially, 7034edb46e9SPaul Traina * all the entries are zero and hence don't match anything. 7044edb46e9SPaul Traina */ 7054edb46e9SPaul Traina 7064edb46e9SPaul Traina #define XIDMAPSIZE 64 7074edb46e9SPaul Traina 7084edb46e9SPaul Traina struct xid_map_entry xid_map[XIDMAPSIZE]; 7094edb46e9SPaul Traina 7104edb46e9SPaul Traina int xid_map_next = 0; 7114edb46e9SPaul Traina int xid_map_hint = 0; 7124edb46e9SPaul Traina 7134edb46e9SPaul Traina static void 7144edb46e9SPaul Traina xid_map_enter(const struct rpc_msg *rp, const struct ip *ip) 7154edb46e9SPaul Traina { 7164edb46e9SPaul Traina struct xid_map_entry *xmep; 7174edb46e9SPaul Traina 7184edb46e9SPaul Traina xmep = &xid_map[xid_map_next]; 7194edb46e9SPaul Traina 7204edb46e9SPaul Traina if (++xid_map_next >= XIDMAPSIZE) 7214edb46e9SPaul Traina xid_map_next = 0; 7224edb46e9SPaul Traina 7234edb46e9SPaul Traina xmep->xid = rp->rm_xid; 7244edb46e9SPaul Traina xmep->client = ip->ip_src; 7254edb46e9SPaul Traina xmep->server = ip->ip_dst; 7264edb46e9SPaul Traina xmep->proc = ntohl(rp->rm_call.cb_proc); 727647f50c3SDoug Rabson xmep->vers = ntohl(rp->rm_call.cb_vers); 7284edb46e9SPaul Traina } 7294edb46e9SPaul Traina 7302ebf6c05SBill Fenner /* 7312ebf6c05SBill Fenner * Returns 0 and puts NFSPROC_xxx in proc return and 7322ebf6c05SBill Fenner * version in vers return, or returns -1 on failure 7332ebf6c05SBill Fenner */ 734647f50c3SDoug Rabson static int 735647f50c3SDoug Rabson xid_map_find(const struct rpc_msg *rp, const struct ip *ip, u_int32_t *proc, 736647f50c3SDoug Rabson u_int32_t *vers) 7374edb46e9SPaul Traina { 7384edb46e9SPaul Traina int i; 7394edb46e9SPaul Traina struct xid_map_entry *xmep; 7404edb46e9SPaul Traina u_int32_t xid = rp->rm_xid; 7414edb46e9SPaul Traina u_int32_t clip = ip->ip_dst.s_addr; 7424edb46e9SPaul Traina u_int32_t sip = ip->ip_src.s_addr; 7434edb46e9SPaul Traina 7444edb46e9SPaul Traina /* Start searching from where we last left off */ 7454edb46e9SPaul Traina i = xid_map_hint; 7464edb46e9SPaul Traina do { 7474edb46e9SPaul Traina xmep = &xid_map[i]; 7484edb46e9SPaul Traina if (xmep->xid == xid && xmep->client.s_addr == clip && 7494edb46e9SPaul Traina xmep->server.s_addr == sip) { 7504edb46e9SPaul Traina /* match */ 7514edb46e9SPaul Traina xid_map_hint = i; 752647f50c3SDoug Rabson *proc = xmep->proc; 753647f50c3SDoug Rabson *vers = xmep->vers; 754647f50c3SDoug Rabson return 0; 7554edb46e9SPaul Traina } 7564edb46e9SPaul Traina if (++i >= XIDMAPSIZE) 7574edb46e9SPaul Traina i = 0; 7584edb46e9SPaul Traina } while (i != xid_map_hint); 7594edb46e9SPaul Traina 7604edb46e9SPaul Traina /* search failed */ 7614edb46e9SPaul Traina return (-1); 7624edb46e9SPaul Traina } 7634edb46e9SPaul Traina 7644edb46e9SPaul Traina /* 7654edb46e9SPaul Traina * Routines for parsing reply packets 7664edb46e9SPaul Traina */ 7674edb46e9SPaul Traina 7684edb46e9SPaul Traina /* 7694edb46e9SPaul Traina * Return a pointer to the beginning of the actual results. 7702ebf6c05SBill Fenner * If the packet was truncated, return NULL. 7714edb46e9SPaul Traina */ 7724edb46e9SPaul Traina static const u_int32_t * 773647f50c3SDoug Rabson parserep(register const struct rpc_msg *rp, register int length) 7744edb46e9SPaul Traina { 7754edb46e9SPaul Traina register const u_int32_t *dp; 776647f50c3SDoug Rabson int len; 7774edb46e9SPaul Traina enum accept_stat astat; 7784edb46e9SPaul Traina 7794edb46e9SPaul Traina /* 7804edb46e9SPaul Traina * Portability note: 7814edb46e9SPaul Traina * Here we find the address of the ar_verf credentials. 7824edb46e9SPaul Traina * Originally, this calculation was 7834edb46e9SPaul Traina * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf 7844edb46e9SPaul Traina * On the wire, the rp_acpt field starts immediately after 7854edb46e9SPaul Traina * the (32 bit) rp_stat field. However, rp_acpt (which is a 7864edb46e9SPaul Traina * "struct accepted_reply") contains a "struct opaque_auth", 7874edb46e9SPaul Traina * whose internal representation contains a pointer, so on a 7884edb46e9SPaul Traina * 64-bit machine the compiler inserts 32 bits of padding 7894edb46e9SPaul Traina * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 7904edb46e9SPaul Traina * the internal representation to parse the on-the-wire 7914edb46e9SPaul Traina * representation. Instead, we skip past the rp_stat field, 7924edb46e9SPaul Traina * which is an "enum" and so occupies one 32-bit word. 7934edb46e9SPaul Traina */ 7944edb46e9SPaul Traina dp = ((const u_int32_t *)&rp->rm_reply) + 1; 7952ebf6c05SBill Fenner TCHECK2(dp[0], 1); 7964edb46e9SPaul Traina len = ntohl(dp[1]); 7974edb46e9SPaul Traina if (len >= length) 7982ebf6c05SBill Fenner return (NULL); 7994edb46e9SPaul Traina /* 8004edb46e9SPaul Traina * skip past the ar_verf credentials. 8014edb46e9SPaul Traina */ 8024edb46e9SPaul Traina dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); 8032ebf6c05SBill Fenner TCHECK2(dp[0], 0); 8044edb46e9SPaul Traina 8054edb46e9SPaul Traina /* 8064edb46e9SPaul Traina * now we can check the ar_stat field 8074edb46e9SPaul Traina */ 8084edb46e9SPaul Traina astat = ntohl(*(enum accept_stat *)dp); 8094edb46e9SPaul Traina switch (astat) { 8104edb46e9SPaul Traina 8114edb46e9SPaul Traina case SUCCESS: 8124edb46e9SPaul Traina break; 8134edb46e9SPaul Traina 8144edb46e9SPaul Traina case PROG_UNAVAIL: 8154edb46e9SPaul Traina printf(" PROG_UNAVAIL"); 8162ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8172ebf6c05SBill Fenner return (NULL); 8184edb46e9SPaul Traina 8194edb46e9SPaul Traina case PROG_MISMATCH: 8204edb46e9SPaul Traina printf(" PROG_MISMATCH"); 8212ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8222ebf6c05SBill Fenner return (NULL); 8234edb46e9SPaul Traina 8244edb46e9SPaul Traina case PROC_UNAVAIL: 8254edb46e9SPaul Traina printf(" PROC_UNAVAIL"); 8262ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8272ebf6c05SBill Fenner return (NULL); 8284edb46e9SPaul Traina 8294edb46e9SPaul Traina case GARBAGE_ARGS: 8304edb46e9SPaul Traina printf(" GARBAGE_ARGS"); 8312ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8322ebf6c05SBill Fenner return (NULL); 8334edb46e9SPaul Traina 8344edb46e9SPaul Traina case SYSTEM_ERR: 8354edb46e9SPaul Traina printf(" SYSTEM_ERR"); 8362ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8372ebf6c05SBill Fenner return (NULL); 8384edb46e9SPaul Traina 8394edb46e9SPaul Traina default: 8404edb46e9SPaul Traina printf(" ar_stat %d", astat); 8412ebf6c05SBill Fenner nfserr = 1; /* suppress trunc string */ 8422ebf6c05SBill Fenner return (NULL); 8434edb46e9SPaul Traina } 8444edb46e9SPaul Traina /* successful return */ 8452ebf6c05SBill Fenner if ((sizeof(astat) + ((u_char *)dp)) < snapend) 8464edb46e9SPaul Traina return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); 8474edb46e9SPaul Traina 8482ebf6c05SBill Fenner trunc: 8492ebf6c05SBill Fenner return (NULL); 8504edb46e9SPaul Traina } 8514edb46e9SPaul Traina 8524edb46e9SPaul Traina 8532ebf6c05SBill Fenner #define T2CHECK(p, l) if ((u_char *)(p) > ((u_char *)snapend) - l) return(NULL) 854647f50c3SDoug Rabson 855647f50c3SDoug Rabson static const u_int32_t * 856647f50c3SDoug Rabson parsestatus(const u_int32_t *dp, int *er) 857647f50c3SDoug Rabson { 8582ebf6c05SBill Fenner register int errnum; 859647f50c3SDoug Rabson 8602ebf6c05SBill Fenner TCHECK(dp[0]); 8612ebf6c05SBill Fenner errnum = ntohl(dp[0]); 862647f50c3SDoug Rabson if (er) 8632ebf6c05SBill Fenner *er = errnum; 8642ebf6c05SBill Fenner if (errnum != 0) { 8652ebf6c05SBill Fenner if (!qflag) 8662ebf6c05SBill Fenner printf(" ERROR: %s", pcap_strerror(errnum)); 8672ebf6c05SBill Fenner nfserr = 1; 8682ebf6c05SBill Fenner return (NULL); 8694edb46e9SPaul Traina } 8704edb46e9SPaul Traina return (dp + 1); 8712ebf6c05SBill Fenner trunc: 8722ebf6c05SBill Fenner return (NULL); 8734edb46e9SPaul Traina } 8744edb46e9SPaul Traina 8754edb46e9SPaul Traina static const u_int32_t * 876647f50c3SDoug Rabson parsefattr(const u_int32_t *dp, int verbose, int v3) 8774edb46e9SPaul Traina { 878647f50c3SDoug Rabson const struct nfs_fattr *fap; 8794edb46e9SPaul Traina 880647f50c3SDoug Rabson T2CHECK(dp, 5 * sizeof(*dp)); 881647f50c3SDoug Rabson 882647f50c3SDoug Rabson fap = (const struct nfs_fattr *)dp; 8834edb46e9SPaul Traina if (verbose) { 8842ebf6c05SBill Fenner printf(" %s %lo ids %ld/%ld", 885647f50c3SDoug Rabson tok2str(type2str, "unk-ft %d ", ntohl(fap->fa_type)), 886647f50c3SDoug Rabson ntohl(fap->fa_mode), ntohl(fap->fa_uid), 887647f50c3SDoug Rabson ntohl(fap->fa_gid)); 888647f50c3SDoug Rabson if (v3) { 889647f50c3SDoug Rabson T2CHECK(dp, 7 * sizeof(*dp)); 890647f50c3SDoug Rabson printf(" sz "); 891647f50c3SDoug Rabson print_int64((u_int32_t *)&fap->fa3_size, UNSIGNED); 892647f50c3SDoug Rabson putchar(' '); 893647f50c3SDoug Rabson } 894647f50c3SDoug Rabson else { 895647f50c3SDoug Rabson T2CHECK(dp, 6 * sizeof(*dp)); 8962ebf6c05SBill Fenner printf(" sz %ld ", ntohl(fap->fa2_size)); 897647f50c3SDoug Rabson } 8984edb46e9SPaul Traina } 8994edb46e9SPaul Traina /* print lots more stuff */ 9004edb46e9SPaul Traina if (verbose > 1) { 901647f50c3SDoug Rabson if (v3) { 902647f50c3SDoug Rabson T2CHECK(dp, 64); 9032ebf6c05SBill Fenner printf("nlink %ld rdev %ld/%ld ", 904647f50c3SDoug Rabson ntohl(fap->fa_nlink), 905647f50c3SDoug Rabson ntohl(fap->fa3_rdev.specdata1), 906647f50c3SDoug Rabson ntohl(fap->fa3_rdev.specdata2)); 907647f50c3SDoug Rabson printf("fsid "); 908647f50c3SDoug Rabson print_int64((u_int32_t *)&fap->fa2_fsid, HEX); 909647f50c3SDoug Rabson printf(" nodeid "); 910647f50c3SDoug Rabson print_int64((u_int32_t *)&fap->fa2_fileid, HEX); 9112ebf6c05SBill Fenner printf(" a/m/ctime %lu.%06lu ", 912647f50c3SDoug Rabson ntohl(fap->fa3_atime.nfsv3_sec), 913647f50c3SDoug Rabson ntohl(fap->fa3_atime.nfsv3_nsec)); 9142ebf6c05SBill Fenner printf("%lu.%06lu ", 915647f50c3SDoug Rabson ntohl(fap->fa3_mtime.nfsv3_sec), 916647f50c3SDoug Rabson ntohl(fap->fa3_mtime.nfsv3_nsec)); 9172ebf6c05SBill Fenner printf("%lu.%06lu ", 918647f50c3SDoug Rabson ntohl(fap->fa3_ctime.nfsv3_sec), 919647f50c3SDoug Rabson ntohl(fap->fa3_ctime.nfsv3_nsec)); 920647f50c3SDoug Rabson } else { 921647f50c3SDoug Rabson T2CHECK(dp, 48); 9222ebf6c05SBill Fenner printf("nlink %ld rdev %lx fsid %lx nodeid %lx a/m/ctime ", 923647f50c3SDoug Rabson ntohl(fap->fa_nlink), ntohl(fap->fa2_rdev), 924647f50c3SDoug Rabson ntohl(fap->fa2_fsid), ntohl(fap->fa2_fileid)); 9252ebf6c05SBill Fenner printf("%lu.%06lu ", 926647f50c3SDoug Rabson ntohl(fap->fa2_atime.nfsv2_sec), 927647f50c3SDoug Rabson ntohl(fap->fa2_atime.nfsv2_usec)); 9282ebf6c05SBill Fenner printf("%lu.%06lu ", 929647f50c3SDoug Rabson ntohl(fap->fa2_mtime.nfsv2_sec), 930647f50c3SDoug Rabson ntohl(fap->fa2_mtime.nfsv2_usec)); 9312ebf6c05SBill Fenner printf("%lu.%06lu ", 932647f50c3SDoug Rabson ntohl(fap->fa2_ctime.nfsv2_sec), 933647f50c3SDoug Rabson ntohl(fap->fa2_ctime.nfsv2_usec)); 9344edb46e9SPaul Traina } 935647f50c3SDoug Rabson } 936647f50c3SDoug Rabson return ((const u_int32_t *)((unsigned char *)dp + 937647f50c3SDoug Rabson (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 9384edb46e9SPaul Traina } 9394edb46e9SPaul Traina 9404edb46e9SPaul Traina static int 941647f50c3SDoug Rabson parseattrstat(const u_int32_t *dp, int verbose, int v3) 9424edb46e9SPaul Traina { 943647f50c3SDoug Rabson int er; 944647f50c3SDoug Rabson 945647f50c3SDoug Rabson dp = parsestatus(dp, &er); 946647f50c3SDoug Rabson if (dp == NULL || er) 9474edb46e9SPaul Traina return (0); 9484edb46e9SPaul Traina 9492ebf6c05SBill Fenner return (parsefattr(dp, verbose, v3) != NULL); 9504edb46e9SPaul Traina } 9514edb46e9SPaul Traina 9524edb46e9SPaul Traina static int 9534edb46e9SPaul Traina parsediropres(const u_int32_t *dp) 9544edb46e9SPaul Traina { 955647f50c3SDoug Rabson int er; 956647f50c3SDoug Rabson 9572ebf6c05SBill Fenner dp = parsestatus(dp, &er); 9582ebf6c05SBill Fenner if (dp == NULL || er) 959647f50c3SDoug Rabson return (0); 960647f50c3SDoug Rabson 961647f50c3SDoug Rabson dp = parsefh(dp, 0); 9624edb46e9SPaul Traina if (dp == NULL) 9634edb46e9SPaul Traina return (0); 9644edb46e9SPaul Traina 965647f50c3SDoug Rabson return (parsefattr(dp, vflag, 0) != NULL); 9664edb46e9SPaul Traina } 9674edb46e9SPaul Traina 9684edb46e9SPaul Traina static int 969647f50c3SDoug Rabson parselinkres(const u_int32_t *dp, int v3) 9704edb46e9SPaul Traina { 971647f50c3SDoug Rabson int er; 9724edb46e9SPaul Traina 973647f50c3SDoug Rabson dp = parsestatus(dp, &er); 974647f50c3SDoug Rabson if (dp == NULL || er) 975647f50c3SDoug Rabson return(0); 9762ebf6c05SBill Fenner 9772ebf6c05SBill Fenner if (v3 && ((dp = parse_post_op_attr(dp, vflag)) != NULL)) 978647f50c3SDoug Rabson return (0); 9792ebf6c05SBill Fenner 9804edb46e9SPaul Traina putchar(' '); 9814edb46e9SPaul Traina return (parsefn(dp) != NULL); 9824edb46e9SPaul Traina } 9834edb46e9SPaul Traina 9844edb46e9SPaul Traina static int 985647f50c3SDoug Rabson parsestatfs(const u_int32_t *dp, int v3) 9864edb46e9SPaul Traina { 987647f50c3SDoug Rabson const struct nfs_statfs *sfsp; 988647f50c3SDoug Rabson int er; 9894edb46e9SPaul Traina 990647f50c3SDoug Rabson dp = parsestatus(dp, &er); 991647f50c3SDoug Rabson if (dp == NULL || (!v3 && er)) 9924edb46e9SPaul Traina return(0); 9934edb46e9SPaul Traina 994647f50c3SDoug Rabson if (qflag) 995647f50c3SDoug Rabson return(1); 996647f50c3SDoug Rabson 997647f50c3SDoug Rabson if (v3) { 998647f50c3SDoug Rabson if (vflag) 999647f50c3SDoug Rabson printf(" POST:"); 10002ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1001647f50c3SDoug Rabson return (0); 1002647f50c3SDoug Rabson } 1003647f50c3SDoug Rabson 1004647f50c3SDoug Rabson T2CHECK(dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 1005647f50c3SDoug Rabson 1006647f50c3SDoug Rabson sfsp = (const struct nfs_statfs *)dp; 1007647f50c3SDoug Rabson 1008647f50c3SDoug Rabson if (v3) { 1009647f50c3SDoug Rabson printf(" tbytes "); 1010647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_tbytes, UNSIGNED); 1011647f50c3SDoug Rabson printf(" fbytes "); 1012647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_fbytes, UNSIGNED); 1013647f50c3SDoug Rabson printf(" abytes "); 1014647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_abytes, UNSIGNED); 1015647f50c3SDoug Rabson if (vflag) { 1016647f50c3SDoug Rabson printf(" tfiles "); 1017647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_tfiles, UNSIGNED); 1018647f50c3SDoug Rabson printf(" ffiles "); 1019647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_ffiles, UNSIGNED); 1020647f50c3SDoug Rabson printf(" afiles "); 1021647f50c3SDoug Rabson print_int64((u_int32_t *)&sfsp->sf_afiles, UNSIGNED); 1022647f50c3SDoug Rabson printf(" invar %lu", ntohl(sfsp->sf_invarsec)); 1023647f50c3SDoug Rabson } 1024647f50c3SDoug Rabson } else { 10252ebf6c05SBill Fenner printf(" tsize %ld bsize %ld blocks %ld bfree %ld bavail %ld", 1026647f50c3SDoug Rabson ntohl(sfsp->sf_tsize), ntohl(sfsp->sf_bsize), 1027647f50c3SDoug Rabson ntohl(sfsp->sf_blocks), ntohl(sfsp->sf_bfree), 1028647f50c3SDoug Rabson ntohl(sfsp->sf_bavail)); 10294edb46e9SPaul Traina } 10304edb46e9SPaul Traina 10314edb46e9SPaul Traina return (1); 10324edb46e9SPaul Traina } 10334edb46e9SPaul Traina 10344edb46e9SPaul Traina static int 10354edb46e9SPaul Traina parserddires(const u_int32_t *dp) 10364edb46e9SPaul Traina { 1037647f50c3SDoug Rabson int er; 1038647f50c3SDoug Rabson 1039647f50c3SDoug Rabson dp = parsestatus(dp, &er); 10402ebf6c05SBill Fenner if (dp == NULL || er) 10414edb46e9SPaul Traina return (0); 1042647f50c3SDoug Rabson if (qflag) 1043647f50c3SDoug Rabson return (1); 1044647f50c3SDoug Rabson 1045647f50c3SDoug Rabson T2CHECK(dp, 12); 10462ebf6c05SBill Fenner printf(" offset %lx size %ld ", ntohl(dp[0]), ntohl(dp[1])); 10474edb46e9SPaul Traina if (dp[2] != 0) 10484edb46e9SPaul Traina printf("eof"); 10494edb46e9SPaul Traina 10504edb46e9SPaul Traina return (1); 1051647f50c3SDoug Rabson } 1052647f50c3SDoug Rabson 1053647f50c3SDoug Rabson static const u_int32_t * 1054647f50c3SDoug Rabson parse_wcc_attr(const u_int32_t *dp) 1055647f50c3SDoug Rabson { 1056647f50c3SDoug Rabson printf(" sz "); 1057647f50c3SDoug Rabson print_int64(dp, UNSIGNED); 10582ebf6c05SBill Fenner printf(" mtime %lu.%06lu ctime %lu.%06lu", ntohl(dp[2]), ntohl(dp[3]), 1059647f50c3SDoug Rabson ntohl(dp[4]), ntohl(dp[5])); 1060647f50c3SDoug Rabson return (dp + 6); 1061647f50c3SDoug Rabson } 1062647f50c3SDoug Rabson 1063647f50c3SDoug Rabson /* 1064647f50c3SDoug Rabson * Pre operation attributes. Print only if vflag > 1. 1065647f50c3SDoug Rabson */ 1066647f50c3SDoug Rabson static const u_int32_t * 1067647f50c3SDoug Rabson parse_pre_op_attr(const u_int32_t *dp, int verbose) 1068647f50c3SDoug Rabson { 1069647f50c3SDoug Rabson T2CHECK(dp, 4); 1070647f50c3SDoug Rabson if (!ntohl(dp[0])) 1071647f50c3SDoug Rabson return (dp + 1); 1072647f50c3SDoug Rabson dp++; 1073647f50c3SDoug Rabson T2CHECK(dp, 24); 1074647f50c3SDoug Rabson if (verbose > 1) { 1075647f50c3SDoug Rabson return parse_wcc_attr(dp); 1076647f50c3SDoug Rabson } else { 1077647f50c3SDoug Rabson /* If not verbose enough, just skip over wcc_attr */ 1078647f50c3SDoug Rabson return (dp + 6); 1079647f50c3SDoug Rabson } 1080647f50c3SDoug Rabson } 1081647f50c3SDoug Rabson 1082647f50c3SDoug Rabson /* 1083647f50c3SDoug Rabson * Post operation attributes are printed if vflag >= 1 1084647f50c3SDoug Rabson */ 1085647f50c3SDoug Rabson static const u_int32_t * 1086647f50c3SDoug Rabson parse_post_op_attr(const u_int32_t *dp, int verbose) 1087647f50c3SDoug Rabson { 1088647f50c3SDoug Rabson T2CHECK(dp, 4); 1089647f50c3SDoug Rabson if (!ntohl(dp[0])) 1090647f50c3SDoug Rabson return (dp + 1); 1091647f50c3SDoug Rabson dp++; 1092647f50c3SDoug Rabson if (verbose) { 1093647f50c3SDoug Rabson return parsefattr(dp, verbose, 1); 1094647f50c3SDoug Rabson } else 1095647f50c3SDoug Rabson return (dp + (NFSX_V3FATTR / sizeof (u_int32_t))); 1096647f50c3SDoug Rabson } 1097647f50c3SDoug Rabson 1098647f50c3SDoug Rabson static const u_int32_t * 1099647f50c3SDoug Rabson parse_wcc_data(const u_int32_t *dp, int verbose) 1100647f50c3SDoug Rabson { 1101647f50c3SDoug Rabson if (verbose > 1) 1102647f50c3SDoug Rabson printf(" PRE:"); 11032ebf6c05SBill Fenner if ((dp = parse_pre_op_attr(dp, verbose)) == NULL) 11042ebf6c05SBill Fenner return (NULL); 1105647f50c3SDoug Rabson 1106647f50c3SDoug Rabson if (verbose) 1107647f50c3SDoug Rabson printf(" POST:"); 1108647f50c3SDoug Rabson return parse_post_op_attr(dp, verbose); 1109647f50c3SDoug Rabson } 1110647f50c3SDoug Rabson 1111647f50c3SDoug Rabson static const u_int32_t * 1112647f50c3SDoug Rabson parsecreateopres(const u_int32_t *dp, int verbose) 1113647f50c3SDoug Rabson { 1114647f50c3SDoug Rabson int er; 1115647f50c3SDoug Rabson 11162ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 11172ebf6c05SBill Fenner return (NULL); 1118647f50c3SDoug Rabson if (er) 1119647f50c3SDoug Rabson dp = parse_wcc_data(dp, verbose); 1120647f50c3SDoug Rabson else { 1121647f50c3SDoug Rabson T2CHECK(dp, 4); 1122647f50c3SDoug Rabson if (!ntohl(dp[0])) 1123647f50c3SDoug Rabson return (dp + 1); 1124647f50c3SDoug Rabson dp++; 11252ebf6c05SBill Fenner if ((dp = parsefh(dp, 1)) == NULL) 11262ebf6c05SBill Fenner return (NULL); 1127647f50c3SDoug Rabson if (verbose) { 11282ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, verbose)) == NULL) 11292ebf6c05SBill Fenner return (NULL); 1130647f50c3SDoug Rabson if (vflag > 1) { 1131647f50c3SDoug Rabson printf("dir attr:"); 1132647f50c3SDoug Rabson dp = parse_wcc_data(dp, verbose); 1133647f50c3SDoug Rabson } 1134647f50c3SDoug Rabson } 1135647f50c3SDoug Rabson } 1136647f50c3SDoug Rabson return (dp); 1137647f50c3SDoug Rabson } 1138647f50c3SDoug Rabson 1139647f50c3SDoug Rabson static int 1140647f50c3SDoug Rabson parsewccres(const u_int32_t *dp, int verbose) 1141647f50c3SDoug Rabson { 1142647f50c3SDoug Rabson int er; 1143647f50c3SDoug Rabson 11442ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1145647f50c3SDoug Rabson return (0); 11462ebf6c05SBill Fenner return parse_wcc_data(dp, verbose) != NULL; 1147647f50c3SDoug Rabson } 1148647f50c3SDoug Rabson 1149647f50c3SDoug Rabson static const u_int32_t * 1150647f50c3SDoug Rabson parsev3rddirres(const u_int32_t *dp, int verbose) 1151647f50c3SDoug Rabson { 1152647f50c3SDoug Rabson int er; 1153647f50c3SDoug Rabson 11542ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 11552ebf6c05SBill Fenner return (NULL); 1156647f50c3SDoug Rabson if (vflag) 1157647f50c3SDoug Rabson printf(" POST:"); 11582ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, verbose)) == NULL) 11592ebf6c05SBill Fenner return (NULL); 1160647f50c3SDoug Rabson if (er) 1161647f50c3SDoug Rabson return dp; 1162647f50c3SDoug Rabson if (vflag) { 1163647f50c3SDoug Rabson T2CHECK(dp, 8); 11642ebf6c05SBill Fenner printf(" verf %08x%08x", dp[0], dp[1]); 1165647f50c3SDoug Rabson dp += 2; 1166647f50c3SDoug Rabson } 1167647f50c3SDoug Rabson return dp; 1168647f50c3SDoug Rabson } 1169647f50c3SDoug Rabson 1170647f50c3SDoug Rabson static int 1171647f50c3SDoug Rabson parsefsinfo(const u_int32_t *dp) 1172647f50c3SDoug Rabson { 1173647f50c3SDoug Rabson struct nfsv3_fsinfo *sfp; 1174647f50c3SDoug Rabson int er; 1175647f50c3SDoug Rabson 11762ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1177647f50c3SDoug Rabson return (0); 1178647f50c3SDoug Rabson if (vflag) 1179647f50c3SDoug Rabson printf(" POST:"); 11802ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1181647f50c3SDoug Rabson return (0); 1182647f50c3SDoug Rabson if (er) 1183647f50c3SDoug Rabson return (1); 1184647f50c3SDoug Rabson 1185647f50c3SDoug Rabson T2CHECK(dp, sizeof (struct nfsv3_fsinfo)); 1186647f50c3SDoug Rabson 1187647f50c3SDoug Rabson sfp = (struct nfsv3_fsinfo *)dp; 1188647f50c3SDoug Rabson printf(" rtmax %lu rtpref %lu wtmax %lu wtpref %lu dtpref %lu", 1189647f50c3SDoug Rabson ntohl(sfp->fs_rtmax), ntohl(sfp->fs_rtpref), 1190647f50c3SDoug Rabson ntohl(sfp->fs_wtmax), ntohl(sfp->fs_wtpref), 1191647f50c3SDoug Rabson ntohl(sfp->fs_dtpref)); 1192647f50c3SDoug Rabson if (vflag) { 1193647f50c3SDoug Rabson printf(" rtmult %lu wtmult %lu maxfsz ", 1194647f50c3SDoug Rabson ntohl(sfp->fs_rtmult), ntohl(sfp->fs_wtmult)); 1195647f50c3SDoug Rabson print_int64((u_int32_t *)&sfp->fs_maxfilesize, UNSIGNED); 11962ebf6c05SBill Fenner printf(" delta %lu.%06lu ", ntohl(sfp->fs_timedelta.nfsv3_sec), 1197647f50c3SDoug Rabson ntohl(sfp->fs_timedelta.nfsv3_nsec)); 1198647f50c3SDoug Rabson } 1199647f50c3SDoug Rabson return (1); 1200647f50c3SDoug Rabson } 1201647f50c3SDoug Rabson 1202647f50c3SDoug Rabson static int 1203647f50c3SDoug Rabson parsepathconf(const u_int32_t *dp) 1204647f50c3SDoug Rabson { 1205647f50c3SDoug Rabson int er; 1206647f50c3SDoug Rabson struct nfsv3_pathconf *spp; 1207647f50c3SDoug Rabson 12082ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1209647f50c3SDoug Rabson return (0); 1210647f50c3SDoug Rabson if (vflag) 1211647f50c3SDoug Rabson printf(" POST:"); 12122ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1213647f50c3SDoug Rabson return (0); 1214647f50c3SDoug Rabson if (er) 1215647f50c3SDoug Rabson return (1); 1216647f50c3SDoug Rabson 1217647f50c3SDoug Rabson T2CHECK(dp, sizeof (struct nfsv3_pathconf)); 1218647f50c3SDoug Rabson 1219647f50c3SDoug Rabson spp = (struct nfsv3_pathconf *)dp; 1220647f50c3SDoug Rabson 1221647f50c3SDoug Rabson printf(" linkmax %lu namemax %lu %s %s %s %s", 1222647f50c3SDoug Rabson ntohl(spp->pc_linkmax), 1223647f50c3SDoug Rabson ntohl(spp->pc_namemax), 1224647f50c3SDoug Rabson ntohl(spp->pc_notrunc) ? "notrunc" : "", 1225647f50c3SDoug Rabson ntohl(spp->pc_chownrestricted) ? "chownres" : "", 1226647f50c3SDoug Rabson ntohl(spp->pc_caseinsensitive) ? "igncase" : "", 1227647f50c3SDoug Rabson ntohl(spp->pc_casepreserving) ? "keepcase" : ""); 12284edb46e9SPaul Traina return (0); 12294edb46e9SPaul Traina } 12304edb46e9SPaul Traina 12314edb46e9SPaul Traina static void 1232647f50c3SDoug Rabson interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int32_t vers, int length) 12334edb46e9SPaul Traina { 12344edb46e9SPaul Traina register const u_int32_t *dp; 1235647f50c3SDoug Rabson register int v3; 12362ebf6c05SBill Fenner 1237647f50c3SDoug Rabson int er; 1238647f50c3SDoug Rabson 1239647f50c3SDoug Rabson v3 = (vers == NFS_VER3); 1240647f50c3SDoug Rabson 1241647f50c3SDoug Rabson if (!v3 && proc < NFS_NPROCS) 1242647f50c3SDoug Rabson proc = nfsv3_procid[proc]; 12434edb46e9SPaul Traina 12444edb46e9SPaul Traina switch (proc) { 12454edb46e9SPaul Traina 12464edb46e9SPaul Traina case NFSPROC_NOOP: 12474edb46e9SPaul Traina printf(" nop"); 12484edb46e9SPaul Traina return; 1249647f50c3SDoug Rabson 12504edb46e9SPaul Traina case NFSPROC_NULL: 12514edb46e9SPaul Traina printf(" null"); 12524edb46e9SPaul Traina return; 12534edb46e9SPaul Traina 12544edb46e9SPaul Traina case NFSPROC_GETATTR: 12554edb46e9SPaul Traina printf(" getattr"); 12564edb46e9SPaul Traina dp = parserep(rp, length); 12572ebf6c05SBill Fenner if (dp != NULL && parseattrstat(dp, !qflag, v3) != 0) 12584edb46e9SPaul Traina return; 12594edb46e9SPaul Traina break; 12604edb46e9SPaul Traina 12614edb46e9SPaul Traina case NFSPROC_SETATTR: 12624edb46e9SPaul Traina printf(" setattr"); 12632ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 12644edb46e9SPaul Traina return; 1265647f50c3SDoug Rabson if (v3) { 12662ebf6c05SBill Fenner if (parsewccres(dp, vflag) != 0) 1267647f50c3SDoug Rabson return; 1268647f50c3SDoug Rabson } else { 1269647f50c3SDoug Rabson if (parseattrstat(dp, !qflag, 0) != 0) 1270647f50c3SDoug Rabson return; 1271647f50c3SDoug Rabson } 12724edb46e9SPaul Traina break; 12734edb46e9SPaul Traina 12744edb46e9SPaul Traina case NFSPROC_LOOKUP: 12754edb46e9SPaul Traina printf(" lookup"); 12762ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 12774edb46e9SPaul Traina break; 1278647f50c3SDoug Rabson if (v3) { 12792ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1280647f50c3SDoug Rabson break; 1281647f50c3SDoug Rabson if (er) { 1282647f50c3SDoug Rabson if (vflag > 1) { 1283647f50c3SDoug Rabson printf(" post dattr:"); 1284647f50c3SDoug Rabson dp = parse_post_op_attr(dp, vflag); 1285647f50c3SDoug Rabson } 1286647f50c3SDoug Rabson } else { 12872ebf6c05SBill Fenner if ((dp = parsefh(dp, v3)) == NULL) 1288647f50c3SDoug Rabson break; 12892ebf6c05SBill Fenner if (((dp = parse_post_op_attr(dp, vflag)) != NULL) && 12902ebf6c05SBill Fenner (vflag > 1)) { 1291647f50c3SDoug Rabson printf(" post dattr:"); 1292647f50c3SDoug Rabson dp = parse_post_op_attr(dp, vflag); 1293647f50c3SDoug Rabson } 1294647f50c3SDoug Rabson } 12952ebf6c05SBill Fenner if (dp != NULL) 1296647f50c3SDoug Rabson return; 1297647f50c3SDoug Rabson } else { 1298647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1299647f50c3SDoug Rabson return; 1300647f50c3SDoug Rabson } 1301647f50c3SDoug Rabson break; 1302647f50c3SDoug Rabson 1303647f50c3SDoug Rabson case NFSPROC_ACCESS: 1304647f50c3SDoug Rabson printf(" access"); 1305647f50c3SDoug Rabson dp = parserep(rp, length); 13062ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1307647f50c3SDoug Rabson break; 1308647f50c3SDoug Rabson if (vflag) 1309647f50c3SDoug Rabson printf(" attr:"); 13102ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1311647f50c3SDoug Rabson break; 1312647f50c3SDoug Rabson if (!er) 13132ebf6c05SBill Fenner printf(" c %04lx", ntohl(dp[0])); 1314647f50c3SDoug Rabson return; 13154edb46e9SPaul Traina 13164edb46e9SPaul Traina case NFSPROC_READLINK: 13174edb46e9SPaul Traina printf(" readlink"); 13184edb46e9SPaul Traina dp = parserep(rp, length); 13192ebf6c05SBill Fenner if (dp != NULL && parselinkres(dp, v3) != 0) 13204edb46e9SPaul Traina return; 13214edb46e9SPaul Traina break; 13224edb46e9SPaul Traina 13234edb46e9SPaul Traina case NFSPROC_READ: 13244edb46e9SPaul Traina printf(" read"); 13252ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1326647f50c3SDoug Rabson break; 1327647f50c3SDoug Rabson if (v3) { 13282ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1329647f50c3SDoug Rabson break; 13302ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1331647f50c3SDoug Rabson break; 1332647f50c3SDoug Rabson if (er) 13334edb46e9SPaul Traina return; 1334647f50c3SDoug Rabson if (vflag) { 1335647f50c3SDoug Rabson TCHECK2(*dp, 8); 1336647f50c3SDoug Rabson printf("%lu bytes", ntohl(dp[0])); 1337647f50c3SDoug Rabson if (ntohl(dp[1])) 1338647f50c3SDoug Rabson printf(" EOF"); 1339647f50c3SDoug Rabson } 1340647f50c3SDoug Rabson return; 1341647f50c3SDoug Rabson } else { 1342647f50c3SDoug Rabson if (parseattrstat(dp, vflag, 0) != 0) 1343647f50c3SDoug Rabson return; 1344647f50c3SDoug Rabson } 13454edb46e9SPaul Traina break; 13464edb46e9SPaul Traina 13474edb46e9SPaul Traina case NFSPROC_WRITE: 13484edb46e9SPaul Traina printf(" write"); 13492ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1350647f50c3SDoug Rabson break; 1351647f50c3SDoug Rabson if (v3) { 13522ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1353647f50c3SDoug Rabson break; 13542ebf6c05SBill Fenner if ((dp = parse_wcc_data(dp, vflag)) == NULL) 1355647f50c3SDoug Rabson break; 1356647f50c3SDoug Rabson if (er) 13574edb46e9SPaul Traina return; 1358647f50c3SDoug Rabson if (vflag) { 1359647f50c3SDoug Rabson TCHECK2(*dp, 4); 1360647f50c3SDoug Rabson printf("%lu bytes", ntohl(dp[0])); 1361647f50c3SDoug Rabson if (vflag > 1) { 1362647f50c3SDoug Rabson TCHECK2(*dp, 4); 1363647f50c3SDoug Rabson printf(" <%s>", 1364647f50c3SDoug Rabson nfsv3_writemodes[ntohl(dp[1])]); 1365647f50c3SDoug Rabson } 1366647f50c3SDoug Rabson return; 1367647f50c3SDoug Rabson } 1368647f50c3SDoug Rabson } else { 1369647f50c3SDoug Rabson if (parseattrstat(dp, vflag, v3) != 0) 1370647f50c3SDoug Rabson return; 1371647f50c3SDoug Rabson } 13724edb46e9SPaul Traina break; 13734edb46e9SPaul Traina 13744edb46e9SPaul Traina case NFSPROC_CREATE: 13754edb46e9SPaul Traina printf(" create"); 13762ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1377647f50c3SDoug Rabson break; 1378647f50c3SDoug Rabson if (v3) { 13792ebf6c05SBill Fenner if (parsecreateopres(dp, vflag) != NULL) 1380647f50c3SDoug Rabson return; 1381647f50c3SDoug Rabson } else { 1382647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1383647f50c3SDoug Rabson return; 1384647f50c3SDoug Rabson } 1385647f50c3SDoug Rabson break; 1386647f50c3SDoug Rabson 1387647f50c3SDoug Rabson case NFSPROC_MKDIR: 1388647f50c3SDoug Rabson printf(" mkdir"); 13892ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1390647f50c3SDoug Rabson break; 1391647f50c3SDoug Rabson if (v3) { 13922ebf6c05SBill Fenner if (parsecreateopres(dp, vflag) != NULL) 1393647f50c3SDoug Rabson return; 1394647f50c3SDoug Rabson } else { 1395647f50c3SDoug Rabson if (parsediropres(dp) != 0) 1396647f50c3SDoug Rabson return; 1397647f50c3SDoug Rabson } 1398647f50c3SDoug Rabson break; 1399647f50c3SDoug Rabson 1400647f50c3SDoug Rabson case NFSPROC_SYMLINK: 1401647f50c3SDoug Rabson printf(" symlink"); 14022ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1403647f50c3SDoug Rabson break; 1404647f50c3SDoug Rabson if (v3) { 14052ebf6c05SBill Fenner if (parsecreateopres(dp, vflag) != NULL) 1406647f50c3SDoug Rabson return; 1407647f50c3SDoug Rabson } else { 14082ebf6c05SBill Fenner if (parsestatus(dp, &er) != NULL) 1409647f50c3SDoug Rabson return; 1410647f50c3SDoug Rabson } 1411647f50c3SDoug Rabson break; 1412647f50c3SDoug Rabson 1413647f50c3SDoug Rabson case NFSPROC_MKNOD: 1414647f50c3SDoug Rabson printf(" mknod"); 14152ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1416647f50c3SDoug Rabson break; 14172ebf6c05SBill Fenner if (parsecreateopres(dp, vflag) != NULL) 14184edb46e9SPaul Traina return; 14194edb46e9SPaul Traina break; 14204edb46e9SPaul Traina 14214edb46e9SPaul Traina case NFSPROC_REMOVE: 14224edb46e9SPaul Traina printf(" remove"); 14232ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 14244edb46e9SPaul Traina break; 1425647f50c3SDoug Rabson if (v3) { 14262ebf6c05SBill Fenner if (parsewccres(dp, vflag) != 0) 14274edb46e9SPaul Traina return; 1428647f50c3SDoug Rabson } else { 14292ebf6c05SBill Fenner if (parsestatus(dp, &er) != NULL) 14304edb46e9SPaul Traina return; 1431647f50c3SDoug Rabson } 14324edb46e9SPaul Traina break; 14334edb46e9SPaul Traina 14344edb46e9SPaul Traina case NFSPROC_RMDIR: 14354edb46e9SPaul Traina printf(" rmdir"); 14362ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1437647f50c3SDoug Rabson break; 1438647f50c3SDoug Rabson if (v3) { 14392ebf6c05SBill Fenner if (parsewccres(dp, vflag) != 0) 14404edb46e9SPaul Traina return; 1441647f50c3SDoug Rabson } else { 14422ebf6c05SBill Fenner if (parsestatus(dp, &er) != NULL) 1443647f50c3SDoug Rabson return; 1444647f50c3SDoug Rabson } 1445647f50c3SDoug Rabson break; 1446647f50c3SDoug Rabson 1447647f50c3SDoug Rabson case NFSPROC_RENAME: 1448647f50c3SDoug Rabson printf(" rename"); 14492ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1450647f50c3SDoug Rabson break; 1451647f50c3SDoug Rabson if (v3) { 14522ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1453647f50c3SDoug Rabson break; 1454647f50c3SDoug Rabson if (vflag) { 1455647f50c3SDoug Rabson printf(" from:"); 14562ebf6c05SBill Fenner if ((dp = parse_wcc_data(dp, vflag)) == NULL) 1457647f50c3SDoug Rabson break; 1458647f50c3SDoug Rabson printf(" to:"); 14592ebf6c05SBill Fenner if ((dp = parse_wcc_data(dp, vflag)) == NULL) 1460647f50c3SDoug Rabson break; 1461647f50c3SDoug Rabson } 1462647f50c3SDoug Rabson return; 1463647f50c3SDoug Rabson } else { 14642ebf6c05SBill Fenner if (parsestatus(dp, &er) != NULL) 1465647f50c3SDoug Rabson return; 1466647f50c3SDoug Rabson } 1467647f50c3SDoug Rabson break; 1468647f50c3SDoug Rabson 1469647f50c3SDoug Rabson case NFSPROC_LINK: 1470647f50c3SDoug Rabson printf(" link"); 14712ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1472647f50c3SDoug Rabson break; 1473647f50c3SDoug Rabson if (v3) { 14742ebf6c05SBill Fenner if ((dp = parsestatus(dp, &er)) == NULL) 1475647f50c3SDoug Rabson break; 1476647f50c3SDoug Rabson if (vflag) { 1477647f50c3SDoug Rabson printf(" file POST:"); 14782ebf6c05SBill Fenner if ((dp = parse_post_op_attr(dp, vflag)) == NULL) 1479647f50c3SDoug Rabson break; 1480647f50c3SDoug Rabson printf(" dir:"); 14812ebf6c05SBill Fenner if ((dp = parse_wcc_data(dp, vflag)) == NULL) 1482647f50c3SDoug Rabson break; 1483647f50c3SDoug Rabson return; 1484647f50c3SDoug Rabson } 1485647f50c3SDoug Rabson } else { 14862ebf6c05SBill Fenner if (parsestatus(dp, &er) != NULL) 1487647f50c3SDoug Rabson return; 1488647f50c3SDoug Rabson } 14894edb46e9SPaul Traina break; 14904edb46e9SPaul Traina 14914edb46e9SPaul Traina case NFSPROC_READDIR: 14924edb46e9SPaul Traina printf(" readdir"); 14932ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1494647f50c3SDoug Rabson break; 1495647f50c3SDoug Rabson if (v3) { 14962ebf6c05SBill Fenner if (parsev3rddirres(dp, vflag) != NULL) 1497647f50c3SDoug Rabson return; 1498647f50c3SDoug Rabson } else { 1499647f50c3SDoug Rabson if (parserddires(dp) != 0) 1500647f50c3SDoug Rabson return; 1501647f50c3SDoug Rabson } 1502647f50c3SDoug Rabson break; 1503647f50c3SDoug Rabson 1504647f50c3SDoug Rabson case NFSPROC_READDIRPLUS: 1505647f50c3SDoug Rabson printf(" readdirplus"); 15062ebf6c05SBill Fenner if ((dp = parserep(rp, length)) == NULL) 1507647f50c3SDoug Rabson break; 15082ebf6c05SBill Fenner if (parsev3rddirres(dp, vflag) != NULL) 15094edb46e9SPaul Traina return; 15104edb46e9SPaul Traina break; 15114edb46e9SPaul Traina 1512647f50c3SDoug Rabson case NFSPROC_FSSTAT: 1513647f50c3SDoug Rabson printf(" fsstat"); 15144edb46e9SPaul Traina dp = parserep(rp, length); 15152ebf6c05SBill Fenner if (dp != NULL && parsestatfs(dp, v3) != NULL) 1516647f50c3SDoug Rabson return; 1517647f50c3SDoug Rabson break; 1518647f50c3SDoug Rabson 1519647f50c3SDoug Rabson case NFSPROC_FSINFO: 1520647f50c3SDoug Rabson printf(" fsinfo"); 1521647f50c3SDoug Rabson dp = parserep(rp, length); 15222ebf6c05SBill Fenner if (dp != NULL && parsefsinfo(dp) != NULL) 1523647f50c3SDoug Rabson return; 1524647f50c3SDoug Rabson break; 1525647f50c3SDoug Rabson 1526647f50c3SDoug Rabson case NFSPROC_PATHCONF: 1527647f50c3SDoug Rabson printf(" pathconf"); 1528647f50c3SDoug Rabson dp = parserep(rp, length); 15292ebf6c05SBill Fenner if (dp != NULL && parsepathconf(dp) != 0) 1530647f50c3SDoug Rabson return; 1531647f50c3SDoug Rabson break; 1532647f50c3SDoug Rabson 1533647f50c3SDoug Rabson case NFSPROC_COMMIT: 1534647f50c3SDoug Rabson printf(" commit"); 1535647f50c3SDoug Rabson dp = parserep(rp, length); 15362ebf6c05SBill Fenner if (dp != NULL && parsewccres(dp, vflag) != 0) 15374edb46e9SPaul Traina return; 15384edb46e9SPaul Traina break; 15394edb46e9SPaul Traina 15404edb46e9SPaul Traina default: 15412ebf6c05SBill Fenner printf(" proc-%u", proc); 15424edb46e9SPaul Traina return; 15434edb46e9SPaul Traina } 1544647f50c3SDoug Rabson 1545647f50c3SDoug Rabson trunc: 15462ebf6c05SBill Fenner if (!nfserr) 15474edb46e9SPaul Traina fputs(" [|nfs]", stdout); 15484edb46e9SPaul Traina } 1549