1999-10-08 07:47:09 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that: (1) source code distributions
|
|
|
|
* retain the above copyright notice and this paragraph in its entirety, (2)
|
|
|
|
* distributions including binary code include the above copyright notice and
|
|
|
|
* this paragraph in its entirety in the documentation or other materials
|
|
|
|
* provided with the distribution, and (3) all advertising materials mentioning
|
|
|
|
* features or use of this software display the following acknowledgement:
|
|
|
|
* ``This product includes software developed by the University of California,
|
|
|
|
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
|
|
|
* the University nor the names of its contributors may be used to endorse
|
|
|
|
* or promote products derived from this software without specific prior
|
|
|
|
* written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*/
|
|
|
|
|
1999-11-21 17:36:43 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
1999-10-08 07:47:09 +08:00
|
|
|
#endif
|
|
|
|
|
2002-08-01 16:52:55 +08:00
|
|
|
#include <tcpdump-stdinc.h>
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "interface.h"
|
|
|
|
#include "addrtoname.h"
|
2002-12-11 15:13:49 +08:00
|
|
|
#include "extract.h"
|
1999-10-08 07:47:09 +08:00
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
#include "nfs.h"
|
1999-10-08 07:47:09 +08:00
|
|
|
#include "nfsfh.h"
|
|
|
|
|
2000-09-23 16:54:24 +08:00
|
|
|
#include "ip.h"
|
2000-10-07 13:53:09 +08:00
|
|
|
#ifdef INET6
|
|
|
|
#include "ip6.h"
|
|
|
|
#endif
|
2004-12-27 08:41:29 +08:00
|
|
|
#include "rpc_auth.h"
|
|
|
|
#include "rpc_msg.h"
|
2000-09-23 16:54:24 +08:00
|
|
|
|
2013-12-26 22:08:06 +08:00
|
|
|
static const char tstr[] = " [|nfs]";
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static void nfs_printfh(netdissect_options *, const uint32_t *, const u_int);
|
2014-04-01 20:05:33 +08:00
|
|
|
static int xid_map_enter(netdissect_options *, const struct sunrpc_msg *, const u_char *);
|
2013-07-11 21:03:03 +08:00
|
|
|
static int xid_map_find(const struct sunrpc_msg *, const u_char *,
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t *, uint32_t *);
|
|
|
|
static void interp_reply(netdissect_options *, const struct sunrpc_msg *, uint32_t, uint32_t, int);
|
|
|
|
static const uint32_t *parse_post_op_attr(netdissect_options *, const uint32_t *, int);
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Mapping of old NFS Version 2 RPC numbers to generic numbers.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t nfsv3_procid[NFS_NPROCS] = {
|
1999-11-21 13:43:49 +08:00
|
|
|
NFSPROC_NULL,
|
|
|
|
NFSPROC_GETATTR,
|
|
|
|
NFSPROC_SETATTR,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_LOOKUP,
|
|
|
|
NFSPROC_READLINK,
|
|
|
|
NFSPROC_READ,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_WRITE,
|
|
|
|
NFSPROC_CREATE,
|
|
|
|
NFSPROC_REMOVE,
|
|
|
|
NFSPROC_RENAME,
|
|
|
|
NFSPROC_LINK,
|
|
|
|
NFSPROC_SYMLINK,
|
|
|
|
NFSPROC_MKDIR,
|
|
|
|
NFSPROC_RMDIR,
|
|
|
|
NFSPROC_READDIR,
|
|
|
|
NFSPROC_FSSTAT,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP
|
|
|
|
};
|
|
|
|
|
2014-04-13 23:28:05 +08:00
|
|
|
static const struct tok nfsproc_str[] = {
|
|
|
|
{ NFSPROC_NOOP, "nop" },
|
|
|
|
{ NFSPROC_NULL, "null" },
|
|
|
|
{ NFSPROC_GETATTR, "getattr" },
|
|
|
|
{ NFSPROC_SETATTR, "setattr" },
|
|
|
|
{ NFSPROC_LOOKUP, "lookup" },
|
|
|
|
{ NFSPROC_ACCESS, "access" },
|
|
|
|
{ NFSPROC_READLINK, "readlink" },
|
|
|
|
{ NFSPROC_READ, "read" },
|
|
|
|
{ NFSPROC_WRITE, "write" },
|
|
|
|
{ NFSPROC_CREATE, "create" },
|
|
|
|
{ NFSPROC_MKDIR, "mkdir" },
|
|
|
|
{ NFSPROC_SYMLINK, "symlink" },
|
|
|
|
{ NFSPROC_MKNOD, "mknod" },
|
|
|
|
{ NFSPROC_REMOVE, "remove" },
|
|
|
|
{ NFSPROC_RMDIR, "rmdir" },
|
|
|
|
{ NFSPROC_RENAME, "rename" },
|
|
|
|
{ NFSPROC_LINK, "link" },
|
|
|
|
{ NFSPROC_READDIR, "readdir" },
|
|
|
|
{ NFSPROC_READDIRPLUS, "readdirplus" },
|
|
|
|
{ NFSPROC_FSSTAT, "fsstat" },
|
|
|
|
{ NFSPROC_FSINFO, "fsinfo" },
|
|
|
|
{ NFSPROC_PATHCONF, "pathconf" },
|
|
|
|
{ NFSPROC_COMMIT, "commit" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2000-08-04 02:52:24 +08:00
|
|
|
/*
|
|
|
|
* NFS V2 and V3 status values.
|
|
|
|
*
|
|
|
|
* Some of these come from the RFCs for NFS V2 and V3, with the message
|
|
|
|
* strings taken from the FreeBSD C library "errlst.c".
|
|
|
|
*
|
|
|
|
* Others are errors that are not in the RFC but that I suspect some
|
|
|
|
* NFS servers could return; the values are FreeBSD errno values, as
|
|
|
|
* the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS
|
|
|
|
* was primarily BSD-derived.
|
|
|
|
*/
|
2013-09-25 00:46:24 +08:00
|
|
|
static const struct tok status2str[] = {
|
2000-08-04 02:52:24 +08:00
|
|
|
{ 1, "Operation not permitted" }, /* EPERM */
|
|
|
|
{ 2, "No such file or directory" }, /* ENOENT */
|
|
|
|
{ 5, "Input/output error" }, /* EIO */
|
|
|
|
{ 6, "Device not configured" }, /* ENXIO */
|
|
|
|
{ 11, "Resource deadlock avoided" }, /* EDEADLK */
|
|
|
|
{ 12, "Cannot allocate memory" }, /* ENOMEM */
|
|
|
|
{ 13, "Permission denied" }, /* EACCES */
|
|
|
|
{ 17, "File exists" }, /* EEXIST */
|
|
|
|
{ 18, "Cross-device link" }, /* EXDEV */
|
|
|
|
{ 19, "Operation not supported by device" }, /* ENODEV */
|
|
|
|
{ 20, "Not a directory" }, /* ENOTDIR */
|
|
|
|
{ 21, "Is a directory" }, /* EISDIR */
|
|
|
|
{ 22, "Invalid argument" }, /* EINVAL */
|
|
|
|
{ 26, "Text file busy" }, /* ETXTBSY */
|
|
|
|
{ 27, "File too large" }, /* EFBIG */
|
|
|
|
{ 28, "No space left on device" }, /* ENOSPC */
|
|
|
|
{ 30, "Read-only file system" }, /* EROFS */
|
|
|
|
{ 31, "Too many links" }, /* EMLINK */
|
|
|
|
{ 45, "Operation not supported" }, /* EOPNOTSUPP */
|
|
|
|
{ 62, "Too many levels of symbolic links" }, /* ELOOP */
|
|
|
|
{ 63, "File name too long" }, /* ENAMETOOLONG */
|
|
|
|
{ 66, "Directory not empty" }, /* ENOTEMPTY */
|
|
|
|
{ 69, "Disc quota exceeded" }, /* EDQUOT */
|
|
|
|
{ 70, "Stale NFS file handle" }, /* ESTALE */
|
|
|
|
{ 71, "Too many levels of remote in path" }, /* EREMOTE */
|
|
|
|
{ 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */
|
|
|
|
{ 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */
|
|
|
|
{ 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */
|
|
|
|
{ 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */
|
|
|
|
{ 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */
|
|
|
|
{ 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */
|
|
|
|
{ 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */
|
|
|
|
{ 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */
|
|
|
|
{ 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2013-09-25 00:46:24 +08:00
|
|
|
static const struct tok nfsv3_writemodes[] = {
|
2000-01-28 08:04:19 +08:00
|
|
|
{ 0, "unstable" },
|
|
|
|
{ 1, "datasync" },
|
|
|
|
{ 2, "filesync" },
|
|
|
|
{ 0, NULL }
|
1999-11-21 13:43:49 +08:00
|
|
|
};
|
|
|
|
|
2013-09-25 00:46:24 +08:00
|
|
|
static const struct tok type2str[] = {
|
1999-11-21 13:43:49 +08:00
|
|
|
{ NFNON, "NON" },
|
|
|
|
{ NFREG, "REG" },
|
|
|
|
{ NFDIR, "DIR" },
|
|
|
|
{ NFBLK, "BLK" },
|
|
|
|
{ NFCHR, "CHR" },
|
|
|
|
{ NFLNK, "LNK" },
|
|
|
|
{ NFFIFO, "FIFO" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2014-04-13 23:28:05 +08:00
|
|
|
static const struct tok sunrpc_auth_str[] = {
|
|
|
|
{ SUNRPC_AUTH_OK, "OK" },
|
|
|
|
{ SUNRPC_AUTH_BADCRED, "Bogus Credentials (seal broken)" },
|
|
|
|
{ SUNRPC_AUTH_REJECTEDCRED, "Rejected Credentials (client should begin new session)" },
|
|
|
|
{ SUNRPC_AUTH_BADVERF, "Bogus Verifier (seal broken)" },
|
|
|
|
{ SUNRPC_AUTH_REJECTEDVERF, "Verifier expired or was replayed" },
|
|
|
|
{ SUNRPC_AUTH_TOOWEAK, "Credentials are too weak" },
|
|
|
|
{ SUNRPC_AUTH_INVALIDRESP, "Bogus response verifier" },
|
|
|
|
{ SUNRPC_AUTH_FAILED, "Unknown failure" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct tok sunrpc_str[] = {
|
|
|
|
{ SUNRPC_PROG_UNAVAIL, "PROG_UNAVAIL" },
|
|
|
|
{ SUNRPC_PROG_MISMATCH, "PROG_MISMATCH" },
|
|
|
|
{ SUNRPC_PROC_UNAVAIL, "PROC_UNAVAIL" },
|
|
|
|
{ SUNRPC_GARBAGE_ARGS, "GARBAGE_ARGS" },
|
|
|
|
{ SUNRPC_SYSTEM_ERR, "SYSTEM_ERR" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2000-06-10 13:12:20 +08:00
|
|
|
static void
|
2014-04-01 20:05:33 +08:00
|
|
|
print_nfsaddr(netdissect_options *ndo,
|
|
|
|
const u_char *bp, const char *s, const char *d)
|
2000-06-10 13:12:20 +08:00
|
|
|
{
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip *ip;
|
2000-06-10 13:12:20 +08:00
|
|
|
#ifdef INET6
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip6_hdr *ip6;
|
2000-06-10 13:12:20 +08:00
|
|
|
char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN];
|
|
|
|
#else
|
2000-06-12 23:45:05 +08:00
|
|
|
#ifndef INET_ADDRSTRLEN
|
|
|
|
#define INET_ADDRSTRLEN 16
|
|
|
|
#endif
|
2000-06-10 13:12:20 +08:00
|
|
|
char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
srcaddr[0] = dstaddr[0] = '\0';
|
2015-04-27 08:24:42 +08:00
|
|
|
switch (IP_V((const struct ip *)bp)) {
|
2000-06-10 13:12:20 +08:00
|
|
|
case 4:
|
2015-04-27 08:24:42 +08:00
|
|
|
ip = (const struct ip *)bp;
|
2014-04-04 15:43:46 +08:00
|
|
|
strlcpy(srcaddr, ipaddr_string(ndo, &ip->ip_src), sizeof(srcaddr));
|
|
|
|
strlcpy(dstaddr, ipaddr_string(ndo, &ip->ip_dst), sizeof(dstaddr));
|
2000-06-10 13:12:20 +08:00
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case 6:
|
2015-04-27 08:24:42 +08:00
|
|
|
ip6 = (const struct ip6_hdr *)bp;
|
2014-04-04 15:43:46 +08:00
|
|
|
strlcpy(srcaddr, ip6addr_string(ndo, &ip6->ip6_src),
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(srcaddr));
|
2014-04-04 15:43:46 +08:00
|
|
|
strlcpy(dstaddr, ip6addr_string(ndo, &ip6->ip6_dst),
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(dstaddr));
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
strlcpy(srcaddr, "?", sizeof(srcaddr));
|
|
|
|
strlcpy(dstaddr, "?", sizeof(dstaddr));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s.%s > %s.%s: ", srcaddr, s, dstaddr, d));
|
2000-06-10 13:12:20 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parse_sattr3(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, struct nfsv3_sattr *sa3)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_modeset = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_modeset) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_mode = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_uidset = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_uidset) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_uid = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_gidset = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_gidset) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_gid = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_sizeset = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_sizeset) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_size = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_atimetype = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_mtimetype = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2002-12-11 15:13:49 +08:00
|
|
|
sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
|
|
|
sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return dp;
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return NULL;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
static int nfserr; /* true if we error rather than trunc */
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
static void
|
2014-04-01 20:05:33 +08:00
|
|
|
print_sattr3(netdissect_options *ndo,
|
|
|
|
const struct nfsv3_sattr *sa3, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
if (sa3->sa_modeset)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " mode %o", sa3->sa_mode));
|
1999-11-21 13:43:49 +08:00
|
|
|
if (sa3->sa_uidset)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " uid %u", sa3->sa_uid));
|
1999-11-21 13:43:49 +08:00
|
|
|
if (sa3->sa_gidset)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " gid %u", sa3->sa_gid));
|
1999-11-21 13:43:49 +08:00
|
|
|
if (verbose > 1) {
|
|
|
|
if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " atime %u.%06u", sa3->sa_atime.nfsv3_sec,
|
|
|
|
sa3->sa_atime.nfsv3_nsec));
|
1999-11-21 13:43:49 +08:00
|
|
|
if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " mtime %u.%06u", sa3->sa_mtime.nfsv3_sec,
|
|
|
|
sa3->sa_mtime.nfsv3_nsec));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
void
|
2014-04-01 20:05:33 +08:00
|
|
|
nfsreply_print(netdissect_options *ndo,
|
|
|
|
register const u_char *bp, u_int length,
|
|
|
|
register const u_char *bp2)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2004-12-27 08:41:29 +08:00
|
|
|
register const struct sunrpc_msg *rp;
|
2000-06-10 13:12:20 +08:00
|
|
|
char srcid[20], dstid[20]; /*fits 32bit*/
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
nfserr = 0; /* assume no error */
|
2004-12-27 08:41:29 +08:00
|
|
|
rp = (const struct sunrpc_msg *)bp;
|
2000-06-10 13:12:20 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(rp->rm_xid);
|
|
|
|
if (!ndo->ndo_nflag) {
|
2000-06-10 13:12:20 +08:00
|
|
|
strlcpy(srcid, "nfs", sizeof(srcid));
|
|
|
|
snprintf(dstid, sizeof(dstid), "%u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&rp->rm_xid));
|
2000-06-10 13:12:20 +08:00
|
|
|
} else {
|
|
|
|
snprintf(srcid, sizeof(srcid), "%u", NFS_PORT);
|
|
|
|
snprintf(dstid, sizeof(dstid), "%u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&rp->rm_xid));
|
2000-06-10 13:12:20 +08:00
|
|
|
}
|
2014-04-01 20:05:33 +08:00
|
|
|
print_nfsaddr(ndo, bp2, srcid, dstid);
|
2013-10-29 06:52:51 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
nfsreply_print_noaddr(ndo, bp, length, bp2);
|
2013-10-29 06:52:51 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
trunc:
|
|
|
|
if (!nfserr)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s", tstr));
|
2013-10-29 06:52:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-01 20:05:33 +08:00
|
|
|
nfsreply_print_noaddr(netdissect_options *ndo,
|
|
|
|
register const u_char *bp, u_int length,
|
|
|
|
register const u_char *bp2)
|
2013-10-29 06:52:51 +08:00
|
|
|
{
|
|
|
|
register const struct sunrpc_msg *rp;
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t proc, vers, reply_stat;
|
2013-10-29 06:52:51 +08:00
|
|
|
enum sunrpc_reject_stat rstat;
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t rlow;
|
|
|
|
uint32_t rhigh;
|
2013-10-29 06:52:51 +08:00
|
|
|
enum sunrpc_auth_stat rwhy;
|
|
|
|
|
|
|
|
nfserr = 0; /* assume no error */
|
|
|
|
rp = (const struct sunrpc_msg *)bp;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(rp->rm_reply.rp_stat);
|
2007-06-16 07:17:05 +08:00
|
|
|
reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat);
|
|
|
|
switch (reply_stat) {
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2007-06-16 03:04:39 +08:00
|
|
|
case SUNRPC_MSG_ACCEPTED:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "reply ok %u", length));
|
2007-06-16 03:04:39 +08:00
|
|
|
if (xid_map_find(rp, bp2, &proc, &vers) >= 0)
|
2014-04-01 20:05:33 +08:00
|
|
|
interp_reply(ndo, rp, proc, vers, length);
|
2007-06-16 03:04:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SUNRPC_MSG_DENIED:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "reply ERR %u: ", length));
|
|
|
|
ND_TCHECK(rp->rm_reply.rp_reject.rj_stat);
|
2007-06-16 03:04:39 +08:00
|
|
|
rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat);
|
|
|
|
switch (rstat) {
|
|
|
|
|
|
|
|
case SUNRPC_RPC_MISMATCH:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(rp->rm_reply.rp_reject.rj_vers.high);
|
2007-06-16 03:04:39 +08:00
|
|
|
rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low);
|
|
|
|
rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "RPC Version mismatch (%u-%u)", rlow, rhigh));
|
2007-06-16 03:04:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SUNRPC_AUTH_ERROR:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(rp->rm_reply.rp_reject.rj_why);
|
2007-06-16 03:04:39 +08:00
|
|
|
rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why);
|
2014-04-13 23:28:05 +08:00
|
|
|
ND_PRINT((ndo, "Auth %s", tok2str(sunrpc_auth_str, "Invalid failure code %u", rwhy)));
|
2007-06-16 03:04:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "Unknown reason for rejecting rpc message %u", (unsigned int)rstat));
|
2007-06-16 03:04:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "reply Unknown rpc response code=%u %u", reply_stat, length));
|
2007-06-16 03:04:39 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-12-22 11:08:04 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
trunc:
|
|
|
|
if (!nfserr)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s", tstr));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a pointer to the first file handle in the packet.
|
|
|
|
* If the packet was truncated, return 0.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsereq(netdissect_options *ndo,
|
|
|
|
register const struct sunrpc_msg *rp, register u_int length)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp;
|
1999-10-08 07:47:09 +08:00
|
|
|
register u_int len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find the start of the req data (if we captured it)
|
|
|
|
*/
|
2015-04-27 08:24:42 +08:00
|
|
|
dp = (const uint32_t *)&rp->rm_call.cb_cred;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2002-12-11 15:13:49 +08:00
|
|
|
len = EXTRACT_32BITS(&dp[1]);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (len < length) {
|
|
|
|
dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2002-12-11 15:13:49 +08:00
|
|
|
len = EXTRACT_32BITS(&dp[1]);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (len < length) {
|
|
|
|
dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(dp[0], 0);
|
1999-10-08 07:47:09 +08:00
|
|
|
return (dp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trunc:
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print out an NFS file handle and return a pointer to following word.
|
|
|
|
* If packet was truncated, return 0.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsefh(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2002-12-11 15:13:49 +08:00
|
|
|
u_int len;
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
len = EXTRACT_32BITS(dp) / 4;
|
1999-11-21 13:43:49 +08:00
|
|
|
dp++;
|
|
|
|
} else
|
|
|
|
len = NFSX_V2FH / 4;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ND_TTEST2(*dp, len * sizeof(*dp))) {
|
|
|
|
nfs_printfh(ndo, dp, len);
|
1999-11-21 13:43:49 +08:00
|
|
|
return (dp + len);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
1999-10-08 07:47:09 +08:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print out a file name and return pointer to 32-bit word past it.
|
|
|
|
* If packet was truncated, return 0.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsefn(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2014-04-23 15:20:40 +08:00
|
|
|
register uint32_t len;
|
1999-10-08 07:47:09 +08:00
|
|
|
register const u_char *cp;
|
|
|
|
|
|
|
|
/* Bail if we don't have the string length */
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(*dp);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
/* Fetch string length; convert to host order */
|
|
|
|
len = *dp++;
|
|
|
|
NTOHL(len);
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(*dp, ((len + 3) & ~3));
|
2000-01-28 08:04:19 +08:00
|
|
|
|
2015-04-27 08:24:42 +08:00
|
|
|
cp = (const u_char *)dp;
|
1999-10-08 07:47:09 +08:00
|
|
|
/* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
|
|
|
|
dp += ((len + 3) & ~3) / sizeof(*dp);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "\""));
|
2014-04-14 14:53:46 +08:00
|
|
|
if (fn_printn(ndo, cp, len, ndo->ndo_snapend)) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "\""));
|
2005-05-06 15:56:51 +08:00
|
|
|
goto trunc;
|
|
|
|
}
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "\""));
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
return (dp);
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return NULL;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print out file handle and file name.
|
|
|
|
* Return pointer to 32-bit word past file name.
|
|
|
|
* If packet was truncated (or there was some other error), return 0.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsefhn(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsefh(ndo, dp, v3);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (dp == NULL)
|
|
|
|
return (NULL);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " "));
|
|
|
|
return (parsefn(ndo, dp));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 06:52:51 +08:00
|
|
|
void
|
2014-04-01 20:05:33 +08:00
|
|
|
nfsreq_print_noaddr(netdissect_options *ndo,
|
|
|
|
register const u_char *bp, u_int length,
|
|
|
|
register const u_char *bp2)
|
2013-10-29 06:52:51 +08:00
|
|
|
{
|
|
|
|
register const struct sunrpc_msg *rp;
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp;
|
2013-10-29 06:52:51 +08:00
|
|
|
nfs_type type;
|
|
|
|
int v3;
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t proc;
|
|
|
|
uint32_t access_flags;
|
2013-10-29 06:52:51 +08:00
|
|
|
struct nfsv3_sattr sa3;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%d", length));
|
2013-10-29 06:52:51 +08:00
|
|
|
nfserr = 0; /* assume no error */
|
|
|
|
rp = (const struct sunrpc_msg *)bp;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!xid_map_enter(ndo, rp, bp2)) /* record proc number for later on */
|
2007-12-22 11:08:04 +08:00
|
|
|
goto trunc;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2002-12-11 15:13:49 +08:00
|
|
|
v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3);
|
|
|
|
proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
if (!v3 && proc < NFS_NPROCS)
|
|
|
|
proc = nfsv3_procid[proc];
|
|
|
|
|
2014-04-13 23:28:05 +08:00
|
|
|
ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
|
1999-11-21 13:43:49 +08:00
|
|
|
switch (proc) {
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
case NFSPROC_GETATTR:
|
|
|
|
case NFSPROC_SETATTR:
|
2014-04-13 23:28:05 +08:00
|
|
|
case NFSPROC_READLINK:
|
|
|
|
case NFSPROC_FSSTAT:
|
|
|
|
case NFSPROC_FSINFO:
|
|
|
|
case NFSPROC_PATHCONF:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
parsefh(ndo, dp, v3) != NULL)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_LOOKUP:
|
2014-04-13 23:28:05 +08:00
|
|
|
case NFSPROC_CREATE:
|
|
|
|
case NFSPROC_MKDIR:
|
|
|
|
case NFSPROC_REMOVE:
|
|
|
|
case NFSPROC_RMDIR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
parsefhn(ndo, dp, v3) != NULL)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_ACCESS:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
|
|
|
ND_TCHECK(dp[0]);
|
2010-01-27 04:09:24 +08:00
|
|
|
access_flags = EXTRACT_32BITS(&dp[0]);
|
|
|
|
if (access_flags & ~NFSV3ACCESS_FULL) {
|
|
|
|
/* NFSV3ACCESS definitions aren't up to date */
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %04x", access_flags));
|
2010-01-27 04:09:24 +08:00
|
|
|
} else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " NFS_ACCESS_FULL"));
|
2010-01-27 04:09:24 +08:00
|
|
|
} else {
|
|
|
|
char separator = ' ';
|
|
|
|
if (access_flags & NFSV3ACCESS_READ) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " NFS_ACCESS_READ"));
|
2010-01-27 04:09:24 +08:00
|
|
|
separator = '|';
|
|
|
|
}
|
|
|
|
if (access_flags & NFSV3ACCESS_LOOKUP) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%cNFS_ACCESS_LOOKUP", separator));
|
2010-01-27 04:09:24 +08:00
|
|
|
separator = '|';
|
|
|
|
}
|
|
|
|
if (access_flags & NFSV3ACCESS_MODIFY) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%cNFS_ACCESS_MODIFY", separator));
|
2010-01-27 04:09:24 +08:00
|
|
|
separator = '|';
|
|
|
|
}
|
|
|
|
if (access_flags & NFSV3ACCESS_EXTEND) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%cNFS_ACCESS_EXTEND", separator));
|
2010-01-27 04:09:24 +08:00
|
|
|
separator = '|';
|
|
|
|
}
|
|
|
|
if (access_flags & NFSV3ACCESS_DELETE) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%cNFS_ACCESS_DELETE", separator));
|
2010-01-27 04:09:24 +08:00
|
|
|
separator = '|';
|
|
|
|
}
|
|
|
|
if (access_flags & NFSV3ACCESS_EXECUTE)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%cNFS_ACCESS_EXECUTE", separator));
|
2010-01-27 04:09:24 +08:00
|
|
|
}
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
case NFSPROC_READ:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
1999-11-21 13:43:49 +08:00
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[2]);
|
|
|
|
ND_PRINT((ndo, " %u bytes @ %" PRIu64,
|
2005-01-05 11:55:05 +08:00
|
|
|
EXTRACT_32BITS(&dp[2]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_64BITS(&dp[0])));
|
1999-11-21 13:43:49 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
|
|
|
ND_PRINT((ndo, " %u bytes @ %u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&dp[1]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[0])));
|
2000-01-28 08:04:19 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
1999-11-21 13:43:49 +08:00
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
case NFSPROC_WRITE:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
1999-11-21 13:43:49 +08:00
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[2]);
|
|
|
|
ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64,
|
2005-01-05 16:16:45 +08:00
|
|
|
EXTRACT_32BITS(&dp[4]),
|
|
|
|
EXTRACT_32BITS(&dp[2]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_64BITS(&dp[0])));
|
|
|
|
if (ndo->ndo_vflag) {
|
1999-11-21 13:43:49 +08:00
|
|
|
dp += 3;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
|
|
|
ND_PRINT((ndo, " <%s>",
|
2000-01-28 08:04:19 +08:00
|
|
|
tok2str(nfsv3_writemodes,
|
2014-04-01 20:05:33 +08:00
|
|
|
NULL, EXTRACT_32BITS(dp))));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[3]);
|
|
|
|
ND_PRINT((ndo, " %u (%u) bytes @ %u (%u)",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&dp[3]),
|
|
|
|
EXTRACT_32BITS(&dp[2]),
|
|
|
|
EXTRACT_32BITS(&dp[1]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[0])));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_SYMLINK:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != 0 &&
|
|
|
|
(dp = parsefhn(ndo, dp, v3)) != 0) {
|
|
|
|
ND_PRINT((ndo, " ->"));
|
|
|
|
if (v3 && (dp = parse_sattr3(ndo, dp, &sa3)) == 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsefn(ndo, dp) == 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (v3 && ndo->ndo_vflag)
|
|
|
|
print_sattr3(ndo, &sa3, ndo->ndo_vflag);
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_MKNOD:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != 0 &&
|
|
|
|
(dp = parsefhn(ndo, dp, v3)) != 0) {
|
|
|
|
ND_TCHECK(*dp);
|
2002-12-11 15:13:49 +08:00
|
|
|
type = (nfs_type)EXTRACT_32BITS(dp);
|
|
|
|
dp++;
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parse_sattr3(ndo, dp, &sa3)) == 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %s", tok2str(type2str, "unk-ft %d", type)));
|
|
|
|
if (ndo->ndo_vflag && (type == NFCHR || type == NFBLK)) {
|
|
|
|
ND_TCHECK(dp[1]);
|
|
|
|
ND_PRINT((ndo, " %u/%u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&dp[0]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[1])));
|
1999-11-21 13:43:49 +08:00
|
|
|
dp += 2;
|
|
|
|
}
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
print_sattr3(ndo, &sa3, ndo->ndo_vflag);
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_RENAME:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefhn(ndo, dp, v3)) != NULL) {
|
|
|
|
ND_PRINT((ndo, " ->"));
|
|
|
|
if (parsefhn(ndo, dp, v3) != NULL)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_LINK:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
|
|
|
ND_PRINT((ndo, " ->"));
|
|
|
|
if (parsefhn(ndo, dp, v3) != NULL)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_READDIR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
1999-11-21 13:43:49 +08:00
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[4]);
|
1999-11-21 13:43:49 +08:00
|
|
|
/*
|
|
|
|
* We shouldn't really try to interpret the
|
|
|
|
* offset cookie here.
|
|
|
|
*/
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %u bytes @ %" PRId64,
|
2005-01-05 11:55:05 +08:00
|
|
|
EXTRACT_32BITS(&dp[4]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_64BITS(&dp[0])));
|
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " verf %08x%08x", dp[2], dp[3]));
|
1999-11-21 13:43:49 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2000-01-28 08:04:19 +08:00
|
|
|
/*
|
1999-11-21 13:43:49 +08:00
|
|
|
* Print the offset as signed, since -1 is
|
|
|
|
* common, but offsets > 2^31 aren't.
|
2000-01-28 08:04:19 +08:00
|
|
|
*/
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %u bytes @ %d",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&dp[1]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[0])));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_READDIRPLUS:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
|
|
|
ND_TCHECK(dp[4]);
|
1999-11-21 13:43:49 +08:00
|
|
|
/*
|
|
|
|
* We don't try to interpret the offset
|
|
|
|
* cookie here.
|
|
|
|
*/
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %u bytes @ %" PRId64,
|
2005-01-05 11:55:05 +08:00
|
|
|
EXTRACT_32BITS(&dp[4]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_64BITS(&dp[0])));
|
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_TCHECK(dp[5]);
|
|
|
|
ND_PRINT((ndo, " max %u verf %08x%08x",
|
|
|
|
EXTRACT_32BITS(&dp[5]), dp[2], dp[3]));
|
2005-01-05 11:55:05 +08:00
|
|
|
}
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_COMMIT:
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parsereq(ndo, rp, length)) != NULL &&
|
|
|
|
(dp = parsefh(ndo, dp, v3)) != NULL) {
|
|
|
|
ND_TCHECK(dp[2]);
|
|
|
|
ND_PRINT((ndo, " %u bytes @ %" PRIu64,
|
2005-01-05 11:55:05 +08:00
|
|
|
EXTRACT_32BITS(&dp[2]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_64BITS(&dp[0])));
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2000-01-28 08:04:19 +08:00
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
trunc:
|
|
|
|
if (!nfserr)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s", tstr));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print out an NFS file handle.
|
|
|
|
* We assume packet was not truncated before the end of the
|
|
|
|
* file handle pointed to by dp.
|
|
|
|
*
|
|
|
|
* Note: new version (using portable file-handle parser) doesn't produce
|
|
|
|
* generation number. It probably could be made to do that, with some
|
|
|
|
* additional hacking on the parser code.
|
|
|
|
*/
|
|
|
|
static void
|
2014-04-01 20:05:33 +08:00
|
|
|
nfs_printfh(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp, const u_int len)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
|
|
|
my_fsid fsid;
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t ino;
|
2002-04-24 14:27:05 +08:00
|
|
|
const char *sfsname = NULL;
|
|
|
|
char *spacep;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_uflag) {
|
Add a few more GCC warnings on GCC >= 2 for ".devel" builds.
From Neil T. Spring: fixes for many of those warnings:
addrtoname.c, configure.in: Linux needs netinet/ether.h for
ether_ntohost
print-*.c: change char *foo = "bar" to const char *foo = "bar"
to appease -Wwrite-strings; should affect no run-time behavior.
print-*.c: make some variables unsigned.
print-bgp.c: plen ('prefix len') is unsigned, no reason to
validate by comparing to zero.
print-cnfp.c, print-rx.c: use intoa, provided by addrtoname,
instead of inet_ntoa.
print-domain.c: unsigned int l; (l=foo()) < 0 is guaranteed to
be false, so check for (u_int)-1, which represents failure,
explicitly.
print-isakmp.c: complete initialization of attrmap objects.
print-lwres.c: "if(x); print foo;" seemed much more likely to be
intended to be "if(x) { print foo; }".
print-smb.c: complete initialization of some structures.
In addition, add some fixes for the signed vs. unsigned comparison
warnings:
extract.h: cast the result of the byte-extraction-and-combining,
as, at least for the 16-bit version, C's integral promotions
will turn "u_int16_t" into "int" if there are other "int"s
nearby.
print-*.c: make some more variables unsigned, or add casts to an
unsigned type of signed values known not to be negative, or add
casts to "int" of unsigned values known to fit in an "int", and
make other changes needed to handle the aforementioned variables
now being unsigned.
print-isakmp.c: clean up the handling of error/status indicators
in notify messages.
print-ppp.c: get rid of a check that an unsigned quantity is >=
0.
print-radius.c: clean up some of the bounds checking.
print-smb.c: extract the word count into a "u_int" to avoid the
aforementioned problems with C's integral promotions.
print-snmp.c: change a check that an unsigned variable is >= 0
to a check that it's != 0.
Also, fix some formats to use "%u" rather than "%d" for unsigned
quantities.
2002-09-05 08:00:07 +08:00
|
|
|
u_int i;
|
2002-08-26 17:36:19 +08:00
|
|
|
char const *sep = "";
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " fh["));
|
2002-08-26 17:36:19 +08:00
|
|
|
for (i=0; i<len; i++) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s%x", sep, dp[i]));
|
2002-08-26 17:36:19 +08:00
|
|
|
sep = ":";
|
|
|
|
}
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "]"));
|
2002-08-26 17:36:19 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-04-24 14:27:05 +08:00
|
|
|
Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
if (sfsname) {
|
|
|
|
/* file system ID is ASCII, not numeric, for this server OS */
|
2000-01-28 08:04:19 +08:00
|
|
|
static char temp[NFSX_V3FHMAX+1];
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
/* Make sure string is null-terminated */
|
2000-01-28 08:04:19 +08:00
|
|
|
strncpy(temp, sfsname, NFSX_V3FHMAX);
|
2000-06-10 13:26:42 +08:00
|
|
|
temp[sizeof(temp) - 1] = '\0';
|
1999-10-08 07:47:09 +08:00
|
|
|
/* Remove trailing spaces */
|
2002-04-24 14:27:05 +08:00
|
|
|
spacep = strchr(temp, ' ');
|
|
|
|
if (spacep)
|
|
|
|
*spacep = '\0';
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " fh %s/", temp));
|
2000-06-01 09:08:18 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " fh %d,%d/",
|
|
|
|
fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
2000-06-01 09:08:18 +08:00
|
|
|
|
2002-08-26 17:36:19 +08:00
|
|
|
if(fsid.Fsid_dev.Minor == 257)
|
2002-06-12 01:08:37 +08:00
|
|
|
/* Print the undecoded handle */
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s", fsid.Opaque_Handle));
|
2000-06-01 09:08:18 +08:00
|
|
|
else
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%ld", (long) ino));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maintain a small cache of recent client.XID.server/proc pairs, to allow
|
|
|
|
* us to match up replies with requests and thus to know how to parse
|
|
|
|
* the reply.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct xid_map_entry {
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t xid; /* transaction ID (net order) */
|
2000-06-10 13:12:20 +08:00
|
|
|
int ipver; /* IP version (4 or 6) */
|
|
|
|
#ifdef INET6
|
|
|
|
struct in6_addr client; /* client IP address (net order) */
|
|
|
|
struct in6_addr server; /* server IP address (net order) */
|
|
|
|
#else
|
1999-10-08 07:47:09 +08:00
|
|
|
struct in_addr client; /* client IP address (net order) */
|
|
|
|
struct in_addr server; /* server IP address (net order) */
|
2000-06-10 13:12:20 +08:00
|
|
|
#endif
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t proc; /* call proc number (host order) */
|
|
|
|
uint32_t vers; /* program version (host order) */
|
1999-10-08 07:47:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map entries are kept in an array that we manage as a ring;
|
|
|
|
* new entries are always added at the tail of the ring. Initially,
|
|
|
|
* all the entries are zero and hence don't match anything.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define XIDMAPSIZE 64
|
|
|
|
|
|
|
|
struct xid_map_entry xid_map[XIDMAPSIZE];
|
|
|
|
|
|
|
|
int xid_map_next = 0;
|
|
|
|
int xid_map_hint = 0;
|
|
|
|
|
2007-12-22 11:08:04 +08:00
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
xid_map_enter(netdissect_options *ndo,
|
|
|
|
const struct sunrpc_msg *rp, const u_char *bp)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip *ip = NULL;
|
2000-06-10 13:12:20 +08:00
|
|
|
#ifdef INET6
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip6_hdr *ip6 = NULL;
|
2000-06-10 13:12:20 +08:00
|
|
|
#endif
|
1999-10-08 07:47:09 +08:00
|
|
|
struct xid_map_entry *xmep;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!ND_TTEST(rp->rm_call.cb_vers))
|
2007-12-22 11:08:04 +08:00
|
|
|
return (0);
|
2015-04-27 08:24:42 +08:00
|
|
|
switch (IP_V((const struct ip *)bp)) {
|
2000-06-10 13:12:20 +08:00
|
|
|
case 4:
|
2015-04-27 08:24:42 +08:00
|
|
|
ip = (const struct ip *)bp;
|
2000-06-10 13:12:20 +08:00
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case 6:
|
2015-04-27 08:24:42 +08:00
|
|
|
ip6 = (const struct ip6_hdr *)bp;
|
2000-06-10 13:12:20 +08:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
2007-12-22 11:08:04 +08:00
|
|
|
return (1);
|
2000-06-10 13:12:20 +08:00
|
|
|
}
|
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
xmep = &xid_map[xid_map_next];
|
|
|
|
|
|
|
|
if (++xid_map_next >= XIDMAPSIZE)
|
|
|
|
xid_map_next = 0;
|
|
|
|
|
2014-06-26 03:55:25 +08:00
|
|
|
UNALIGNED_MEMCPY(&xmep->xid, &rp->rm_xid, sizeof(xmep->xid));
|
2000-06-10 13:12:20 +08:00
|
|
|
if (ip) {
|
|
|
|
xmep->ipver = 4;
|
2014-01-19 04:09:45 +08:00
|
|
|
UNALIGNED_MEMCPY(&xmep->client, &ip->ip_src, sizeof(ip->ip_src));
|
|
|
|
UNALIGNED_MEMCPY(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst));
|
2000-06-10 13:12:20 +08:00
|
|
|
}
|
|
|
|
#ifdef INET6
|
|
|
|
else if (ip6) {
|
|
|
|
xmep->ipver = 6;
|
2014-01-19 04:09:45 +08:00
|
|
|
UNALIGNED_MEMCPY(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src));
|
|
|
|
UNALIGNED_MEMCPY(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
|
2000-06-10 13:12:20 +08:00
|
|
|
}
|
|
|
|
#endif
|
2002-12-11 15:13:49 +08:00
|
|
|
xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
|
|
|
|
xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers);
|
2007-12-22 11:08:04 +08:00
|
|
|
return (1);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
2000-01-28 08:04:19 +08:00
|
|
|
/*
|
|
|
|
* Returns 0 and puts NFSPROC_xxx in proc return and
|
|
|
|
* version in vers return, or returns -1 on failure
|
|
|
|
*/
|
1999-11-21 13:43:49 +08:00
|
|
|
static int
|
2014-04-23 15:20:40 +08:00
|
|
|
xid_map_find(const struct sunrpc_msg *rp, const u_char *bp, uint32_t *proc,
|
|
|
|
uint32_t *vers)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct xid_map_entry *xmep;
|
2014-04-23 15:20:40 +08:00
|
|
|
uint32_t xid = rp->rm_xid;
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip *ip = (const struct ip *)bp;
|
2000-06-10 13:12:20 +08:00
|
|
|
#ifdef INET6
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp;
|
2000-06-10 13:12:20 +08:00
|
|
|
#endif
|
|
|
|
int cmp;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
/* Start searching from where we last left off */
|
2002-06-12 01:08:37 +08:00
|
|
|
i = xid_map_hint;
|
1999-10-08 07:47:09 +08:00
|
|
|
do {
|
|
|
|
xmep = &xid_map[i];
|
2000-06-10 13:12:20 +08:00
|
|
|
cmp = 1;
|
2000-10-03 10:54:54 +08:00
|
|
|
if (xmep->ipver != IP_V(ip) || xmep->xid != xid)
|
2000-06-10 13:12:20 +08:00
|
|
|
goto nextitem;
|
|
|
|
switch (xmep->ipver) {
|
|
|
|
case 4:
|
2014-01-19 04:42:15 +08:00
|
|
|
if (UNALIGNED_MEMCMP(&ip->ip_src, &xmep->server,
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(ip->ip_src)) != 0 ||
|
2014-01-19 04:42:15 +08:00
|
|
|
UNALIGNED_MEMCMP(&ip->ip_dst, &xmep->client,
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(ip->ip_dst)) != 0) {
|
|
|
|
cmp = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case 6:
|
2014-01-19 04:42:15 +08:00
|
|
|
if (UNALIGNED_MEMCMP(&ip6->ip6_src, &xmep->server,
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(ip6->ip6_src)) != 0 ||
|
2014-01-19 04:42:15 +08:00
|
|
|
UNALIGNED_MEMCMP(&ip6->ip6_dst, &xmep->client,
|
2000-06-10 13:12:20 +08:00
|
|
|
sizeof(ip6->ip6_dst)) != 0) {
|
|
|
|
cmp = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
cmp = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cmp) {
|
1999-10-08 07:47:09 +08:00
|
|
|
/* match */
|
|
|
|
xid_map_hint = i;
|
|
|
|
*proc = xmep->proc;
|
1999-11-21 13:43:49 +08:00
|
|
|
*vers = xmep->vers;
|
2000-01-28 08:04:19 +08:00
|
|
|
return 0;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
2000-06-10 13:12:20 +08:00
|
|
|
nextitem:
|
1999-10-08 07:47:09 +08:00
|
|
|
if (++i >= XIDMAPSIZE)
|
|
|
|
i = 0;
|
|
|
|
} while (i != xid_map_hint);
|
|
|
|
|
|
|
|
/* search failed */
|
2000-01-28 08:04:19 +08:00
|
|
|
return (-1);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Routines for parsing reply packets
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a pointer to the beginning of the actual results.
|
|
|
|
* If the packet was truncated, return 0.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parserep(netdissect_options *ndo,
|
|
|
|
register const struct sunrpc_msg *rp, register u_int length)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp;
|
1999-10-08 07:47:09 +08:00
|
|
|
u_int len;
|
2004-12-27 08:41:29 +08:00
|
|
|
enum sunrpc_accept_stat astat;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Portability note:
|
|
|
|
* Here we find the address of the ar_verf credentials.
|
|
|
|
* Originally, this calculation was
|
2014-04-23 15:20:40 +08:00
|
|
|
* dp = (uint32_t *)&rp->rm_reply.rp_acpt.ar_verf
|
1999-10-08 07:47:09 +08:00
|
|
|
* On the wire, the rp_acpt field starts immediately after
|
|
|
|
* the (32 bit) rp_stat field. However, rp_acpt (which is a
|
|
|
|
* "struct accepted_reply") contains a "struct opaque_auth",
|
|
|
|
* whose internal representation contains a pointer, so on a
|
|
|
|
* 64-bit machine the compiler inserts 32 bits of padding
|
|
|
|
* before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use
|
|
|
|
* the internal representation to parse the on-the-wire
|
|
|
|
* representation. Instead, we skip past the rp_stat field,
|
|
|
|
* which is an "enum" and so occupies one 32-bit word.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
dp = ((const uint32_t *)&rp->rm_reply) + 1;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[1]);
|
2002-12-11 15:13:49 +08:00
|
|
|
len = EXTRACT_32BITS(&dp[1]);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (len >= length)
|
|
|
|
return (NULL);
|
|
|
|
/*
|
|
|
|
* skip past the ar_verf credentials.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(dp[0], 0);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* now we can check the ar_stat field
|
|
|
|
*/
|
2005-04-21 05:52:53 +08:00
|
|
|
astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp);
|
2014-04-13 23:28:05 +08:00
|
|
|
if (astat != SUNRPC_SUCCESS) {
|
|
|
|
ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat)));
|
1999-10-08 07:47:09 +08:00
|
|
|
nfserr = 1; /* suppress trunc string */
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
/* successful return */
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(*dp, sizeof(astat));
|
2015-04-27 08:24:42 +08:00
|
|
|
return ((const uint32_t *) (sizeof(astat) + ((const char *)dp)));
|
1999-10-08 07:47:09 +08:00
|
|
|
trunc:
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsestatus(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int *er)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2000-01-28 08:04:19 +08:00
|
|
|
int errnum;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
1999-11-21 13:43:49 +08:00
|
|
|
|
2002-12-11 15:13:49 +08:00
|
|
|
errnum = EXTRACT_32BITS(&dp[0]);
|
1999-11-21 13:43:49 +08:00
|
|
|
if (er)
|
2000-01-28 08:04:19 +08:00
|
|
|
*er = errnum;
|
|
|
|
if (errnum != 0) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!ndo->ndo_qflag)
|
|
|
|
ND_PRINT((ndo, " ERROR: %s",
|
|
|
|
tok2str(status2str, "unk %d", errnum)));
|
2000-01-28 08:04:19 +08:00
|
|
|
nfserr = 1;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
return (dp + 1);
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return NULL;
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsefattr(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
const struct nfs_fattr *fap;
|
|
|
|
|
|
|
|
fap = (const struct nfs_fattr *)dp;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(fap->fa_gid);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (verbose) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " %s %o ids %d/%d",
|
1999-10-08 07:47:09 +08:00
|
|
|
tok2str(type2str, "unk-ft %d ",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa_type)),
|
|
|
|
EXTRACT_32BITS(&fap->fa_mode),
|
|
|
|
EXTRACT_32BITS(&fap->fa_uid),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa_gid)));
|
1999-11-21 13:43:49 +08:00
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(fap->fa3_size);
|
|
|
|
ND_PRINT((ndo, " sz %" PRIu64,
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&fap->fa3_size)));
|
2000-01-28 08:04:19 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(fap->fa2_size);
|
|
|
|
ND_PRINT((ndo, " sz %d", EXTRACT_32BITS(&fap->fa2_size)));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
/* print lots more stuff */
|
|
|
|
if (verbose > 1) {
|
1999-11-21 13:43:49 +08:00
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(fap->fa3_ctime);
|
|
|
|
ND_PRINT((ndo, " nlink %d rdev %d/%d",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa_nlink),
|
|
|
|
EXTRACT_32BITS(&fap->fa3_rdev.specdata1),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_rdev.specdata2)));
|
|
|
|
ND_PRINT((ndo, " fsid %" PRIx64,
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&fap->fa3_fsid)));
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " fileid %" PRIx64,
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&fap->fa3_fileid)));
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " a/m/ctime %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)));
|
|
|
|
ND_PRINT((ndo, " %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)));
|
|
|
|
ND_PRINT((ndo, " %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)));
|
1999-11-21 13:43:49 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(fap->fa2_ctime);
|
2014-04-15 16:43:47 +08:00
|
|
|
ND_PRINT((ndo, " nlink %d rdev 0x%x fsid 0x%x nodeid 0x%x a/m/ctime",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa_nlink),
|
|
|
|
EXTRACT_32BITS(&fap->fa2_rdev),
|
|
|
|
EXTRACT_32BITS(&fap->fa2_fsid),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_fileid)));
|
|
|
|
ND_PRINT((ndo, " %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)));
|
|
|
|
ND_PRINT((ndo, " %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)));
|
|
|
|
ND_PRINT((ndo, " %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)));
|
2000-01-28 08:04:19 +08:00
|
|
|
}
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
2015-04-27 08:24:42 +08:00
|
|
|
return ((const uint32_t *)((const unsigned char *)dp +
|
1999-11-21 13:43:49 +08:00
|
|
|
(v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (NULL);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parseattrstat(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
int er;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsestatus(ndo, dp, &er);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (dp == NULL)
|
1999-10-08 07:47:09 +08:00
|
|
|
return (0);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (er)
|
|
|
|
return (1);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
return (parsefattr(ndo, dp, verbose, v3) != NULL);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parsediropres(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
int er;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-10-08 07:47:09 +08:00
|
|
|
return (0);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (er)
|
|
|
|
return (1);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsefh(ndo, dp, 0);
|
1999-10-08 07:47:09 +08:00
|
|
|
if (dp == NULL)
|
|
|
|
return (0);
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
return (parsefattr(ndo, dp, ndo->ndo_vflag, 0) != NULL);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parselinkres(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
int er;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsestatus(ndo, dp, &er);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (dp == NULL)
|
1999-11-21 13:43:49 +08:00
|
|
|
return(0);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (er)
|
|
|
|
return(1);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (v3 && !(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " "));
|
|
|
|
return (parsefn(ndo, dp) != NULL);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parsestatfs(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int v3)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
const struct nfs_statfs *sfsp;
|
|
|
|
int er;
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsestatus(ndo, dp, &er);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (dp == NULL)
|
1999-10-08 07:47:09 +08:00
|
|
|
return (0);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (!v3 && er)
|
|
|
|
return (1);
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_qflag)
|
1999-11-21 13:43:49 +08:00
|
|
|
return(1);
|
|
|
|
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " POST:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
sfsp = (const struct nfs_statfs *)dp;
|
|
|
|
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_tbytes),
|
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_fbytes),
|
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_abytes)));
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_PRINT((ndo, " tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_tfiles),
|
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_ffiles),
|
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfsp->sf_afiles),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&sfsp->sf_invarsec)));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " tsize %d bsize %d blocks %d bfree %d bavail %d",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&sfsp->sf_tsize),
|
|
|
|
EXTRACT_32BITS(&sfsp->sf_bsize),
|
|
|
|
EXTRACT_32BITS(&sfsp->sf_blocks),
|
|
|
|
EXTRACT_32BITS(&sfsp->sf_bfree),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&sfsp->sf_bavail)));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return (1);
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (0);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parserddires(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
1999-11-21 13:43:49 +08:00
|
|
|
int er;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parsestatus(ndo, dp, &er);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (dp == NULL)
|
1999-10-08 07:47:09 +08:00
|
|
|
return (0);
|
2002-05-31 17:47:23 +08:00
|
|
|
if (er)
|
|
|
|
return (1);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_qflag)
|
1999-11-21 13:43:49 +08:00
|
|
|
return (1);
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[2]);
|
2014-04-15 16:43:47 +08:00
|
|
|
ND_PRINT((ndo, " offset 0x%x size %d ",
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])));
|
2000-01-28 08:04:19 +08:00
|
|
|
if (dp[2] != 0)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " eof"));
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
return (1);
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (0);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parse_wcc_attr(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0])));
|
|
|
|
ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])));
|
1999-11-21 13:43:49 +08:00
|
|
|
return (dp + 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pre operation attributes. Print only if vflag > 1.
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parse_pre_op_attr(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
if (!EXTRACT_32BITS(&dp[0]))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (dp + 1);
|
|
|
|
dp++;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK2(*dp, 24);
|
1999-11-21 13:43:49 +08:00
|
|
|
if (verbose > 1) {
|
2014-04-01 20:05:33 +08:00
|
|
|
return parse_wcc_attr(ndo, dp);
|
1999-11-21 13:43:49 +08:00
|
|
|
} else {
|
|
|
|
/* If not verbose enough, just skip over wcc_attr */
|
|
|
|
return (dp + 6);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (NULL);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
/*
|
|
|
|
* Post operation attributes are printed if vflag >= 1
|
|
|
|
*/
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parse_post_op_attr(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
if (!EXTRACT_32BITS(&dp[0]))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (dp + 1);
|
|
|
|
dp++;
|
|
|
|
if (verbose) {
|
2014-04-01 20:05:33 +08:00
|
|
|
return parsefattr(ndo, dp, verbose, 1);
|
1999-11-21 13:43:49 +08:00
|
|
|
} else
|
2014-04-23 15:20:40 +08:00
|
|
|
return (dp + (NFSX_V3FATTR / sizeof (uint32_t)));
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (NULL);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parse_wcc_data(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
if (verbose > 1)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " PRE:"));
|
|
|
|
if (!(dp = parse_pre_op_attr(ndo, dp, verbose)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (verbose)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " POST:"));
|
|
|
|
return parse_post_op_attr(ndo, dp, verbose);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsecreateopres(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
int er;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
if (er)
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parse_wcc_data(ndo, dp, verbose);
|
1999-11-21 13:43:49 +08:00
|
|
|
else {
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(dp[0]);
|
2002-12-11 15:13:49 +08:00
|
|
|
if (!EXTRACT_32BITS(&dp[0]))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (dp + 1);
|
|
|
|
dp++;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsefh(ndo, dp, 1)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
if (verbose) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag > 1) {
|
|
|
|
ND_PRINT((ndo, " dir attr:"));
|
|
|
|
dp = parse_wcc_data(ndo, dp, verbose);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (dp);
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (NULL);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parsewccres(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
int er;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
return parse_wcc_data(ndo, dp, verbose) != 0;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 15:20:40 +08:00
|
|
|
static const uint32_t *
|
2014-04-01 20:05:33 +08:00
|
|
|
parsev3rddirres(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp, int verbose)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
int er;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " POST:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
if (er)
|
|
|
|
return dp;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_TCHECK(dp[1]);
|
|
|
|
ND_PRINT((ndo, " verf %08x%08x", dp[0], dp[1]));
|
1999-11-21 13:43:49 +08:00
|
|
|
dp += 2;
|
|
|
|
}
|
|
|
|
return dp;
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
|
|
|
return (NULL);
|
|
|
|
}
|
1999-11-21 13:43:49 +08:00
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parsefsinfo(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct nfsv3_fsinfo *sfp;
|
1999-11-21 13:43:49 +08:00
|
|
|
int er;
|
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " POST:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
if (er)
|
2000-01-28 08:04:19 +08:00
|
|
|
return (1);
|
1999-11-21 13:43:49 +08:00
|
|
|
|
2015-04-27 08:24:42 +08:00
|
|
|
sfp = (const struct nfsv3_fsinfo *)dp;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(*sfp);
|
|
|
|
ND_PRINT((ndo, " rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_rtmax),
|
|
|
|
EXTRACT_32BITS(&sfp->fs_rtpref),
|
|
|
|
EXTRACT_32BITS(&sfp->fs_wtmax),
|
|
|
|
EXTRACT_32BITS(&sfp->fs_wtpref),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_dtpref)));
|
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_PRINT((ndo, " rtmult %u wtmult %u maxfsz %" PRIu64,
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_rtmult),
|
2005-01-05 11:55:05 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_wtmult),
|
2015-04-27 08:24:42 +08:00
|
|
|
EXTRACT_64BITS((const uint32_t *)&sfp->fs_maxfilesize)));
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " delta %u.%06u ",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec),
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
return (1);
|
2002-05-31 17:47:23 +08:00
|
|
|
trunc:
|
|
|
|
return (0);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-04-01 20:05:33 +08:00
|
|
|
parsepathconf(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const uint32_t *dp)
|
1999-11-21 13:43:49 +08:00
|
|
|
{
|
|
|
|
int er;
|
2015-04-27 08:24:42 +08:00
|
|
|
const struct nfsv3_pathconf *spp;
|
1999-11-21 13:43:49 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
2000-01-28 08:04:19 +08:00
|
|
|
return (0);
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " POST:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return (0);
|
|
|
|
if (er)
|
|
|
|
return (1);
|
|
|
|
|
2015-04-27 08:24:42 +08:00
|
|
|
spp = (const struct nfsv3_pathconf *)dp;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_TCHECK(*spp);
|
1999-11-21 13:43:49 +08:00
|
|
|
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " linkmax %u namemax %u %s %s %s %s",
|
2002-12-11 15:13:49 +08:00
|
|
|
EXTRACT_32BITS(&spp->pc_linkmax),
|
|
|
|
EXTRACT_32BITS(&spp->pc_namemax),
|
|
|
|
EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "",
|
|
|
|
EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "",
|
|
|
|
EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "",
|
2014-04-01 20:05:33 +08:00
|
|
|
EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""));
|
2000-01-28 08:04:19 +08:00
|
|
|
return (1);
|
2002-05-31 17:47:23 +08:00
|
|
|
trunc:
|
|
|
|
return (0);
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-04-01 20:05:33 +08:00
|
|
|
interp_reply(netdissect_options *ndo,
|
2014-04-23 15:20:40 +08:00
|
|
|
const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers, int length)
|
1999-10-08 07:47:09 +08:00
|
|
|
{
|
2014-04-23 15:20:40 +08:00
|
|
|
register const uint32_t *dp;
|
1999-11-21 13:43:49 +08:00
|
|
|
register int v3;
|
|
|
|
int er;
|
|
|
|
|
|
|
|
v3 = (vers == NFS_VER3);
|
|
|
|
|
|
|
|
if (!v3 && proc < NFS_NPROCS)
|
|
|
|
proc = nfsv3_procid[proc];
|
1999-10-08 07:47:09 +08:00
|
|
|
|
2014-04-13 23:28:05 +08:00
|
|
|
ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
|
1999-10-08 07:47:09 +08:00
|
|
|
switch (proc) {
|
|
|
|
|
|
|
|
case NFSPROC_GETATTR:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parseattrstat(ndo, dp, !ndo->ndo_qflag, v3) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_SETATTR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsewccres(ndo, dp, ndo->ndo_vflag))
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_LOOKUP:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (er) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag > 1) {
|
|
|
|
ND_PRINT((ndo, " post dattr:"));
|
|
|
|
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsefh(ndo, dp, v3)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if ((dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)) &&
|
|
|
|
ndo->ndo_vflag > 1) {
|
|
|
|
ND_PRINT((ndo, " post dattr:"));
|
|
|
|
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dp)
|
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsediropres(ndo, dp) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_ACCESS:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
2001-07-05 03:24:10 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag)
|
|
|
|
ND_PRINT((ndo, " attr:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (!er)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0])));
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
|
1999-10-08 07:47:09 +08:00
|
|
|
case NFSPROC_READLINK:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parselinkres(ndo, dp, v3) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_READ:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (er)
|
|
|
|
return;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_TCHECK(dp[1]);
|
|
|
|
ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
|
2002-12-11 15:13:49 +08:00
|
|
|
if (EXTRACT_32BITS(&dp[1]))
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " EOF"));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_WRITE:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (er)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_TCHECK(dp[0]);
|
|
|
|
ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
|
|
|
|
if (ndo->ndo_vflag > 1) {
|
|
|
|
ND_TCHECK(dp[1]);
|
|
|
|
ND_PRINT((ndo, " <%s>",
|
2000-01-28 08:04:19 +08:00
|
|
|
tok2str(nfsv3_writemodes,
|
2014-04-01 20:05:33 +08:00
|
|
|
NULL, EXTRACT_32BITS(&dp[1]))));
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3) != 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_CREATE:
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_MKDIR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsediropres(ndo, dp) != 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_SYMLINK:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsestatus(ndo, dp, &er) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_MKNOD:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_REMOVE:
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_RMDIR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsewccres(ndo, dp, ndo->ndo_vflag))
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsestatus(ndo, dp, &er) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_RENAME:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_PRINT((ndo, " from:"));
|
|
|
|
if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " to:"));
|
|
|
|
if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsestatus(ndo, dp, &er) != 0)
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_LINK:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parsestatus(ndo, dp, &er)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (ndo->ndo_vflag) {
|
|
|
|
ND_PRINT((ndo, " file POST:"));
|
|
|
|
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, " dir:"));
|
|
|
|
if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsestatus(ndo, dp, &er) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_READDIR:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
|
|
|
if (v3) {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
} else {
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parserddires(ndo, dp) != 0)
|
2000-01-28 08:04:19 +08:00
|
|
|
return;
|
1999-11-21 13:43:49 +08:00
|
|
|
}
|
1999-10-08 07:47:09 +08:00
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_READDIRPLUS:
|
2014-04-01 20:05:33 +08:00
|
|
|
if (!(dp = parserep(ndo, rp, length)))
|
1999-11-21 13:43:49 +08:00
|
|
|
break;
|
2014-04-01 20:05:33 +08:00
|
|
|
if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
|
1999-11-21 13:43:49 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NFSPROC_FSSTAT:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parsestatfs(ndo, dp, v3) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_FSINFO:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parsefsinfo(ndo, dp) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_PATHCONF:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parsepathconf(ndo, dp) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
1999-11-21 13:43:49 +08:00
|
|
|
case NFSPROC_COMMIT:
|
2014-04-01 20:05:33 +08:00
|
|
|
dp = parserep(ndo, rp, length);
|
|
|
|
if (dp != NULL && parsewccres(ndo, dp, ndo->ndo_vflag) != 0)
|
1999-10-08 07:47:09 +08:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2000-01-28 08:04:19 +08:00
|
|
|
trunc:
|
1999-10-08 07:47:09 +08:00
|
|
|
if (!nfserr)
|
2014-04-01 20:05:33 +08:00
|
|
|
ND_PRINT((ndo, "%s", tstr));
|
1999-10-08 07:47:09 +08:00
|
|
|
}
|