+static int32_t xid_map_find(const struct rpc_msg *, const struct ip *,
+ u_int32_t *, u_int32_t *);
+static void interp_reply(const struct rpc_msg *, u_int32_t, u_int32_t, int);
+static const u_int32_t *parse_post_op_attr(const u_int32_t *, int);
+static void print_sattr3(const struct nfsv3_sattr *sa3, int verbose);
+static int print_int64(const u_int32_t *dp, int how);
+
+/*
+ * Mapping of old NFS Version 2 RPC numbers to generic numbers.
+ */
+u_int32_t nfsv3_procid[NFS_NPROCS] = {
+ 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
+};
+
+static struct tok nfsv3_writemodes[] = {
+ { 0, "unstable" },
+ { 1, "datasync" },
+ { 2, "filesync" },
+ { 0, NULL }
+};
+
+static struct tok type2str[] = {
+ { NFNON, "NON" },
+ { NFREG, "REG" },
+ { NFDIR, "DIR" },
+ { NFBLK, "BLK" },
+ { NFCHR, "CHR" },
+ { NFLNK, "LNK" },
+ { NFFIFO, "FIFO" },
+ { 0, NULL }
+};
+
+/*
+ * Print out a 64-bit integer. This appears to be different on each system,
+ * try to make the best of it. The integer stored as 2 consecutive XDR
+ * encoded 32-bit integers, to which a pointer is passed.
+ *
+ * Assume that a system that has INT64_FORMAT defined, has a 64-bit
+ * integer datatype and can print it.
+ */
+
+#define UNSIGNED 0
+#define SIGNED 1
+#define HEX 2
+
+static int print_int64(const u_int32_t *dp, int how)
+{
+#ifdef INT64_FORMAT
+ u_int64_t res;
+
+ res = ((u_int64_t)ntohl(dp[0]) << 32) | (u_int64_t)ntohl(dp[1]);
+ switch (how) {
+ case SIGNED:
+ printf(INT64_FORMAT, res);
+ break;
+ case UNSIGNED:
+ printf(U_INT64_FORMAT, res);
+ break;
+ case HEX:
+ printf(HEX_INT64_FORMAT, res);
+ break;
+ default:
+ return (0);
+ }
+#else
+ switch (how) {
+ case SIGNED :
+ case UNSIGNED :
+ case HEX :
+ printf ("0x%x%08x", dp[0], dp[1]);
+ break;
+ default :
+ return (0);
+ }
+#endif
+ return 1;
+}
+
+static const u_int32_t *
+parse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3)
+{
+ TCHECK(dp[0]);
+ if ((sa3->sa_modeset = ntohl(*dp++))) {
+ TCHECK(dp[0]);
+ sa3->sa_mode = ntohl(*dp++);
+ }
+
+ TCHECK(dp[0]);
+ if ((sa3->sa_uidset = ntohl(*dp++))) {
+ TCHECK(dp[0]);
+ sa3->sa_uid = ntohl(*dp++);
+ }
+
+ TCHECK(dp[0]);
+ if ((sa3->sa_gidset = ntohl(*dp++))) {
+ TCHECK(dp[0]);
+ sa3->sa_gid = ntohl(*dp++);
+ }
+
+ TCHECK(dp[0]);
+ if ((sa3->sa_sizeset = ntohl(*dp++))) {
+ TCHECK(dp[0]);
+ sa3->sa_size = ntohl(*dp++);
+ }
+
+ TCHECK(dp[0]);
+ if ((sa3->sa_atimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) {
+ TCHECK(dp[1]);
+ sa3->sa_atime.nfsv3_sec = ntohl(*dp++);
+ sa3->sa_atime.nfsv3_nsec = ntohl(*dp++);
+ }
+
+ TCHECK(dp[0]);
+ if ((sa3->sa_mtimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) {
+ TCHECK(dp[1]);
+ sa3->sa_mtime.nfsv3_sec = ntohl(*dp++);
+ sa3->sa_mtime.nfsv3_nsec = ntohl(*dp++);
+ }
+
+ return dp;
+trunc:
+ return NULL;
+}