print-nfs.c revision 276788
117680Spst/* 239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2075118Sfenner * 2175118Sfenner * $FreeBSD: head/contrib/tcpdump/print-nfs.c 276788 2015-01-07 19:55:18Z delphij $ 2217680Spst */ 2317680Spst 24276788Sdelphij#define NETDISSECT_REWORKED 2575118Sfenner#ifdef HAVE_CONFIG_H 2675118Sfenner#include "config.h" 2775118Sfenner#endif 2875118Sfenner 29127675Sbms#include <tcpdump-stdinc.h> 3017680Spst 3117680Spst#include <stdio.h> 3217680Spst#include <string.h> 3317680Spst 3417680Spst#include "interface.h" 3517680Spst#include "addrtoname.h" 36127675Sbms#include "extract.h" 3717680Spst 3818976Sdfr#include "nfs.h" 3917680Spst#include "nfsfh.h" 4017680Spst 4175118Sfenner#include "ip.h" 4275118Sfenner#ifdef INET6 4375118Sfenner#include "ip6.h" 4475118Sfenner#endif 45146778Ssam#include "rpc_auth.h" 46146778Ssam#include "rpc_msg.h" 4775118Sfenner 48276788Sdelphijstatic const char tstr[] = " [|nfs]"; 4917680Spst 50276788Sdelphijstatic void nfs_printfh(netdissect_options *, const uint32_t *, const u_int); 51276788Sdelphijstatic int xid_map_enter(netdissect_options *, const struct sunrpc_msg *, const u_char *); 52276788Sdelphijstatic int xid_map_find(const struct sunrpc_msg *, const u_char *, 53276788Sdelphij uint32_t *, uint32_t *); 54276788Sdelphijstatic void interp_reply(netdissect_options *, const struct sunrpc_msg *, uint32_t, uint32_t, int); 55276788Sdelphijstatic const uint32_t *parse_post_op_attr(netdissect_options *, const uint32_t *, int); 56276788Sdelphij 5718976Sdfr/* 5818976Sdfr * Mapping of old NFS Version 2 RPC numbers to generic numbers. 5918976Sdfr */ 60276788Sdelphijuint32_t nfsv3_procid[NFS_NPROCS] = { 6118976Sdfr NFSPROC_NULL, 6218976Sdfr NFSPROC_GETATTR, 6318976Sdfr NFSPROC_SETATTR, 6418976Sdfr NFSPROC_NOOP, 6518976Sdfr NFSPROC_LOOKUP, 6618976Sdfr NFSPROC_READLINK, 6718976Sdfr NFSPROC_READ, 6818976Sdfr NFSPROC_NOOP, 6918976Sdfr NFSPROC_WRITE, 7018976Sdfr NFSPROC_CREATE, 7118976Sdfr NFSPROC_REMOVE, 7218976Sdfr NFSPROC_RENAME, 7318976Sdfr NFSPROC_LINK, 7418976Sdfr NFSPROC_SYMLINK, 7518976Sdfr NFSPROC_MKDIR, 7618976Sdfr NFSPROC_RMDIR, 7718976Sdfr NFSPROC_READDIR, 7818976Sdfr NFSPROC_FSSTAT, 7918976Sdfr NFSPROC_NOOP, 8018976Sdfr NFSPROC_NOOP, 8118976Sdfr NFSPROC_NOOP, 8218976Sdfr NFSPROC_NOOP, 8318976Sdfr NFSPROC_NOOP, 8418976Sdfr NFSPROC_NOOP, 8518976Sdfr NFSPROC_NOOP, 8618976Sdfr NFSPROC_NOOP 8718976Sdfr}; 8818976Sdfr 89276788Sdelphijstatic const struct tok nfsproc_str[] = { 90276788Sdelphij { NFSPROC_NOOP, "nop" }, 91276788Sdelphij { NFSPROC_NULL, "null" }, 92276788Sdelphij { NFSPROC_GETATTR, "getattr" }, 93276788Sdelphij { NFSPROC_SETATTR, "setattr" }, 94276788Sdelphij { NFSPROC_LOOKUP, "lookup" }, 95276788Sdelphij { NFSPROC_ACCESS, "access" }, 96276788Sdelphij { NFSPROC_READLINK, "readlink" }, 97276788Sdelphij { NFSPROC_READ, "read" }, 98276788Sdelphij { NFSPROC_WRITE, "write" }, 99276788Sdelphij { NFSPROC_CREATE, "create" }, 100276788Sdelphij { NFSPROC_MKDIR, "mkdir" }, 101276788Sdelphij { NFSPROC_SYMLINK, "symlink" }, 102276788Sdelphij { NFSPROC_MKNOD, "mknod" }, 103276788Sdelphij { NFSPROC_REMOVE, "remove" }, 104276788Sdelphij { NFSPROC_RMDIR, "rmdir" }, 105276788Sdelphij { NFSPROC_RENAME, "rename" }, 106276788Sdelphij { NFSPROC_LINK, "link" }, 107276788Sdelphij { NFSPROC_READDIR, "readdir" }, 108276788Sdelphij { NFSPROC_READDIRPLUS, "readdirplus" }, 109276788Sdelphij { NFSPROC_FSSTAT, "fsstat" }, 110276788Sdelphij { NFSPROC_FSINFO, "fsinfo" }, 111276788Sdelphij { NFSPROC_PATHCONF, "pathconf" }, 112276788Sdelphij { NFSPROC_COMMIT, "commit" }, 113276788Sdelphij { 0, NULL } 114276788Sdelphij}; 115276788Sdelphij 11675118Sfenner/* 11775118Sfenner * NFS V2 and V3 status values. 11875118Sfenner * 11975118Sfenner * Some of these come from the RFCs for NFS V2 and V3, with the message 12075118Sfenner * strings taken from the FreeBSD C library "errlst.c". 12175118Sfenner * 12275118Sfenner * Others are errors that are not in the RFC but that I suspect some 12375118Sfenner * NFS servers could return; the values are FreeBSD errno values, as 12475118Sfenner * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS 12575118Sfenner * was primarily BSD-derived. 12675118Sfenner */ 127276788Sdelphijstatic const struct tok status2str[] = { 12875118Sfenner { 1, "Operation not permitted" }, /* EPERM */ 12975118Sfenner { 2, "No such file or directory" }, /* ENOENT */ 13075118Sfenner { 5, "Input/output error" }, /* EIO */ 13175118Sfenner { 6, "Device not configured" }, /* ENXIO */ 13275118Sfenner { 11, "Resource deadlock avoided" }, /* EDEADLK */ 13375118Sfenner { 12, "Cannot allocate memory" }, /* ENOMEM */ 13475118Sfenner { 13, "Permission denied" }, /* EACCES */ 13575118Sfenner { 17, "File exists" }, /* EEXIST */ 13675118Sfenner { 18, "Cross-device link" }, /* EXDEV */ 13775118Sfenner { 19, "Operation not supported by device" }, /* ENODEV */ 13875118Sfenner { 20, "Not a directory" }, /* ENOTDIR */ 13975118Sfenner { 21, "Is a directory" }, /* EISDIR */ 14075118Sfenner { 22, "Invalid argument" }, /* EINVAL */ 14175118Sfenner { 26, "Text file busy" }, /* ETXTBSY */ 14275118Sfenner { 27, "File too large" }, /* EFBIG */ 14375118Sfenner { 28, "No space left on device" }, /* ENOSPC */ 14475118Sfenner { 30, "Read-only file system" }, /* EROFS */ 14575118Sfenner { 31, "Too many links" }, /* EMLINK */ 14675118Sfenner { 45, "Operation not supported" }, /* EOPNOTSUPP */ 14775118Sfenner { 62, "Too many levels of symbolic links" }, /* ELOOP */ 14875118Sfenner { 63, "File name too long" }, /* ENAMETOOLONG */ 14975118Sfenner { 66, "Directory not empty" }, /* ENOTEMPTY */ 15075118Sfenner { 69, "Disc quota exceeded" }, /* EDQUOT */ 15175118Sfenner { 70, "Stale NFS file handle" }, /* ESTALE */ 15275118Sfenner { 71, "Too many levels of remote in path" }, /* EREMOTE */ 15375118Sfenner { 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */ 15475118Sfenner { 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */ 15575118Sfenner { 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */ 15675118Sfenner { 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */ 15775118Sfenner { 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */ 15875118Sfenner { 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */ 15975118Sfenner { 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */ 16075118Sfenner { 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */ 16175118Sfenner { 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */ 16275118Sfenner { 0, NULL } 16318976Sdfr}; 16418976Sdfr 165276788Sdelphijstatic const struct tok nfsv3_writemodes[] = { 16675118Sfenner { 0, "unstable" }, 16775118Sfenner { 1, "datasync" }, 16875118Sfenner { 2, "filesync" }, 16975118Sfenner { 0, NULL } 17075118Sfenner}; 17175118Sfenner 172276788Sdelphijstatic const struct tok type2str[] = { 17318976Sdfr { NFNON, "NON" }, 17418976Sdfr { NFREG, "REG" }, 17518976Sdfr { NFDIR, "DIR" }, 17618976Sdfr { NFBLK, "BLK" }, 17718976Sdfr { NFCHR, "CHR" }, 17818976Sdfr { NFLNK, "LNK" }, 17918976Sdfr { NFFIFO, "FIFO" }, 18018976Sdfr { 0, NULL } 18118976Sdfr}; 18218976Sdfr 183276788Sdelphijstatic const struct tok sunrpc_auth_str[] = { 184276788Sdelphij { SUNRPC_AUTH_OK, "OK" }, 185276788Sdelphij { SUNRPC_AUTH_BADCRED, "Bogus Credentials (seal broken)" }, 186276788Sdelphij { SUNRPC_AUTH_REJECTEDCRED, "Rejected Credentials (client should begin new session)" }, 187276788Sdelphij { SUNRPC_AUTH_BADVERF, "Bogus Verifier (seal broken)" }, 188276788Sdelphij { SUNRPC_AUTH_REJECTEDVERF, "Verifier expired or was replayed" }, 189276788Sdelphij { SUNRPC_AUTH_TOOWEAK, "Credentials are too weak" }, 190276788Sdelphij { SUNRPC_AUTH_INVALIDRESP, "Bogus response verifier" }, 191276788Sdelphij { SUNRPC_AUTH_FAILED, "Unknown failure" }, 192276788Sdelphij { 0, NULL } 193276788Sdelphij}; 194276788Sdelphij 195276788Sdelphijstatic const struct tok sunrpc_str[] = { 196276788Sdelphij { SUNRPC_PROG_UNAVAIL, "PROG_UNAVAIL" }, 197276788Sdelphij { SUNRPC_PROG_MISMATCH, "PROG_MISMATCH" }, 198276788Sdelphij { SUNRPC_PROC_UNAVAIL, "PROC_UNAVAIL" }, 199276788Sdelphij { SUNRPC_GARBAGE_ARGS, "GARBAGE_ARGS" }, 200276788Sdelphij { SUNRPC_SYSTEM_ERR, "SYSTEM_ERR" }, 201276788Sdelphij { 0, NULL } 202276788Sdelphij}; 203276788Sdelphij 20475118Sfennerstatic void 205276788Sdelphijprint_nfsaddr(netdissect_options *ndo, 206276788Sdelphij const u_char *bp, const char *s, const char *d) 20775118Sfenner{ 20875118Sfenner struct ip *ip; 20975118Sfenner#ifdef INET6 21075118Sfenner struct ip6_hdr *ip6; 21175118Sfenner char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; 21275118Sfenner#else 21375118Sfenner#ifndef INET_ADDRSTRLEN 21475118Sfenner#define INET_ADDRSTRLEN 16 21575118Sfenner#endif 21675118Sfenner char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN]; 21775118Sfenner#endif 21875118Sfenner 21975118Sfenner srcaddr[0] = dstaddr[0] = '\0'; 22075118Sfenner switch (IP_V((struct ip *)bp)) { 22175118Sfenner case 4: 22275118Sfenner ip = (struct ip *)bp; 223276788Sdelphij strlcpy(srcaddr, ipaddr_string(ndo, &ip->ip_src), sizeof(srcaddr)); 224276788Sdelphij strlcpy(dstaddr, ipaddr_string(ndo, &ip->ip_dst), sizeof(dstaddr)); 22575118Sfenner break; 22675118Sfenner#ifdef INET6 22775118Sfenner case 6: 22875118Sfenner ip6 = (struct ip6_hdr *)bp; 229276788Sdelphij strlcpy(srcaddr, ip6addr_string(ndo, &ip6->ip6_src), 23075118Sfenner sizeof(srcaddr)); 231276788Sdelphij strlcpy(dstaddr, ip6addr_string(ndo, &ip6->ip6_dst), 23275118Sfenner sizeof(dstaddr)); 23375118Sfenner break; 23475118Sfenner#endif 23575118Sfenner default: 23675118Sfenner strlcpy(srcaddr, "?", sizeof(srcaddr)); 23775118Sfenner strlcpy(dstaddr, "?", sizeof(dstaddr)); 23875118Sfenner break; 23975118Sfenner } 24075118Sfenner 241276788Sdelphij ND_PRINT((ndo, "%s.%s > %s.%s: ", srcaddr, s, dstaddr, d)); 24275118Sfenner} 24375118Sfenner 244276788Sdelphijstatic const uint32_t * 245276788Sdelphijparse_sattr3(netdissect_options *ndo, 246276788Sdelphij const uint32_t *dp, struct nfsv3_sattr *sa3) 24718976Sdfr{ 248276788Sdelphij ND_TCHECK(dp[0]); 249127675Sbms sa3->sa_modeset = EXTRACT_32BITS(dp); 250127675Sbms dp++; 251127675Sbms if (sa3->sa_modeset) { 252276788Sdelphij ND_TCHECK(dp[0]); 253127675Sbms sa3->sa_mode = EXTRACT_32BITS(dp); 254127675Sbms dp++; 25518976Sdfr } 25618976Sdfr 257276788Sdelphij ND_TCHECK(dp[0]); 258127675Sbms sa3->sa_uidset = EXTRACT_32BITS(dp); 259127675Sbms dp++; 260127675Sbms if (sa3->sa_uidset) { 261276788Sdelphij ND_TCHECK(dp[0]); 262127675Sbms sa3->sa_uid = EXTRACT_32BITS(dp); 263127675Sbms dp++; 26418976Sdfr } 26518976Sdfr 266276788Sdelphij ND_TCHECK(dp[0]); 267127675Sbms sa3->sa_gidset = EXTRACT_32BITS(dp); 268127675Sbms dp++; 269127675Sbms if (sa3->sa_gidset) { 270276788Sdelphij ND_TCHECK(dp[0]); 271127675Sbms sa3->sa_gid = EXTRACT_32BITS(dp); 272127675Sbms dp++; 27318976Sdfr } 27418976Sdfr 275276788Sdelphij ND_TCHECK(dp[0]); 276127675Sbms sa3->sa_sizeset = EXTRACT_32BITS(dp); 277127675Sbms dp++; 278127675Sbms if (sa3->sa_sizeset) { 279276788Sdelphij ND_TCHECK(dp[0]); 280127675Sbms sa3->sa_size = EXTRACT_32BITS(dp); 281127675Sbms dp++; 28218976Sdfr } 28318976Sdfr 284276788Sdelphij ND_TCHECK(dp[0]); 285127675Sbms sa3->sa_atimetype = EXTRACT_32BITS(dp); 286127675Sbms dp++; 287127675Sbms if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) { 288276788Sdelphij ND_TCHECK(dp[1]); 289127675Sbms sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp); 290127675Sbms dp++; 291127675Sbms sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp); 292127675Sbms dp++; 29318976Sdfr } 29418976Sdfr 295276788Sdelphij ND_TCHECK(dp[0]); 296127675Sbms sa3->sa_mtimetype = EXTRACT_32BITS(dp); 297127675Sbms dp++; 298127675Sbms if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) { 299276788Sdelphij ND_TCHECK(dp[1]); 300127675Sbms sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp); 301127675Sbms dp++; 302127675Sbms sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp); 303127675Sbms dp++; 30418976Sdfr } 30518976Sdfr 30618976Sdfr return dp; 30775118Sfennertrunc: 30875118Sfenner return NULL; 30918976Sdfr} 31018976Sdfr 31175118Sfennerstatic int nfserr; /* true if we error rather than trunc */ 31275118Sfenner 31375118Sfennerstatic void 314276788Sdelphijprint_sattr3(netdissect_options *ndo, 315276788Sdelphij const struct nfsv3_sattr *sa3, int verbose) 31618976Sdfr{ 31718976Sdfr if (sa3->sa_modeset) 318276788Sdelphij ND_PRINT((ndo, " mode %o", sa3->sa_mode)); 31918976Sdfr if (sa3->sa_uidset) 320276788Sdelphij ND_PRINT((ndo, " uid %u", sa3->sa_uid)); 32118976Sdfr if (sa3->sa_gidset) 322276788Sdelphij ND_PRINT((ndo, " gid %u", sa3->sa_gid)); 32318976Sdfr if (verbose > 1) { 32418976Sdfr if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) 325276788Sdelphij ND_PRINT((ndo, " atime %u.%06u", sa3->sa_atime.nfsv3_sec, 326276788Sdelphij sa3->sa_atime.nfsv3_nsec)); 32718976Sdfr if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) 328276788Sdelphij ND_PRINT((ndo, " mtime %u.%06u", sa3->sa_mtime.nfsv3_sec, 329276788Sdelphij sa3->sa_mtime.nfsv3_nsec)); 33018976Sdfr } 33118976Sdfr} 33218976Sdfr 33318976Sdfrvoid 334276788Sdelphijnfsreply_print(netdissect_options *ndo, 335276788Sdelphij register const u_char *bp, u_int length, 336276788Sdelphij register const u_char *bp2) 33717680Spst{ 338146778Ssam register const struct sunrpc_msg *rp; 33975118Sfenner char srcid[20], dstid[20]; /*fits 32bit*/ 34017680Spst 34126183Sfenner nfserr = 0; /* assume no error */ 342146778Ssam rp = (const struct sunrpc_msg *)bp; 34317680Spst 344276788Sdelphij ND_TCHECK(rp->rm_xid); 345276788Sdelphij if (!ndo->ndo_nflag) { 34675118Sfenner strlcpy(srcid, "nfs", sizeof(srcid)); 34775118Sfenner snprintf(dstid, sizeof(dstid), "%u", 348127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 34975118Sfenner } else { 35075118Sfenner snprintf(srcid, sizeof(srcid), "%u", NFS_PORT); 35175118Sfenner snprintf(dstid, sizeof(dstid), "%u", 352127675Sbms EXTRACT_32BITS(&rp->rm_xid)); 35375118Sfenner } 354276788Sdelphij print_nfsaddr(ndo, bp2, srcid, dstid); 355276788Sdelphij 356276788Sdelphij nfsreply_print_noaddr(ndo, bp, length, bp2); 357276788Sdelphij return; 358276788Sdelphij 359276788Sdelphijtrunc: 360276788Sdelphij if (!nfserr) 361276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 362276788Sdelphij} 363276788Sdelphij 364276788Sdelphijvoid 365276788Sdelphijnfsreply_print_noaddr(netdissect_options *ndo, 366276788Sdelphij register const u_char *bp, u_int length, 367276788Sdelphij register const u_char *bp2) 368276788Sdelphij{ 369276788Sdelphij register const struct sunrpc_msg *rp; 370276788Sdelphij uint32_t proc, vers, reply_stat; 371276788Sdelphij enum sunrpc_reject_stat rstat; 372276788Sdelphij uint32_t rlow; 373276788Sdelphij uint32_t rhigh; 374276788Sdelphij enum sunrpc_auth_stat rwhy; 375276788Sdelphij 376276788Sdelphij nfserr = 0; /* assume no error */ 377276788Sdelphij rp = (const struct sunrpc_msg *)bp; 378276788Sdelphij 379276788Sdelphij ND_TCHECK(rp->rm_reply.rp_stat); 380172686Smlaier reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat); 381172686Smlaier switch (reply_stat) { 38217680Spst 383172686Smlaier case SUNRPC_MSG_ACCEPTED: 384276788Sdelphij ND_PRINT((ndo, "reply ok %u", length)); 385172686Smlaier if (xid_map_find(rp, bp2, &proc, &vers) >= 0) 386276788Sdelphij interp_reply(ndo, rp, proc, vers, length); 387172686Smlaier break; 388172686Smlaier 389172686Smlaier case SUNRPC_MSG_DENIED: 390276788Sdelphij ND_PRINT((ndo, "reply ERR %u: ", length)); 391276788Sdelphij ND_TCHECK(rp->rm_reply.rp_reject.rj_stat); 392172686Smlaier rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat); 393172686Smlaier switch (rstat) { 394172686Smlaier 395172686Smlaier case SUNRPC_RPC_MISMATCH: 396276788Sdelphij ND_TCHECK(rp->rm_reply.rp_reject.rj_vers.high); 397172686Smlaier rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low); 398172686Smlaier rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high); 399276788Sdelphij ND_PRINT((ndo, "RPC Version mismatch (%u-%u)", rlow, rhigh)); 400172686Smlaier break; 401172686Smlaier 402172686Smlaier case SUNRPC_AUTH_ERROR: 403276788Sdelphij ND_TCHECK(rp->rm_reply.rp_reject.rj_why); 404172686Smlaier rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why); 405276788Sdelphij ND_PRINT((ndo, "Auth %s", tok2str(sunrpc_auth_str, "Invalid failure code %u", rwhy))); 406172686Smlaier break; 407172686Smlaier 408172686Smlaier default: 409276788Sdelphij ND_PRINT((ndo, "Unknown reason for rejecting rpc message %u", (unsigned int)rstat)); 410172686Smlaier break; 411172686Smlaier } 412172686Smlaier break; 413172686Smlaier 414172686Smlaier default: 415276788Sdelphij ND_PRINT((ndo, "reply Unknown rpc response code=%u %u", reply_stat, length)); 416172686Smlaier break; 417172686Smlaier } 418190207Srpaulo return; 419190207Srpaulo 420190207Srpaulotrunc: 421190207Srpaulo if (!nfserr) 422276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 42317680Spst} 42417680Spst 42517680Spst/* 42617680Spst * Return a pointer to the first file handle in the packet. 42775118Sfenner * If the packet was truncated, return 0. 42817680Spst */ 429276788Sdelphijstatic const uint32_t * 430276788Sdelphijparsereq(netdissect_options *ndo, 431276788Sdelphij register const struct sunrpc_msg *rp, register u_int length) 43217680Spst{ 433276788Sdelphij register const uint32_t *dp; 43417680Spst register u_int len; 43517680Spst 43617680Spst /* 43717680Spst * find the start of the req data (if we captured it) 43817680Spst */ 439276788Sdelphij dp = (uint32_t *)&rp->rm_call.cb_cred; 440276788Sdelphij ND_TCHECK(dp[1]); 441127675Sbms len = EXTRACT_32BITS(&dp[1]); 44226183Sfenner if (len < length) { 44326183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 444276788Sdelphij ND_TCHECK(dp[1]); 445127675Sbms len = EXTRACT_32BITS(&dp[1]); 44626183Sfenner if (len < length) { 44726183Sfenner dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); 448276788Sdelphij ND_TCHECK2(dp[0], 0); 44926183Sfenner return (dp); 45017680Spst } 45117680Spst } 45226183Sfennertrunc: 45326183Sfenner return (NULL); 45417680Spst} 45517680Spst 45617680Spst/* 45717680Spst * Print out an NFS file handle and return a pointer to following word. 45875118Sfenner * If packet was truncated, return 0. 45917680Spst */ 460276788Sdelphijstatic const uint32_t * 461276788Sdelphijparsefh(netdissect_options *ndo, 462276788Sdelphij register const uint32_t *dp, int v3) 46317680Spst{ 464127675Sbms u_int len; 46518976Sdfr 46618976Sdfr if (v3) { 467276788Sdelphij ND_TCHECK(dp[0]); 468127675Sbms len = EXTRACT_32BITS(dp) / 4; 46918976Sdfr dp++; 47018976Sdfr } else 47118976Sdfr len = NFSX_V2FH / 4; 47218976Sdfr 473276788Sdelphij if (ND_TTEST2(*dp, len * sizeof(*dp))) { 474276788Sdelphij nfs_printfh(ndo, dp, len); 47518976Sdfr return (dp + len); 47617680Spst } 47726183Sfennertrunc: 47826183Sfenner return (NULL); 47917680Spst} 48017680Spst 48117680Spst/* 48217680Spst * Print out a file name and return pointer to 32-bit word past it. 48375118Sfenner * If packet was truncated, return 0. 48417680Spst */ 485276788Sdelphijstatic const uint32_t * 486276788Sdelphijparsefn(netdissect_options *ndo, 487276788Sdelphij register const uint32_t *dp) 48817680Spst{ 489276788Sdelphij register uint32_t len; 49017680Spst register const u_char *cp; 49117680Spst 49217680Spst /* Bail if we don't have the string length */ 493276788Sdelphij ND_TCHECK(*dp); 49417680Spst 49517680Spst /* Fetch string length; convert to host order */ 49617680Spst len = *dp++; 49717680Spst NTOHL(len); 49817680Spst 499276788Sdelphij ND_TCHECK2(*dp, ((len + 3) & ~3)); 50075118Sfenner 50117680Spst cp = (u_char *)dp; 50217680Spst /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ 50317680Spst dp += ((len + 3) & ~3) / sizeof(*dp); 504276788Sdelphij ND_PRINT((ndo, "\"")); 505276788Sdelphij if (fn_printn(ndo, cp, len, ndo->ndo_snapend)) { 506276788Sdelphij ND_PRINT((ndo, "\"")); 507147904Ssam goto trunc; 508147904Ssam } 509276788Sdelphij ND_PRINT((ndo, "\"")); 51017680Spst 51117680Spst return (dp); 51275118Sfennertrunc: 51375118Sfenner return NULL; 51417680Spst} 51517680Spst 51617680Spst/* 51717680Spst * Print out file handle and file name. 51817680Spst * Return pointer to 32-bit word past file name. 51975118Sfenner * If packet was truncated (or there was some other error), return 0. 52017680Spst */ 521276788Sdelphijstatic const uint32_t * 522276788Sdelphijparsefhn(netdissect_options *ndo, 523276788Sdelphij register const uint32_t *dp, int v3) 52417680Spst{ 525276788Sdelphij dp = parsefh(ndo, dp, v3); 52626183Sfenner if (dp == NULL) 52726183Sfenner return (NULL); 528276788Sdelphij ND_PRINT((ndo, " ")); 529276788Sdelphij return (parsefn(ndo, dp)); 53017680Spst} 53117680Spst 53217680Spstvoid 533276788Sdelphijnfsreq_print_noaddr(netdissect_options *ndo, 534276788Sdelphij register const u_char *bp, u_int length, 535276788Sdelphij register const u_char *bp2) 53617680Spst{ 537146778Ssam register const struct sunrpc_msg *rp; 538276788Sdelphij register const uint32_t *dp; 53975118Sfenner nfs_type type; 54075118Sfenner int v3; 541276788Sdelphij uint32_t proc; 542276788Sdelphij uint32_t access_flags; 54318976Sdfr struct nfsv3_sattr sa3; 54417680Spst 545276788Sdelphij ND_PRINT((ndo, "%d", length)); 54626183Sfenner nfserr = 0; /* assume no error */ 547146778Ssam rp = (const struct sunrpc_msg *)bp; 548190207Srpaulo 549276788Sdelphij if (!xid_map_enter(ndo, rp, bp2)) /* record proc number for later on */ 550190207Srpaulo goto trunc; 55117680Spst 552127675Sbms v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3); 553127675Sbms proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 55418976Sdfr 55518976Sdfr if (!v3 && proc < NFS_NPROCS) 55618976Sdfr proc = nfsv3_procid[proc]; 55718976Sdfr 558276788Sdelphij ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc))); 55918976Sdfr switch (proc) { 56017680Spst 56117680Spst case NFSPROC_GETATTR: 56217680Spst case NFSPROC_SETATTR: 563276788Sdelphij case NFSPROC_READLINK: 564276788Sdelphij case NFSPROC_FSSTAT: 565276788Sdelphij case NFSPROC_FSINFO: 566276788Sdelphij case NFSPROC_PATHCONF: 567276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 568276788Sdelphij parsefh(ndo, dp, v3) != NULL) 56917680Spst return; 57017680Spst break; 57117680Spst 57217680Spst case NFSPROC_LOOKUP: 573276788Sdelphij case NFSPROC_CREATE: 574276788Sdelphij case NFSPROC_MKDIR: 575276788Sdelphij case NFSPROC_REMOVE: 576276788Sdelphij case NFSPROC_RMDIR: 577276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 578276788Sdelphij parsefhn(ndo, dp, v3) != NULL) 57917680Spst return; 58017680Spst break; 58117680Spst 58218976Sdfr case NFSPROC_ACCESS: 583276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 584276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 585276788Sdelphij ND_TCHECK(dp[0]); 586214478Srpaulo access_flags = EXTRACT_32BITS(&dp[0]); 587214478Srpaulo if (access_flags & ~NFSV3ACCESS_FULL) { 588214478Srpaulo /* NFSV3ACCESS definitions aren't up to date */ 589276788Sdelphij ND_PRINT((ndo, " %04x", access_flags)); 590214478Srpaulo } else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) { 591276788Sdelphij ND_PRINT((ndo, " NFS_ACCESS_FULL")); 592214478Srpaulo } else { 593214478Srpaulo char separator = ' '; 594214478Srpaulo if (access_flags & NFSV3ACCESS_READ) { 595276788Sdelphij ND_PRINT((ndo, " NFS_ACCESS_READ")); 596214478Srpaulo separator = '|'; 597214478Srpaulo } 598214478Srpaulo if (access_flags & NFSV3ACCESS_LOOKUP) { 599276788Sdelphij ND_PRINT((ndo, "%cNFS_ACCESS_LOOKUP", separator)); 600214478Srpaulo separator = '|'; 601214478Srpaulo } 602214478Srpaulo if (access_flags & NFSV3ACCESS_MODIFY) { 603276788Sdelphij ND_PRINT((ndo, "%cNFS_ACCESS_MODIFY", separator)); 604214478Srpaulo separator = '|'; 605214478Srpaulo } 606214478Srpaulo if (access_flags & NFSV3ACCESS_EXTEND) { 607276788Sdelphij ND_PRINT((ndo, "%cNFS_ACCESS_EXTEND", separator)); 608214478Srpaulo separator = '|'; 609214478Srpaulo } 610214478Srpaulo if (access_flags & NFSV3ACCESS_DELETE) { 611276788Sdelphij ND_PRINT((ndo, "%cNFS_ACCESS_DELETE", separator)); 612214478Srpaulo separator = '|'; 613214478Srpaulo } 614214478Srpaulo if (access_flags & NFSV3ACCESS_EXECUTE) 615276788Sdelphij ND_PRINT((ndo, "%cNFS_ACCESS_EXECUTE", separator)); 616214478Srpaulo } 61718976Sdfr return; 61818976Sdfr } 61918976Sdfr break; 62018976Sdfr 62117680Spst case NFSPROC_READ: 622276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 623276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 62418976Sdfr if (v3) { 625276788Sdelphij ND_TCHECK(dp[2]); 626276788Sdelphij ND_PRINT((ndo, " %u bytes @ %" PRIu64, 627146778Ssam EXTRACT_32BITS(&dp[2]), 628276788Sdelphij EXTRACT_64BITS(&dp[0]))); 62918976Sdfr } else { 630276788Sdelphij ND_TCHECK(dp[1]); 631276788Sdelphij ND_PRINT((ndo, " %u bytes @ %u", 632127675Sbms EXTRACT_32BITS(&dp[1]), 633276788Sdelphij EXTRACT_32BITS(&dp[0]))); 63418976Sdfr } 63517680Spst return; 63617680Spst } 63717680Spst break; 63817680Spst 63917680Spst case NFSPROC_WRITE: 640276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 641276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 64218976Sdfr if (v3) { 643276788Sdelphij ND_TCHECK(dp[2]); 644276788Sdelphij ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64, 645146778Ssam EXTRACT_32BITS(&dp[4]), 646146778Ssam EXTRACT_32BITS(&dp[2]), 647276788Sdelphij EXTRACT_64BITS(&dp[0]))); 648276788Sdelphij if (ndo->ndo_vflag) { 64918976Sdfr dp += 3; 650276788Sdelphij ND_TCHECK(dp[0]); 651276788Sdelphij ND_PRINT((ndo, " <%s>", 65275118Sfenner tok2str(nfsv3_writemodes, 653276788Sdelphij NULL, EXTRACT_32BITS(dp)))); 65418976Sdfr } 65518976Sdfr } else { 656276788Sdelphij ND_TCHECK(dp[3]); 657276788Sdelphij ND_PRINT((ndo, " %u (%u) bytes @ %u (%u)", 658127675Sbms EXTRACT_32BITS(&dp[3]), 659127675Sbms EXTRACT_32BITS(&dp[2]), 660127675Sbms EXTRACT_32BITS(&dp[1]), 661276788Sdelphij EXTRACT_32BITS(&dp[0]))); 66218976Sdfr } 66317680Spst return; 66417680Spst } 66517680Spst break; 66617680Spst 66718976Sdfr case NFSPROC_SYMLINK: 668276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != 0 && 669276788Sdelphij (dp = parsefhn(ndo, dp, v3)) != 0) { 670276788Sdelphij ND_PRINT((ndo, " ->")); 671276788Sdelphij if (v3 && (dp = parse_sattr3(ndo, dp, &sa3)) == 0) 67218976Sdfr break; 673276788Sdelphij if (parsefn(ndo, dp) == 0) 67418976Sdfr break; 675276788Sdelphij if (v3 && ndo->ndo_vflag) 676276788Sdelphij print_sattr3(ndo, &sa3, ndo->ndo_vflag); 67718976Sdfr return; 67818976Sdfr } 67918976Sdfr break; 68018976Sdfr 68118976Sdfr case NFSPROC_MKNOD: 682276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != 0 && 683276788Sdelphij (dp = parsefhn(ndo, dp, v3)) != 0) { 684276788Sdelphij ND_TCHECK(*dp); 685127675Sbms type = (nfs_type)EXTRACT_32BITS(dp); 686127675Sbms dp++; 687276788Sdelphij if ((dp = parse_sattr3(ndo, dp, &sa3)) == 0) 68818976Sdfr break; 689276788Sdelphij ND_PRINT((ndo, " %s", tok2str(type2str, "unk-ft %d", type))); 690276788Sdelphij if (ndo->ndo_vflag && (type == NFCHR || type == NFBLK)) { 691276788Sdelphij ND_TCHECK(dp[1]); 692276788Sdelphij ND_PRINT((ndo, " %u/%u", 693127675Sbms EXTRACT_32BITS(&dp[0]), 694276788Sdelphij EXTRACT_32BITS(&dp[1]))); 69518976Sdfr dp += 2; 69618976Sdfr } 697276788Sdelphij if (ndo->ndo_vflag) 698276788Sdelphij print_sattr3(ndo, &sa3, ndo->ndo_vflag); 69918976Sdfr return; 70018976Sdfr } 70118976Sdfr break; 70218976Sdfr 70317680Spst case NFSPROC_RENAME: 704276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 705276788Sdelphij (dp = parsefhn(ndo, dp, v3)) != NULL) { 706276788Sdelphij ND_PRINT((ndo, " ->")); 707276788Sdelphij if (parsefhn(ndo, dp, v3) != NULL) 70817680Spst return; 70917680Spst } 71017680Spst break; 71117680Spst 71217680Spst case NFSPROC_LINK: 713276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 714276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 715276788Sdelphij ND_PRINT((ndo, " ->")); 716276788Sdelphij if (parsefhn(ndo, dp, v3) != NULL) 71717680Spst return; 71817680Spst } 71917680Spst break; 72017680Spst 72118976Sdfr case NFSPROC_READDIR: 722276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 723276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 72418976Sdfr if (v3) { 725276788Sdelphij ND_TCHECK(dp[4]); 72618976Sdfr /* 72718976Sdfr * We shouldn't really try to interpret the 72818976Sdfr * offset cookie here. 72918976Sdfr */ 730276788Sdelphij ND_PRINT((ndo, " %u bytes @ %" PRId64, 731146778Ssam EXTRACT_32BITS(&dp[4]), 732276788Sdelphij EXTRACT_64BITS(&dp[0]))); 733276788Sdelphij if (ndo->ndo_vflag) 734276788Sdelphij ND_PRINT((ndo, " verf %08x%08x", dp[2], dp[3])); 73518976Sdfr } else { 736276788Sdelphij ND_TCHECK(dp[1]); 73718976Sdfr /* 73818976Sdfr * Print the offset as signed, since -1 is 73918976Sdfr * common, but offsets > 2^31 aren't. 74018976Sdfr */ 741276788Sdelphij ND_PRINT((ndo, " %u bytes @ %d", 742127675Sbms EXTRACT_32BITS(&dp[1]), 743276788Sdelphij EXTRACT_32BITS(&dp[0]))); 74418976Sdfr } 74518976Sdfr return; 74617680Spst } 74717680Spst break; 74817680Spst 74918976Sdfr case NFSPROC_READDIRPLUS: 750276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 751276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 752276788Sdelphij ND_TCHECK(dp[4]); 75318976Sdfr /* 75418976Sdfr * We don't try to interpret the offset 75518976Sdfr * cookie here. 75618976Sdfr */ 757276788Sdelphij ND_PRINT((ndo, " %u bytes @ %" PRId64, 758146778Ssam EXTRACT_32BITS(&dp[4]), 759276788Sdelphij EXTRACT_64BITS(&dp[0]))); 760276788Sdelphij if (ndo->ndo_vflag) { 761276788Sdelphij ND_TCHECK(dp[5]); 762276788Sdelphij ND_PRINT((ndo, " max %u verf %08x%08x", 763276788Sdelphij EXTRACT_32BITS(&dp[5]), dp[2], dp[3])); 764146778Ssam } 76517680Spst return; 76618976Sdfr } 76717680Spst break; 76817680Spst 76918976Sdfr case NFSPROC_COMMIT: 770276788Sdelphij if ((dp = parsereq(ndo, rp, length)) != NULL && 771276788Sdelphij (dp = parsefh(ndo, dp, v3)) != NULL) { 772276788Sdelphij ND_TCHECK(dp[2]); 773276788Sdelphij ND_PRINT((ndo, " %u bytes @ %" PRIu64, 774146778Ssam EXTRACT_32BITS(&dp[2]), 775276788Sdelphij EXTRACT_64BITS(&dp[0]))); 77617680Spst return; 77717680Spst } 77817680Spst break; 77917680Spst 78017680Spst default: 78117680Spst return; 78217680Spst } 78375118Sfenner 78417680Spsttrunc: 78526183Sfenner if (!nfserr) 786276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 78717680Spst} 78817680Spst 78917680Spst/* 79017680Spst * Print out an NFS file handle. 79117680Spst * We assume packet was not truncated before the end of the 79217680Spst * file handle pointed to by dp. 79317680Spst * 79417680Spst * Note: new version (using portable file-handle parser) doesn't produce 79517680Spst * generation number. It probably could be made to do that, with some 79617680Spst * additional hacking on the parser code. 79717680Spst */ 79817680Spststatic void 799276788Sdelphijnfs_printfh(netdissect_options *ndo, 800276788Sdelphij register const uint32_t *dp, const u_int len) 80117680Spst{ 80217680Spst my_fsid fsid; 803276788Sdelphij uint32_t ino; 804127675Sbms const char *sfsname = NULL; 805127675Sbms char *spacep; 80617680Spst 807276788Sdelphij if (ndo->ndo_uflag) { 808127675Sbms u_int i; 809127675Sbms char const *sep = ""; 81017680Spst 811276788Sdelphij ND_PRINT((ndo, " fh[")); 812127675Sbms for (i=0; i<len; i++) { 813276788Sdelphij ND_PRINT((ndo, "%s%x", sep, dp[i])); 814127675Sbms sep = ":"; 815127675Sbms } 816276788Sdelphij ND_PRINT((ndo, "]")); 817127675Sbms return; 818127675Sbms } 819127675Sbms 820127675Sbms Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0); 821127675Sbms 82217680Spst if (sfsname) { 82326183Sfenner /* file system ID is ASCII, not numeric, for this server OS */ 82426183Sfenner static char temp[NFSX_V3FHMAX+1]; 82517680Spst 82626183Sfenner /* Make sure string is null-terminated */ 82726183Sfenner strncpy(temp, sfsname, NFSX_V3FHMAX); 82875118Sfenner temp[sizeof(temp) - 1] = '\0'; 82926183Sfenner /* Remove trailing spaces */ 830127675Sbms spacep = strchr(temp, ' '); 831127675Sbms if (spacep) 832127675Sbms *spacep = '\0'; 83317680Spst 834276788Sdelphij ND_PRINT((ndo, " fh %s/", temp)); 83526183Sfenner } else { 836276788Sdelphij ND_PRINT((ndo, " fh %d,%d/", 837276788Sdelphij fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor)); 83817680Spst } 83975118Sfenner 840127675Sbms if(fsid.Fsid_dev.Minor == 257) 841127675Sbms /* Print the undecoded handle */ 842276788Sdelphij ND_PRINT((ndo, "%s", fsid.Opaque_Handle)); 84375118Sfenner else 844276788Sdelphij ND_PRINT((ndo, "%ld", (long) ino)); 84517680Spst} 84617680Spst 84717680Spst/* 84817680Spst * Maintain a small cache of recent client.XID.server/proc pairs, to allow 84917680Spst * us to match up replies with requests and thus to know how to parse 85017680Spst * the reply. 85117680Spst */ 85217680Spst 85317680Spststruct xid_map_entry { 854276788Sdelphij uint32_t xid; /* transaction ID (net order) */ 85575118Sfenner int ipver; /* IP version (4 or 6) */ 85675118Sfenner#ifdef INET6 85775118Sfenner struct in6_addr client; /* client IP address (net order) */ 85875118Sfenner struct in6_addr server; /* server IP address (net order) */ 85975118Sfenner#else 86017680Spst struct in_addr client; /* client IP address (net order) */ 86117680Spst struct in_addr server; /* server IP address (net order) */ 86275118Sfenner#endif 863276788Sdelphij uint32_t proc; /* call proc number (host order) */ 864276788Sdelphij uint32_t vers; /* program version (host order) */ 86517680Spst}; 86617680Spst 86717680Spst/* 86817680Spst * Map entries are kept in an array that we manage as a ring; 86917680Spst * new entries are always added at the tail of the ring. Initially, 87017680Spst * all the entries are zero and hence don't match anything. 87117680Spst */ 87217680Spst 87317680Spst#define XIDMAPSIZE 64 87417680Spst 87517680Spststruct xid_map_entry xid_map[XIDMAPSIZE]; 87617680Spst 87717680Spstint xid_map_next = 0; 87817680Spstint xid_map_hint = 0; 87917680Spst 880190207Srpaulostatic int 881276788Sdelphijxid_map_enter(netdissect_options *ndo, 882276788Sdelphij const struct sunrpc_msg *rp, const u_char *bp) 88317680Spst{ 88475118Sfenner struct ip *ip = NULL; 88575118Sfenner#ifdef INET6 88675118Sfenner struct ip6_hdr *ip6 = NULL; 88775118Sfenner#endif 88817680Spst struct xid_map_entry *xmep; 88917680Spst 890276788Sdelphij if (!ND_TTEST(rp->rm_call.cb_vers)) 891190207Srpaulo return (0); 89275118Sfenner switch (IP_V((struct ip *)bp)) { 89375118Sfenner case 4: 89475118Sfenner ip = (struct ip *)bp; 89575118Sfenner break; 89675118Sfenner#ifdef INET6 89775118Sfenner case 6: 89875118Sfenner ip6 = (struct ip6_hdr *)bp; 89975118Sfenner break; 90075118Sfenner#endif 90175118Sfenner default: 902190207Srpaulo return (1); 90375118Sfenner } 90475118Sfenner 90517680Spst xmep = &xid_map[xid_map_next]; 90617680Spst 90717680Spst if (++xid_map_next >= XIDMAPSIZE) 90817680Spst xid_map_next = 0; 90917680Spst 910276788Sdelphij UNALIGNED_MEMCPY(&xmep->xid, &rp->rm_xid, sizeof(xmep->xid)); 91175118Sfenner if (ip) { 91275118Sfenner xmep->ipver = 4; 913276788Sdelphij UNALIGNED_MEMCPY(&xmep->client, &ip->ip_src, sizeof(ip->ip_src)); 914276788Sdelphij UNALIGNED_MEMCPY(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst)); 91575118Sfenner } 91675118Sfenner#ifdef INET6 91775118Sfenner else if (ip6) { 91875118Sfenner xmep->ipver = 6; 919276788Sdelphij UNALIGNED_MEMCPY(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src)); 920276788Sdelphij UNALIGNED_MEMCPY(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 92175118Sfenner } 92275118Sfenner#endif 923127675Sbms xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc); 924127675Sbms xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers); 925190207Srpaulo return (1); 92617680Spst} 92717680Spst 92826183Sfenner/* 92926183Sfenner * Returns 0 and puts NFSPROC_xxx in proc return and 93026183Sfenner * version in vers return, or returns -1 on failure 93126183Sfenner */ 93218976Sdfrstatic int 933276788Sdelphijxid_map_find(const struct sunrpc_msg *rp, const u_char *bp, uint32_t *proc, 934276788Sdelphij uint32_t *vers) 93517680Spst{ 93617680Spst int i; 93717680Spst struct xid_map_entry *xmep; 938276788Sdelphij uint32_t xid = rp->rm_xid; 93975118Sfenner struct ip *ip = (struct ip *)bp; 94075118Sfenner#ifdef INET6 94175118Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 94275118Sfenner#endif 94375118Sfenner int cmp; 94417680Spst 94517680Spst /* Start searching from where we last left off */ 946127675Sbms i = xid_map_hint; 94717680Spst do { 94817680Spst xmep = &xid_map[i]; 94975118Sfenner cmp = 1; 95075118Sfenner if (xmep->ipver != IP_V(ip) || xmep->xid != xid) 95175118Sfenner goto nextitem; 95275118Sfenner switch (xmep->ipver) { 95375118Sfenner case 4: 954276788Sdelphij if (UNALIGNED_MEMCMP(&ip->ip_src, &xmep->server, 95575118Sfenner sizeof(ip->ip_src)) != 0 || 956276788Sdelphij UNALIGNED_MEMCMP(&ip->ip_dst, &xmep->client, 95775118Sfenner sizeof(ip->ip_dst)) != 0) { 95875118Sfenner cmp = 0; 95975118Sfenner } 96075118Sfenner break; 96175118Sfenner#ifdef INET6 96275118Sfenner case 6: 963276788Sdelphij if (UNALIGNED_MEMCMP(&ip6->ip6_src, &xmep->server, 96475118Sfenner sizeof(ip6->ip6_src)) != 0 || 965276788Sdelphij UNALIGNED_MEMCMP(&ip6->ip6_dst, &xmep->client, 96675118Sfenner sizeof(ip6->ip6_dst)) != 0) { 96775118Sfenner cmp = 0; 96875118Sfenner } 96975118Sfenner break; 97075118Sfenner#endif 97175118Sfenner default: 97275118Sfenner cmp = 0; 97375118Sfenner break; 97475118Sfenner } 97575118Sfenner if (cmp) { 97617680Spst /* match */ 97717680Spst xid_map_hint = i; 97818976Sdfr *proc = xmep->proc; 97918976Sdfr *vers = xmep->vers; 98018976Sdfr return 0; 98117680Spst } 98275118Sfenner nextitem: 98317680Spst if (++i >= XIDMAPSIZE) 98417680Spst i = 0; 98517680Spst } while (i != xid_map_hint); 98617680Spst 98717680Spst /* search failed */ 98875118Sfenner return (-1); 98917680Spst} 99017680Spst 99117680Spst/* 99217680Spst * Routines for parsing reply packets 99317680Spst */ 99417680Spst 99517680Spst/* 99617680Spst * Return a pointer to the beginning of the actual results. 99775118Sfenner * If the packet was truncated, return 0. 99817680Spst */ 999276788Sdelphijstatic const uint32_t * 1000276788Sdelphijparserep(netdissect_options *ndo, 1001276788Sdelphij register const struct sunrpc_msg *rp, register u_int length) 100217680Spst{ 1003276788Sdelphij register const uint32_t *dp; 100475118Sfenner u_int len; 1005146778Ssam enum sunrpc_accept_stat astat; 100617680Spst 100717680Spst /* 100817680Spst * Portability note: 100917680Spst * Here we find the address of the ar_verf credentials. 101017680Spst * Originally, this calculation was 1011276788Sdelphij * dp = (uint32_t *)&rp->rm_reply.rp_acpt.ar_verf 101217680Spst * On the wire, the rp_acpt field starts immediately after 101317680Spst * the (32 bit) rp_stat field. However, rp_acpt (which is a 101417680Spst * "struct accepted_reply") contains a "struct opaque_auth", 101517680Spst * whose internal representation contains a pointer, so on a 101617680Spst * 64-bit machine the compiler inserts 32 bits of padding 101717680Spst * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use 101817680Spst * the internal representation to parse the on-the-wire 101917680Spst * representation. Instead, we skip past the rp_stat field, 102017680Spst * which is an "enum" and so occupies one 32-bit word. 102117680Spst */ 1022276788Sdelphij dp = ((const uint32_t *)&rp->rm_reply) + 1; 1023276788Sdelphij ND_TCHECK(dp[1]); 1024127675Sbms len = EXTRACT_32BITS(&dp[1]); 102517680Spst if (len >= length) 102626183Sfenner return (NULL); 102717680Spst /* 102817680Spst * skip past the ar_verf credentials. 102917680Spst */ 1030276788Sdelphij dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t); 1031276788Sdelphij ND_TCHECK2(dp[0], 0); 103217680Spst 103317680Spst /* 103417680Spst * now we can check the ar_stat field 103517680Spst */ 1036147904Ssam astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); 1037276788Sdelphij if (astat != SUNRPC_SUCCESS) { 1038276788Sdelphij ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat))); 103926183Sfenner nfserr = 1; /* suppress trunc string */ 104026183Sfenner return (NULL); 104117680Spst } 104217680Spst /* successful return */ 1043276788Sdelphij ND_TCHECK2(*dp, sizeof(astat)); 1044276788Sdelphij return ((uint32_t *) (sizeof(astat) + ((char *)dp))); 104526183Sfennertrunc: 104675118Sfenner return (0); 104717680Spst} 104817680Spst 1049276788Sdelphijstatic const uint32_t * 1050276788Sdelphijparsestatus(netdissect_options *ndo, 1051276788Sdelphij const uint32_t *dp, int *er) 105217680Spst{ 105375118Sfenner int errnum; 105417680Spst 1055276788Sdelphij ND_TCHECK(dp[0]); 105675118Sfenner 1057127675Sbms errnum = EXTRACT_32BITS(&dp[0]); 105818976Sdfr if (er) 105926183Sfenner *er = errnum; 106026183Sfenner if (errnum != 0) { 1061276788Sdelphij if (!ndo->ndo_qflag) 1062276788Sdelphij ND_PRINT((ndo, " ERROR: %s", 1063276788Sdelphij tok2str(status2str, "unk %d", errnum))); 106426183Sfenner nfserr = 1; 106517680Spst } 106617680Spst return (dp + 1); 106726183Sfennertrunc: 106875118Sfenner return NULL; 106917680Spst} 107017680Spst 1071276788Sdelphijstatic const uint32_t * 1072276788Sdelphijparsefattr(netdissect_options *ndo, 1073276788Sdelphij const uint32_t *dp, int verbose, int v3) 107417680Spst{ 107518976Sdfr const struct nfs_fattr *fap; 107617680Spst 107718976Sdfr fap = (const struct nfs_fattr *)dp; 1078276788Sdelphij ND_TCHECK(fap->fa_gid); 107917680Spst if (verbose) { 1080276788Sdelphij ND_PRINT((ndo, " %s %o ids %d/%d", 108175118Sfenner tok2str(type2str, "unk-ft %d ", 1082127675Sbms EXTRACT_32BITS(&fap->fa_type)), 1083127675Sbms EXTRACT_32BITS(&fap->fa_mode), 1084127675Sbms EXTRACT_32BITS(&fap->fa_uid), 1085276788Sdelphij EXTRACT_32BITS(&fap->fa_gid))); 108618976Sdfr if (v3) { 1087276788Sdelphij ND_TCHECK(fap->fa3_size); 1088276788Sdelphij ND_PRINT((ndo, " sz %" PRIu64, 1089276788Sdelphij EXTRACT_64BITS((uint32_t *)&fap->fa3_size))); 109026184Sfenner } else { 1091276788Sdelphij ND_TCHECK(fap->fa2_size); 1092276788Sdelphij ND_PRINT((ndo, " sz %d", EXTRACT_32BITS(&fap->fa2_size))); 109318976Sdfr } 109417680Spst } 109517680Spst /* print lots more stuff */ 109617680Spst if (verbose > 1) { 109718976Sdfr if (v3) { 1098276788Sdelphij ND_TCHECK(fap->fa3_ctime); 1099276788Sdelphij ND_PRINT((ndo, " nlink %d rdev %d/%d", 1100127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1101127675Sbms EXTRACT_32BITS(&fap->fa3_rdev.specdata1), 1102276788Sdelphij EXTRACT_32BITS(&fap->fa3_rdev.specdata2))); 1103276788Sdelphij ND_PRINT((ndo, " fsid %" PRIx64, 1104276788Sdelphij EXTRACT_64BITS((uint32_t *)&fap->fa3_fsid))); 1105276788Sdelphij ND_PRINT((ndo, " fileid %" PRIx64, 1106276788Sdelphij EXTRACT_64BITS((uint32_t *)&fap->fa3_fileid))); 1107276788Sdelphij ND_PRINT((ndo, " a/m/ctime %u.%06u", 1108127675Sbms EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec), 1109276788Sdelphij EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec))); 1110276788Sdelphij ND_PRINT((ndo, " %u.%06u", 1111127675Sbms EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec), 1112276788Sdelphij EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec))); 1113276788Sdelphij ND_PRINT((ndo, " %u.%06u", 1114127675Sbms EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec), 1115276788Sdelphij EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec))); 111618976Sdfr } else { 1117276788Sdelphij ND_TCHECK(fap->fa2_ctime); 1118276788Sdelphij ND_PRINT((ndo, " nlink %d rdev 0x%x fsid 0x%x nodeid 0x%x a/m/ctime", 1119127675Sbms EXTRACT_32BITS(&fap->fa_nlink), 1120127675Sbms EXTRACT_32BITS(&fap->fa2_rdev), 1121127675Sbms EXTRACT_32BITS(&fap->fa2_fsid), 1122276788Sdelphij EXTRACT_32BITS(&fap->fa2_fileid))); 1123276788Sdelphij ND_PRINT((ndo, " %u.%06u", 1124127675Sbms EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec), 1125276788Sdelphij EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec))); 1126276788Sdelphij ND_PRINT((ndo, " %u.%06u", 1127127675Sbms EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec), 1128276788Sdelphij EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec))); 1129276788Sdelphij ND_PRINT((ndo, " %u.%06u", 1130127675Sbms EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec), 1131276788Sdelphij EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec))); 113218976Sdfr } 113317680Spst } 1134276788Sdelphij return ((const uint32_t *)((unsigned char *)dp + 113518976Sdfr (v3 ? NFSX_V3FATTR : NFSX_V2FATTR))); 113626184Sfennertrunc: 113726184Sfenner return (NULL); 113817680Spst} 113917680Spst 114017680Spststatic int 1141276788Sdelphijparseattrstat(netdissect_options *ndo, 1142276788Sdelphij const uint32_t *dp, int verbose, int v3) 114317680Spst{ 114418976Sdfr int er; 114518976Sdfr 1146276788Sdelphij dp = parsestatus(ndo, dp, &er); 1147111729Sfenner if (dp == NULL) 114817680Spst return (0); 1149111729Sfenner if (er) 1150111729Sfenner return (1); 115117680Spst 1152276788Sdelphij return (parsefattr(ndo, dp, verbose, v3) != NULL); 115317680Spst} 115417680Spst 115517680Spststatic int 1156276788Sdelphijparsediropres(netdissect_options *ndo, 1157276788Sdelphij const uint32_t *dp) 115817680Spst{ 115918976Sdfr int er; 116018976Sdfr 1161276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 116217680Spst return (0); 1163111729Sfenner if (er) 1164111729Sfenner return (1); 116517680Spst 1166276788Sdelphij dp = parsefh(ndo, dp, 0); 116717680Spst if (dp == NULL) 116817680Spst return (0); 116917680Spst 1170276788Sdelphij return (parsefattr(ndo, dp, ndo->ndo_vflag, 0) != NULL); 117117680Spst} 117217680Spst 117317680Spststatic int 1174276788Sdelphijparselinkres(netdissect_options *ndo, 1175276788Sdelphij const uint32_t *dp, int v3) 117617680Spst{ 117718976Sdfr int er; 117818976Sdfr 1179276788Sdelphij dp = parsestatus(ndo, dp, &er); 1180111729Sfenner if (dp == NULL) 118117680Spst return(0); 1182111729Sfenner if (er) 1183111729Sfenner return(1); 1184276788Sdelphij if (v3 && !(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 118518976Sdfr return (0); 1186276788Sdelphij ND_PRINT((ndo, " ")); 1187276788Sdelphij return (parsefn(ndo, dp) != NULL); 118817680Spst} 118917680Spst 119017680Spststatic int 1191276788Sdelphijparsestatfs(netdissect_options *ndo, 1192276788Sdelphij const uint32_t *dp, int v3) 119317680Spst{ 119418976Sdfr const struct nfs_statfs *sfsp; 119518976Sdfr int er; 119617680Spst 1197276788Sdelphij dp = parsestatus(ndo, dp, &er); 1198111729Sfenner if (dp == NULL) 119975118Sfenner return (0); 1200111729Sfenner if (!v3 && er) 1201111729Sfenner return (1); 120217680Spst 1203276788Sdelphij if (ndo->ndo_qflag) 120418976Sdfr return(1); 120518976Sdfr 120618976Sdfr if (v3) { 1207276788Sdelphij if (ndo->ndo_vflag) 1208276788Sdelphij ND_PRINT((ndo, " POST:")); 1209276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 121018976Sdfr return (0); 121117680Spst } 121217680Spst 1213276788Sdelphij ND_TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS)); 121418976Sdfr 121518976Sdfr sfsp = (const struct nfs_statfs *)dp; 121618976Sdfr 121718976Sdfr if (v3) { 1218276788Sdelphij ND_PRINT((ndo, " tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64, 1219276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_tbytes), 1220276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_fbytes), 1221276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_abytes))); 1222276788Sdelphij if (ndo->ndo_vflag) { 1223276788Sdelphij ND_PRINT((ndo, " tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u", 1224276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_tfiles), 1225276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_ffiles), 1226276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfsp->sf_afiles), 1227276788Sdelphij EXTRACT_32BITS(&sfsp->sf_invarsec))); 122818976Sdfr } 122918976Sdfr } else { 1230276788Sdelphij ND_PRINT((ndo, " tsize %d bsize %d blocks %d bfree %d bavail %d", 1231127675Sbms EXTRACT_32BITS(&sfsp->sf_tsize), 1232127675Sbms EXTRACT_32BITS(&sfsp->sf_bsize), 1233127675Sbms EXTRACT_32BITS(&sfsp->sf_blocks), 1234127675Sbms EXTRACT_32BITS(&sfsp->sf_bfree), 1235276788Sdelphij EXTRACT_32BITS(&sfsp->sf_bavail))); 123618976Sdfr } 123718976Sdfr 123817680Spst return (1); 123926184Sfennertrunc: 124026184Sfenner return (0); 124117680Spst} 124217680Spst 124317680Spststatic int 1244276788Sdelphijparserddires(netdissect_options *ndo, 1245276788Sdelphij const uint32_t *dp) 124617680Spst{ 124718976Sdfr int er; 124818976Sdfr 1249276788Sdelphij dp = parsestatus(ndo, dp, &er); 1250111729Sfenner if (dp == NULL) 125117680Spst return (0); 1252111729Sfenner if (er) 1253111729Sfenner return (1); 1254276788Sdelphij if (ndo->ndo_qflag) 125518976Sdfr return (1); 125618976Sdfr 1257276788Sdelphij ND_TCHECK(dp[2]); 1258276788Sdelphij ND_PRINT((ndo, " offset 0x%x size %d ", 1259276788Sdelphij EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1]))); 126018976Sdfr if (dp[2] != 0) 1261276788Sdelphij ND_PRINT((ndo, " eof")); 126218976Sdfr 126318976Sdfr return (1); 126426184Sfennertrunc: 126526184Sfenner return (0); 126618976Sdfr} 126718976Sdfr 1268276788Sdelphijstatic const uint32_t * 1269276788Sdelphijparse_wcc_attr(netdissect_options *ndo, 1270276788Sdelphij const uint32_t *dp) 127118976Sdfr{ 1272276788Sdelphij ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0]))); 1273276788Sdelphij ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u", 1274127675Sbms EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]), 1275276788Sdelphij EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5]))); 127618976Sdfr return (dp + 6); 127718976Sdfr} 127818976Sdfr 127918976Sdfr/* 128018976Sdfr * Pre operation attributes. Print only if vflag > 1. 128118976Sdfr */ 1282276788Sdelphijstatic const uint32_t * 1283276788Sdelphijparse_pre_op_attr(netdissect_options *ndo, 1284276788Sdelphij const uint32_t *dp, int verbose) 128518976Sdfr{ 1286276788Sdelphij ND_TCHECK(dp[0]); 1287127675Sbms if (!EXTRACT_32BITS(&dp[0])) 128818976Sdfr return (dp + 1); 128918976Sdfr dp++; 1290276788Sdelphij ND_TCHECK2(*dp, 24); 129118976Sdfr if (verbose > 1) { 1292276788Sdelphij return parse_wcc_attr(ndo, dp); 129318976Sdfr } else { 129418976Sdfr /* If not verbose enough, just skip over wcc_attr */ 129518976Sdfr return (dp + 6); 129617680Spst } 129726184Sfennertrunc: 129826184Sfenner return (NULL); 129918976Sdfr} 130017680Spst 130118976Sdfr/* 130218976Sdfr * Post operation attributes are printed if vflag >= 1 130318976Sdfr */ 1304276788Sdelphijstatic const uint32_t * 1305276788Sdelphijparse_post_op_attr(netdissect_options *ndo, 1306276788Sdelphij const uint32_t *dp, int verbose) 130718976Sdfr{ 1308276788Sdelphij ND_TCHECK(dp[0]); 1309127675Sbms if (!EXTRACT_32BITS(&dp[0])) 131018976Sdfr return (dp + 1); 131118976Sdfr dp++; 131218976Sdfr if (verbose) { 1313276788Sdelphij return parsefattr(ndo, dp, verbose, 1); 131418976Sdfr } else 1315276788Sdelphij return (dp + (NFSX_V3FATTR / sizeof (uint32_t))); 131626184Sfennertrunc: 131726184Sfenner return (NULL); 131818976Sdfr} 131918976Sdfr 1320276788Sdelphijstatic const uint32_t * 1321276788Sdelphijparse_wcc_data(netdissect_options *ndo, 1322276788Sdelphij const uint32_t *dp, int verbose) 132318976Sdfr{ 132418976Sdfr if (verbose > 1) 1325276788Sdelphij ND_PRINT((ndo, " PRE:")); 1326276788Sdelphij if (!(dp = parse_pre_op_attr(ndo, dp, verbose))) 132775118Sfenner return (0); 132818976Sdfr 132918976Sdfr if (verbose) 1330276788Sdelphij ND_PRINT((ndo, " POST:")); 1331276788Sdelphij return parse_post_op_attr(ndo, dp, verbose); 133218976Sdfr} 133318976Sdfr 1334276788Sdelphijstatic const uint32_t * 1335276788Sdelphijparsecreateopres(netdissect_options *ndo, 1336276788Sdelphij const uint32_t *dp, int verbose) 133718976Sdfr{ 133818976Sdfr int er; 133918976Sdfr 1340276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 134175118Sfenner return (0); 134218976Sdfr if (er) 1343276788Sdelphij dp = parse_wcc_data(ndo, dp, verbose); 134418976Sdfr else { 1345276788Sdelphij ND_TCHECK(dp[0]); 1346127675Sbms if (!EXTRACT_32BITS(&dp[0])) 134718976Sdfr return (dp + 1); 134818976Sdfr dp++; 1349276788Sdelphij if (!(dp = parsefh(ndo, dp, 1))) 135075118Sfenner return (0); 135118976Sdfr if (verbose) { 1352276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, verbose))) 135375118Sfenner return (0); 1354276788Sdelphij if (ndo->ndo_vflag > 1) { 1355276788Sdelphij ND_PRINT((ndo, " dir attr:")); 1356276788Sdelphij dp = parse_wcc_data(ndo, dp, verbose); 135718976Sdfr } 135818976Sdfr } 135918976Sdfr } 136018976Sdfr return (dp); 136126184Sfennertrunc: 136226184Sfenner return (NULL); 136318976Sdfr} 136418976Sdfr 136518976Sdfrstatic int 1366276788Sdelphijparsewccres(netdissect_options *ndo, 1367276788Sdelphij const uint32_t *dp, int verbose) 136818976Sdfr{ 136918976Sdfr int er; 137018976Sdfr 1371276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 137218976Sdfr return (0); 1373276788Sdelphij return parse_wcc_data(ndo, dp, verbose) != 0; 137418976Sdfr} 137518976Sdfr 1376276788Sdelphijstatic const uint32_t * 1377276788Sdelphijparsev3rddirres(netdissect_options *ndo, 1378276788Sdelphij const uint32_t *dp, int verbose) 137918976Sdfr{ 138018976Sdfr int er; 138118976Sdfr 1382276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 138375118Sfenner return (0); 1384276788Sdelphij if (ndo->ndo_vflag) 1385276788Sdelphij ND_PRINT((ndo, " POST:")); 1386276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, verbose))) 138775118Sfenner return (0); 138818976Sdfr if (er) 138918976Sdfr return dp; 1390276788Sdelphij if (ndo->ndo_vflag) { 1391276788Sdelphij ND_TCHECK(dp[1]); 1392276788Sdelphij ND_PRINT((ndo, " verf %08x%08x", dp[0], dp[1])); 139318976Sdfr dp += 2; 139418976Sdfr } 139518976Sdfr return dp; 139626184Sfennertrunc: 139726184Sfenner return (NULL); 139818976Sdfr} 139918976Sdfr 140018976Sdfrstatic int 1401276788Sdelphijparsefsinfo(netdissect_options *ndo, 1402276788Sdelphij const uint32_t *dp) 140318976Sdfr{ 140418976Sdfr struct nfsv3_fsinfo *sfp; 140518976Sdfr int er; 140618976Sdfr 1407276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 140818976Sdfr return (0); 1409276788Sdelphij if (ndo->ndo_vflag) 1410276788Sdelphij ND_PRINT((ndo, " POST:")); 1411276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 141218976Sdfr return (0); 141318976Sdfr if (er) 141418976Sdfr return (1); 141518976Sdfr 141618976Sdfr sfp = (struct nfsv3_fsinfo *)dp; 1417276788Sdelphij ND_TCHECK(*sfp); 1418276788Sdelphij ND_PRINT((ndo, " rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u", 1419127675Sbms EXTRACT_32BITS(&sfp->fs_rtmax), 1420127675Sbms EXTRACT_32BITS(&sfp->fs_rtpref), 1421127675Sbms EXTRACT_32BITS(&sfp->fs_wtmax), 1422127675Sbms EXTRACT_32BITS(&sfp->fs_wtpref), 1423276788Sdelphij EXTRACT_32BITS(&sfp->fs_dtpref))); 1424276788Sdelphij if (ndo->ndo_vflag) { 1425276788Sdelphij ND_PRINT((ndo, " rtmult %u wtmult %u maxfsz %" PRIu64, 1426127675Sbms EXTRACT_32BITS(&sfp->fs_rtmult), 1427146778Ssam EXTRACT_32BITS(&sfp->fs_wtmult), 1428276788Sdelphij EXTRACT_64BITS((uint32_t *)&sfp->fs_maxfilesize))); 1429276788Sdelphij ND_PRINT((ndo, " delta %u.%06u ", 1430127675Sbms EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec), 1431276788Sdelphij EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec))); 143218976Sdfr } 1433111729Sfenner return (1); 1434111729Sfennertrunc: 143575118Sfenner return (0); 143618976Sdfr} 143718976Sdfr 143818976Sdfrstatic int 1439276788Sdelphijparsepathconf(netdissect_options *ndo, 1440276788Sdelphij const uint32_t *dp) 144118976Sdfr{ 144218976Sdfr int er; 144318976Sdfr struct nfsv3_pathconf *spp; 144418976Sdfr 1445276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 144618976Sdfr return (0); 1447276788Sdelphij if (ndo->ndo_vflag) 1448276788Sdelphij ND_PRINT((ndo, " POST:")); 1449276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 145018976Sdfr return (0); 145118976Sdfr if (er) 145218976Sdfr return (1); 145318976Sdfr 145418976Sdfr spp = (struct nfsv3_pathconf *)dp; 1455276788Sdelphij ND_TCHECK(*spp); 145618976Sdfr 1457276788Sdelphij ND_PRINT((ndo, " linkmax %u namemax %u %s %s %s %s", 1458127675Sbms EXTRACT_32BITS(&spp->pc_linkmax), 1459127675Sbms EXTRACT_32BITS(&spp->pc_namemax), 1460127675Sbms EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "", 1461127675Sbms EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "", 1462127675Sbms EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "", 1463276788Sdelphij EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : "")); 1464111729Sfenner return (1); 1465111729Sfennertrunc: 146675118Sfenner return (0); 146717680Spst} 146875118Sfenner 146917680Spststatic void 1470276788Sdelphijinterp_reply(netdissect_options *ndo, 1471276788Sdelphij const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers, int length) 147217680Spst{ 1473276788Sdelphij register const uint32_t *dp; 147418976Sdfr register int v3; 147518976Sdfr int er; 147617680Spst 147718976Sdfr v3 = (vers == NFS_VER3); 147818976Sdfr 147918976Sdfr if (!v3 && proc < NFS_NPROCS) 148018976Sdfr proc = nfsv3_procid[proc]; 148118976Sdfr 1482276788Sdelphij ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc))); 148317680Spst switch (proc) { 148417680Spst 148517680Spst case NFSPROC_GETATTR: 1486276788Sdelphij dp = parserep(ndo, rp, length); 1487276788Sdelphij if (dp != NULL && parseattrstat(ndo, dp, !ndo->ndo_qflag, v3) != 0) 148817680Spst return; 148917680Spst break; 149017680Spst 149117680Spst case NFSPROC_SETATTR: 1492276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 149317680Spst return; 149418976Sdfr if (v3) { 1495276788Sdelphij if (parsewccres(ndo, dp, ndo->ndo_vflag)) 149618976Sdfr return; 149718976Sdfr } else { 1498276788Sdelphij if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0) != 0) 149918976Sdfr return; 150018976Sdfr } 150117680Spst break; 150217680Spst 150317680Spst case NFSPROC_LOOKUP: 1504276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 150518976Sdfr break; 150618976Sdfr if (v3) { 1507276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 150818976Sdfr break; 150918976Sdfr if (er) { 1510276788Sdelphij if (ndo->ndo_vflag > 1) { 1511276788Sdelphij ND_PRINT((ndo, " post dattr:")); 1512276788Sdelphij dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag); 151318976Sdfr } 151418976Sdfr } else { 1515276788Sdelphij if (!(dp = parsefh(ndo, dp, v3))) 151618976Sdfr break; 1517276788Sdelphij if ((dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)) && 1518276788Sdelphij ndo->ndo_vflag > 1) { 1519276788Sdelphij ND_PRINT((ndo, " post dattr:")); 1520276788Sdelphij dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag); 152118976Sdfr } 152218976Sdfr } 152375118Sfenner if (dp) 152418976Sdfr return; 152518976Sdfr } else { 1526276788Sdelphij if (parsediropres(ndo, dp) != 0) 152718976Sdfr return; 152818976Sdfr } 152917680Spst break; 153017680Spst 153118976Sdfr case NFSPROC_ACCESS: 1532276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 153398527Sfenner break; 1534276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 153518976Sdfr break; 1536276788Sdelphij if (ndo->ndo_vflag) 1537276788Sdelphij ND_PRINT((ndo, " attr:")); 1538276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 153918976Sdfr break; 154018976Sdfr if (!er) 1541276788Sdelphij ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0]))); 154218976Sdfr return; 154318976Sdfr 154417680Spst case NFSPROC_READLINK: 1545276788Sdelphij dp = parserep(ndo, rp, length); 1546276788Sdelphij if (dp != NULL && parselinkres(ndo, dp, v3) != 0) 154717680Spst return; 154817680Spst break; 154917680Spst 155017680Spst case NFSPROC_READ: 1551276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 155218976Sdfr break; 155318976Sdfr if (v3) { 1554276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 155518976Sdfr break; 1556276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 155718976Sdfr break; 155818976Sdfr if (er) 155918976Sdfr return; 1560276788Sdelphij if (ndo->ndo_vflag) { 1561276788Sdelphij ND_TCHECK(dp[1]); 1562276788Sdelphij ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0]))); 1563127675Sbms if (EXTRACT_32BITS(&dp[1])) 1564276788Sdelphij ND_PRINT((ndo, " EOF")); 156518976Sdfr } 156617680Spst return; 156718976Sdfr } else { 1568276788Sdelphij if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0) != 0) 156918976Sdfr return; 157018976Sdfr } 157117680Spst break; 157217680Spst 157317680Spst case NFSPROC_WRITE: 1574276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 157518976Sdfr break; 157618976Sdfr if (v3) { 1577276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 157818976Sdfr break; 1579276788Sdelphij if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag))) 158018976Sdfr break; 158118976Sdfr if (er) 158218976Sdfr return; 1583276788Sdelphij if (ndo->ndo_vflag) { 1584276788Sdelphij ND_TCHECK(dp[0]); 1585276788Sdelphij ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0]))); 1586276788Sdelphij if (ndo->ndo_vflag > 1) { 1587276788Sdelphij ND_TCHECK(dp[1]); 1588276788Sdelphij ND_PRINT((ndo, " <%s>", 158975118Sfenner tok2str(nfsv3_writemodes, 1590276788Sdelphij NULL, EXTRACT_32BITS(&dp[1])))); 159118976Sdfr } 159218976Sdfr return; 159318976Sdfr } 159418976Sdfr } else { 1595276788Sdelphij if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3) != 0) 159618976Sdfr return; 159718976Sdfr } 159817680Spst break; 159917680Spst 160017680Spst case NFSPROC_CREATE: 160118976Sdfr case NFSPROC_MKDIR: 1602276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 160318976Sdfr break; 160418976Sdfr if (v3) { 1605276788Sdelphij if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0) 160618976Sdfr return; 160718976Sdfr } else { 1608276788Sdelphij if (parsediropres(ndo, dp) != 0) 160918976Sdfr return; 161018976Sdfr } 161118976Sdfr break; 161218976Sdfr 161318976Sdfr case NFSPROC_SYMLINK: 1614276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 161518976Sdfr break; 161618976Sdfr if (v3) { 1617276788Sdelphij if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0) 161818976Sdfr return; 161918976Sdfr } else { 1620276788Sdelphij if (parsestatus(ndo, dp, &er) != 0) 162118976Sdfr return; 162218976Sdfr } 162318976Sdfr break; 162418976Sdfr 162518976Sdfr case NFSPROC_MKNOD: 1626276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 162718976Sdfr break; 1628276788Sdelphij if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0) 162917680Spst return; 163017680Spst break; 163117680Spst 163217680Spst case NFSPROC_REMOVE: 163318976Sdfr case NFSPROC_RMDIR: 1634276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 163518976Sdfr break; 163618976Sdfr if (v3) { 1637276788Sdelphij if (parsewccres(ndo, dp, ndo->ndo_vflag)) 163818976Sdfr return; 163918976Sdfr } else { 1640276788Sdelphij if (parsestatus(ndo, dp, &er) != 0) 164118976Sdfr return; 164218976Sdfr } 164318976Sdfr break; 164418976Sdfr 164517680Spst case NFSPROC_RENAME: 1646276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 164718976Sdfr break; 164818976Sdfr if (v3) { 1649276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 165018976Sdfr break; 1651276788Sdelphij if (ndo->ndo_vflag) { 1652276788Sdelphij ND_PRINT((ndo, " from:")); 1653276788Sdelphij if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag))) 165418976Sdfr break; 1655276788Sdelphij ND_PRINT((ndo, " to:")); 1656276788Sdelphij if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag))) 165718976Sdfr break; 165818976Sdfr } 165917680Spst return; 166018976Sdfr } else { 1661276788Sdelphij if (parsestatus(ndo, dp, &er) != 0) 166218976Sdfr return; 166318976Sdfr } 166417680Spst break; 166517680Spst 166617680Spst case NFSPROC_LINK: 1667276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 166818976Sdfr break; 166918976Sdfr if (v3) { 1670276788Sdelphij if (!(dp = parsestatus(ndo, dp, &er))) 167118976Sdfr break; 1672276788Sdelphij if (ndo->ndo_vflag) { 1673276788Sdelphij ND_PRINT((ndo, " file POST:")); 1674276788Sdelphij if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) 167518976Sdfr break; 1676276788Sdelphij ND_PRINT((ndo, " dir:")); 1677276788Sdelphij if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag))) 167818976Sdfr break; 167918976Sdfr return; 168018976Sdfr } 168118976Sdfr } else { 1682276788Sdelphij if (parsestatus(ndo, dp, &er) != 0) 168318976Sdfr return; 168418976Sdfr } 168517680Spst break; 168617680Spst 168718976Sdfr case NFSPROC_READDIR: 1688276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 168918976Sdfr break; 169018976Sdfr if (v3) { 1691276788Sdelphij if (parsev3rddirres(ndo, dp, ndo->ndo_vflag)) 169218976Sdfr return; 169318976Sdfr } else { 1694276788Sdelphij if (parserddires(ndo, dp) != 0) 169518976Sdfr return; 169618976Sdfr } 169718976Sdfr break; 169818976Sdfr 169918976Sdfr case NFSPROC_READDIRPLUS: 1700276788Sdelphij if (!(dp = parserep(ndo, rp, length))) 170118976Sdfr break; 1702276788Sdelphij if (parsev3rddirres(ndo, dp, ndo->ndo_vflag)) 170317680Spst return; 170417680Spst break; 170517680Spst 170618976Sdfr case NFSPROC_FSSTAT: 1707276788Sdelphij dp = parserep(ndo, rp, length); 1708276788Sdelphij if (dp != NULL && parsestatfs(ndo, dp, v3) != 0) 170917680Spst return; 171017680Spst break; 171117680Spst 171218976Sdfr case NFSPROC_FSINFO: 1713276788Sdelphij dp = parserep(ndo, rp, length); 1714276788Sdelphij if (dp != NULL && parsefsinfo(ndo, dp) != 0) 171517680Spst return; 171617680Spst break; 171717680Spst 171818976Sdfr case NFSPROC_PATHCONF: 1719276788Sdelphij dp = parserep(ndo, rp, length); 1720276788Sdelphij if (dp != NULL && parsepathconf(ndo, dp) != 0) 172117680Spst return; 172217680Spst break; 172317680Spst 172418976Sdfr case NFSPROC_COMMIT: 1725276788Sdelphij dp = parserep(ndo, rp, length); 1726276788Sdelphij if (dp != NULL && parsewccres(ndo, dp, ndo->ndo_vflag) != 0) 172717680Spst return; 172817680Spst break; 172917680Spst 173017680Spst default: 173117680Spst return; 173217680Spst } 173318976Sdfrtrunc: 173426183Sfenner if (!nfserr) 1735276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 173617680Spst} 1737