* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.110 2007-06-15 23:17:05 guy Exp $ (LBL)";
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rpc_auth.h"
#include "rpc_msg.h"
+static const char tstr[] = " [|nfs]";
+
static void nfs_printfh(const u_int32_t *, const u_int);
-static void xid_map_enter(const struct sunrpc_msg *, const u_char *);
-static int32_t xid_map_find(const struct sunrpc_msg *, const u_char *,
+static int xid_map_enter(const struct sunrpc_msg *, const u_char *);
+static int xid_map_find(const struct sunrpc_msg *, const u_char *,
u_int32_t *, u_int32_t *);
static void interp_reply(const struct sunrpc_msg *, u_int32_t, u_int32_t, int);
static const u_int32_t *parse_post_op_attr(const u_int32_t *, int);
* the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS
* was primarily BSD-derived.
*/
-static struct tok status2str[] = {
+static const struct tok status2str[] = {
{ 1, "Operation not permitted" }, /* EPERM */
{ 2, "No such file or directory" }, /* ENOENT */
{ 5, "Input/output error" }, /* EIO */
{ 0, NULL }
};
-static struct tok nfsv3_writemodes[] = {
+static const struct tok nfsv3_writemodes[] = {
{ 0, "unstable" },
{ 1, "datasync" },
{ 2, "filesync" },
{ 0, NULL }
};
-static struct tok type2str[] = {
+static const struct tok type2str[] = {
{ NFNON, "NON" },
{ NFREG, "REG" },
{ NFDIR, "DIR" },
register const u_char *bp2)
{
register const struct sunrpc_msg *rp;
- u_int32_t proc, vers, reply_stat;
char srcid[20], dstid[20]; /*fits 32bit*/
- enum sunrpc_reject_stat rstat;
- u_int32_t rlow;
- u_int32_t rhigh;
- enum sunrpc_auth_stat rwhy;
nfserr = 0; /* assume no error */
rp = (const struct sunrpc_msg *)bp;
+ TCHECK(rp->rm_xid);
if (!nflag) {
strlcpy(srcid, "nfs", sizeof(srcid));
snprintf(dstid, sizeof(dstid), "%u",
EXTRACT_32BITS(&rp->rm_xid));
}
print_nfsaddr(bp2, srcid, dstid);
+
+ nfsreply_print_noaddr(bp, length, bp2);
+ return;
+
+trunc:
+ if (!nfserr)
+ printf("%s", tstr);
+}
+
+void
+nfsreply_print_noaddr(register const u_char *bp, u_int length,
+ register const u_char *bp2)
+{
+ register const struct sunrpc_msg *rp;
+ u_int32_t proc, vers, reply_stat;
+ enum sunrpc_reject_stat rstat;
+ u_int32_t rlow;
+ u_int32_t rhigh;
+ enum sunrpc_auth_stat rwhy;
+
+ nfserr = 0; /* assume no error */
+ rp = (const struct sunrpc_msg *)bp;
+
+ TCHECK(rp->rm_reply.rp_stat);
reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat);
switch (reply_stat) {
case SUNRPC_MSG_DENIED:
(void)printf("reply ERR %u: ", length);
+ TCHECK(rp->rm_reply.rp_reject.rj_stat);
rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat);
switch (rstat) {
case SUNRPC_RPC_MISMATCH:
+ TCHECK(rp->rm_reply.rp_reject.rj_vers.high);
rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low);
rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high);
(void)printf("RPC Version mismatch (%u-%u)",
break;
case SUNRPC_AUTH_ERROR:
+ TCHECK(rp->rm_reply.rp_reject.rj_why);
rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why);
(void)printf("Auth ");
switch (rwhy) {
reply_stat, length);
break;
}
+ return;
+
+trunc:
+ if (!nfserr)
+ printf("%s", tstr);
}
/*
register const u_char *bp2)
{
register const struct sunrpc_msg *rp;
- register const u_int32_t *dp;
- nfs_type type;
- int v3;
- u_int32_t proc;
- struct nfsv3_sattr sa3;
char srcid[20], dstid[20]; /*fits 32bit*/
nfserr = 0; /* assume no error */
rp = (const struct sunrpc_msg *)bp;
+
+ TCHECK(rp->rm_xid);
if (!nflag) {
snprintf(srcid, sizeof(srcid), "%u",
EXTRACT_32BITS(&rp->rm_xid));
print_nfsaddr(bp2, srcid, dstid);
(void)printf("%d", length);
- xid_map_enter(rp, bp2); /* record proc number for later on */
+ nfsreq_print_noaddr(bp, length, bp2);
+ return;
+
+trunc:
+ if (!nfserr)
+ printf("%s", tstr);
+}
+
+void
+nfsreq_print_noaddr(register const u_char *bp, u_int length,
+ register const u_char *bp2)
+{
+ register const struct sunrpc_msg *rp;
+ register const u_int32_t *dp;
+ nfs_type type;
+ int v3;
+ u_int32_t proc;
+ u_int32_t access_flags;
+ struct nfsv3_sattr sa3;
+
+ nfserr = 0; /* assume no error */
+ rp = (const struct sunrpc_msg *)bp;
+
+ if (!xid_map_enter(rp, bp2)) /* record proc number for later on */
+ goto trunc;
v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3);
proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
if ((dp = parsereq(rp, length)) != NULL &&
(dp = parsefh(dp, v3)) != NULL) {
TCHECK(dp[0]);
- printf(" %04x", EXTRACT_32BITS(&dp[0]));
+ access_flags = EXTRACT_32BITS(&dp[0]);
+ if (access_flags & ~NFSV3ACCESS_FULL) {
+ /* NFSV3ACCESS definitions aren't up to date */
+ printf(" %04x", access_flags);
+ } else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) {
+ printf(" NFS_ACCESS_FULL");
+ } else {
+ char separator = ' ';
+ if (access_flags & NFSV3ACCESS_READ) {
+ printf(" NFS_ACCESS_READ");
+ separator = '|';
+ }
+ if (access_flags & NFSV3ACCESS_LOOKUP) {
+ printf("%cNFS_ACCESS_LOOKUP", separator);
+ separator = '|';
+ }
+ if (access_flags & NFSV3ACCESS_MODIFY) {
+ printf("%cNFS_ACCESS_MODIFY", separator);
+ separator = '|';
+ }
+ if (access_flags & NFSV3ACCESS_EXTEND) {
+ printf("%cNFS_ACCESS_EXTEND", separator);
+ separator = '|';
+ }
+ if (access_flags & NFSV3ACCESS_DELETE) {
+ printf("%cNFS_ACCESS_DELETE", separator);
+ separator = '|';
+ }
+ if (access_flags & NFSV3ACCESS_EXECUTE)
+ printf("%cNFS_ACCESS_EXECUTE", separator);
+ }
return;
}
break;
trunc:
if (!nfserr)
- fputs(" [|nfs]", stdout);
+ printf("%s", tstr);
}
/*
nfs_printfh(register const u_int32_t *dp, const u_int len)
{
my_fsid fsid;
- ino_t ino;
+ u_int32_t ino;
const char *sfsname = NULL;
char *spacep;
int xid_map_next = 0;
int xid_map_hint = 0;
-static void
+static int
xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp)
{
struct ip *ip = NULL;
#endif
struct xid_map_entry *xmep;
+ if (!TTEST(rp->rm_call.cb_vers))
+ return (0);
switch (IP_V((struct ip *)bp)) {
case 4:
ip = (struct ip *)bp;
break;
#endif
default:
- return;
+ return (1);
}
xmep = &xid_map[xid_map_next];
xmep->xid = rp->rm_xid;
if (ip) {
xmep->ipver = 4;
- memcpy(&xmep->client, &ip->ip_src, sizeof(ip->ip_src));
- memcpy(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst));
+ UNALIGNED_MEMCPY(&xmep->client, &ip->ip_src, sizeof(ip->ip_src));
+ UNALIGNED_MEMCPY(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst));
}
#ifdef INET6
else if (ip6) {
xmep->ipver = 6;
- memcpy(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src));
- memcpy(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
+ UNALIGNED_MEMCPY(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src));
+ UNALIGNED_MEMCPY(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
}
#endif
xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers);
+ return (1);
}
/*
}
trunc:
if (!nfserr)
- fputs(" [|nfs]", stdout);
+ printf("%s", tstr);
}