⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _nfs.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 3 页
字号:
           if (vflag && (type == NFCHR || type == NFBLK))
           {
             if (dp + 2 > (u_int32_t*)snapend)
               break;
             PRINTF (" %lu/%lu", ntohl (dp[0]), ntohl (dp[1]));
             dp += 2;
           }
           if (vflag)
             print_sattr3 (&sa3, vflag);
           return;
         }
         break;

    case NFSPROC_REMOVE:
         PUTS (" remove");
         if ((dp = parsereq (rp, length)) != NULL && parsefhn (dp, v3))
           return;
         break;

    case NFSPROC_RMDIR:
         PUTS (" rmdir");
         if ((dp = parsereq (rp, length)) != NULL && parsefhn (dp, v3))
           return;
         break;

    case NFSPROC_RENAME:
         PUTS (" rename");
         if ((dp = parsereq (rp, length)) != NULL && (dp = parsefhn (dp, v3)) != NULL)
         {
           PUTS (" ->");
           if (parsefhn (dp, v3))
             return;
         }
         break;

    case NFSPROC_LINK:
         PUTS (" link");
         if ((dp = parsereq (rp, length)) != NULL && (dp = parsefh (dp, v3)) != NULL)
         {
           PUTS (" ->");
           if (parsefhn (dp, v3))
             return;
         }
         break;

    case NFSPROC_READDIR:
         PUTS (" readdir");
         if ((dp = parsereq (rp, length)) != NULL && (dp = parsefh (dp, v3)) != NULL)
         {
           if (v3)
           {
             TCHECK2 (*dp, 20);
             /*
              * We shouldn't really try to interpret the
              * offset cookie here.
              */
             PRINTF (" %lu bytes @ ", ntohl (dp[4]));
             print_int64 (dp, SIGNED);
             if (vflag)
               PRINTF (" verf %08x%08x", dp[2], dp[3]);
           }
           else
           {
             TCHECK2 (*dp, 2 * sizeof(*dp));
             /*
              * Print the offset as signed, since -1 is
              * common, but offsets > 2^31 aren't.
              */
             PRINTF (" %lu bytes @ %ld", ntohl (dp[1]), ntohl (dp[0]));
           }
           return;
         }
         break;

    case NFSPROC_READDIRPLUS:
         PUTS (" readdirplus");
         if ((dp = parsereq (rp, length)) != NULL && (dp = parsefh (dp, v3)) != NULL)
         {
           TCHECK2 (*dp, 20);
           /*
            * We don't try to interpret the offset
            * cookie here.
            */
           PRINTF (" %lu bytes @ ", ntohl (dp[4]));
           print_int64 (dp, SIGNED);
           if (vflag)
             PRINTF (" max %lu verf %08x%08x", ntohl (dp[5]), dp[2], dp[3]);
           return;
         }
         break;

    case NFSPROC_FSSTAT:
         PUTS (" fsstat");
         if ((dp = parsereq (rp, length)) != NULL && parsefh (dp, v3))
           return;
         break;

    case NFSPROC_FSINFO:
         PUTS (" fsinfo");
         break;

    case NFSPROC_PATHCONF:
         PUTS (" pathconf");
         break;

    case NFSPROC_COMMIT:
         PUTS (" commit");
         if ((dp = parsereq (rp, length)) != NULL && (dp = parsefh (dp, v3)) != NULL)
         {
           PRINTF (" %lu bytes @ ", ntohl (dp[2]));
           print_int64 (dp, UNSIGNED);
           return;
         }
         break;

    default:
         PRINTF (" proc-%lu", proc);
         return;
  }
trunc:
  if (!nfserr)
     PUTS (" [|nfs]");
}

/*
 * 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 nfs_printfh (const u_int32_t * dp, const int len)
{
  my_fsid fsid;
  ino_t   ino;
  char   *sfsname = NULL;

  Parse_fh ((caddr_t*)dp, len, &fsid, &ino, NULL, &sfsname, 0);

  if (sfsname)
  {
    /* file system ID is ASCII, not numeric, for this server OS */
    static char temp[NFSX_V3FHMAX + 1];

    /* Make sure string is null-terminated */
    strncpy (temp, sfsname, NFSX_V3FHMAX);

    /* Remove trailing spaces */
    sfsname = strchr (temp, ' ');
    if (sfsname)
       *sfsname = 0;

    PRINTF (" fh %s/%u", temp, (u_int32_t) ino);
    if (fsid.Fsid_dev.Minor == 257 && uflag == 1)
         PRINTF (" fh %s/%s", temp, fsid.Opaque_Handle); /* Print the undecoded handle */
    else PRINTF (" fh %s/%ld", temp, (long)ino);
  }
  else
    PRINTF (" fh %u,%u/%u", fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor,
            (u_int32_t)ino);
}

/*
 * 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 {
       u_int32_t      xid;     /* transaction ID (net order) */
       struct in_addr client;  /* client IP address (net order) */
       struct in_addr server;  /* server IP address (net order) */
       u_int32_t      proc;    /* call proc number (host order) */
       u_int32_t      vers;    /* program version (host order) */
     };

/*
 * 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

static struct xid_map_entry xid_map[XIDMAPSIZE];

static int xid_map_next = 0;
static int xid_map_hint = 0;

static void xid_map_enter (const struct rpc_msg *rp, const struct ip *ip)
{
  struct xid_map_entry *xmep = &xid_map[xid_map_next];

  if (++xid_map_next >= XIDMAPSIZE)
     xid_map_next = 0;

  xmep->xid    = rp->rm_xid;
  xmep->client = ip->ip_src;
  xmep->server = ip->ip_dst;
  xmep->proc   = ntohl (rp->rm_call.cb_proc);
  xmep->vers   = ntohl (rp->rm_call.cb_vers);
}

/*
 * Returns 0 and puts NFSPROC_xxx in proc return and
 * version in vers return, or returns -1 on failure
 */
static int xid_map_find (const struct rpc_msg *rp, const struct ip *ip,
                         u_int32_t * proc, u_int32_t * vers)
{
  struct xid_map_entry *xmep;
  u_int32_t xid  = rp->rm_xid;
  u_int32_t clip = ip->ip_dst.s_addr;
  u_int32_t sip  = ip->ip_src.s_addr;
  int       i;

  /* Start searching from where we last left off
   */
  i = xid_map_hint;
  do
  {
    xmep = &xid_map[i];
    if (xmep->xid == xid            &&
        xmep->client.s_addr == clip &&
        xmep->server.s_addr == sip)
    {
      /* match */
      xid_map_hint = i;
      *proc = xmep->proc;
      *vers = xmep->vers;
      return 0;
    }
    if (++i >= XIDMAPSIZE)
      i = 0;
  }
  while (i != xid_map_hint);

  /* search failed */
  return (0);
}

/*
 * Routines for parsing reply packets
 */

/*
 * Return a pointer to the beginning of the actual results.
 * If the packet was truncated, return NULL.
 */
static const u_int32_t *parserep (const struct rpc_msg *rp, int length)
{
  const u_int32_t *dp;
  enum  accept_stat astat;
  int   len;

  /*
   * Portability note:
   * Here we find the address of the ar_verf credentials.
   * Originally, this calculation was
   *      dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf
   * 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.
   */
  dp = ((const u_int32_t*)&rp->rm_reply) + 1;
  TCHECK2 (dp[0], 1);
  len = ntohl (dp[1]);
  if (len >= length)
     return (NULL);

  /* skip past the ar_verf credentials.
   */
  dp += (len + (2 * sizeof(u_int32_t) + 3)) / sizeof(u_int32_t);
  TCHECK2 (dp[0], 0);

  /* now we can check the ar_stat field
   */
  astat = ntohl (*(enum accept_stat*)dp);
  switch (astat)
  {
    case SUCCESS:
         break;

    case PROG_UNAVAIL:
         PUTS (" PROG_UNAVAIL");
         nfserr = 1;            /* suppress trunc string */
         return (NULL);

    case PROG_MISMATCH:
         PUTS (" PROG_MISMATCH");
         nfserr = 1;            /* suppress trunc string */
         return (NULL);

    case PROC_UNAVAIL:
         PUTS (" PROC_UNAVAIL");
         nfserr = 1;            /* suppress trunc string */
         return (NULL);

    case GARBAGE_ARGS:
         PUTS (" GARBAGE_ARGS");
         nfserr = 1;            /* suppress trunc string */
         return (NULL);

    case SYSTEM_ERR:
         PUTS (" SYSTEM_ERR");
         nfserr = 1;            /* suppress trunc string */
         return (NULL);

    default:
         PRINTF (" ar_stat %d", astat);
         nfserr = 1;            /* suppress trunc string */
         return (NULL);
  }
  /* successful return */
  if ((sizeof(astat) + ((u_char*)dp)) < snapend)
     return ((u_int32_t*)(sizeof(astat) + ((char*)dp)));

trunc:
  return (NULL);
}


static const u_int32_t *parsestatus (const u_int32_t *dp, int *er)
{
  int errnum;

  TCHECK (dp[0]);
  errnum = ntohl (dp[0]);
  if (er)
     *er = errnum;

  if (errnum)
  {
    if (!qflag)
       PRINTF (" ERROR: %s", pcap_strerror (errnum));
    nfserr = 1;
    return (NULL);
  }
  return (dp + 1);
trunc:
  return (NULL);
}

static const u_int32_t *parsefattr (const u_int32_t *dp, int verbose, int v3)
{
  const struct nfs_fattr *fap = (const struct nfs_fattr*)dp;

  TCHECK (fap->fa_gid);
  if (verbose)
  {
    PRINTF (" %s %lo ids %ld/%ld",
            tok2str (type2str, "unk-ft %d ", ntohl (fap->fa_type)),
            ntohl (fap->fa_mode), ntohl (fap->fa_uid), ntohl (fap->fa_gid));
    if (v3)
    {
      TCHECK (fap->fa3_size);
      PUTS (" sz ");
      print_int64 ((u_int32_t*) &fap->fa3_size, UNSIGNED);
      PUTCHAR (' ');
    }
    else
    {
      TCHECK (fap->fa2_size);
      PRINTF (" sz %ld ", ntohl (fap->fa2_size));
    }
  }

  /* print lots more stuff
   */
  if (verbose > 1)
  {
    if (v3)
    {
      TCHECK (fap->fa3_ctime);
      PRINTF ("nlink %ld rdev %ld/%ld fsid",
              ntohl (fap->fa_nlink),
              ntohl (fap->fa3_rdev.specdata1),
              ntohl (fap->fa3_rdev.specdata2));

      print_int64 ((u_int32_t*)&fap->fa2_fsid, HEX);
      PUTS (" nodeid ");
      print_int64 ((u_int32_t*)&fap->fa2_fileid, HEX);
      PRINTF (" a/m/ctime %lu.%06lu %lu.%06lu %lu.%06lu ",
              ntohl (fap->fa3_atime.nfsv3_sec),
              ntohl (fap->fa3_atime.nfsv3_nsec),
              ntohl (fap->fa3_mtime.nfsv3_sec),
              ntohl (fap->fa3_mtime.nfsv3_nsec),
              ntohl (fap->fa3_ctime.nfsv3_sec),
              ntohl (fap->fa3_ctime.nfsv3_nsec));
    }
    else
    {
      TCHECK (fap->fa2_ctime);
      PRINTF ("nlink %ld rdev %lx fsid %lx nodeid %lx a/m/ctime ",
              ntohl (fap->fa_nlink),
              ntohl (fap->fa2_rdev),
              ntohl (fap->fa2_fsid),
              ntohl (fap->fa2_fileid));
      PRINTF ("%lu.%06lu %lu.%06lu %lu.%06lu ",
              ntohl (fap->fa2_atime.nfsv2_sec),
              ntohl (fap->fa2_atime.nfsv2_usec),
              ntohl (fap->fa2_mtime.nfsv2_sec),
              ntohl (fap->fa2_mtime.nfsv2_usec),
              ntohl (fap->fa2_ctime.nfsv2_sec),
              ntohl (fap->fa2_ctime.nfsv2_usec));
    }
  }
  return ((const u_int32_t*) ((unsigned char*) dp +
          (v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
trunc:
  return (NULL);
}

static __inline int parseattrstat (const u_int32_t *dp, int verbose, int v3)
{
  int er;

  dp = parsestatus (dp, &er);
  if (dp == NULL || er)
     return (0);
  return (parsefattr (dp, verbose, v3) != NULL);
}

static __inline int parsediropres (const u_int32_t *dp)
{
  int er;

  dp = parsestatus (dp, &er);
  if (dp == NULL || er)
     return (0);

  dp = parsefh (dp, 0);
  if (dp == NULL)
     return (0);
  return (parsefattr (dp, vflag, 0) != NULL);
}

static __inline int parselinkres (const u_int32_t *dp, int v3)
{
  int er;

  dp = parsestatus (dp, &er);
  if (dp == NULL || er)
     return (0);

  if (v3 && ((dp = parse_post_op_attr (dp, vflag)) != NULL))
     return (0);

  PUTCHAR (' ');
  return (parsefn (dp) != NULL);
}

static int parsestatfs (const u_int32_t *dp, int v3)
{
  const struct nfs_statfs *sfsp;
  int   er;

  dp = parsestatus (dp, &er);
  if (dp == NULL || (!v3 && er))
     return (0);

  if (qflag)
     return (1);

  if (v3)
  {
    if (vflag)
       PUTS (" POST:");
    if ((dp = parse_post_op_attr (dp, vflag)) == NULL)
       return (0);
  }

  TCHECK2 (dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));

  sfsp = (const struct nfs_statfs*)dp;

  if (v3)
  {
    PUTS (" tbytes ");
    print_int64 ((u_int32_t*)&sfsp->sf_tbytes, UNSIGNED);
    PUTS (" fbytes ");
    print_int64 ((u_int32_t*)&sfsp->sf_fbytes, UNSIGNED);
    PUTS (" abytes ");
    print_int64 ((u_int32_t*)&sfsp->sf_abytes, UNSIGNED);
    if (vflag)
    {
      PUTS (" tfiles ");
      print_int64 ((u_int32_t*)&sfsp->sf_tfiles, UNSIGNED);
      PUTS (" ffiles ");
      print_int64 ((u_int32_t*)&sfsp->sf_ffiles, UNSIGNED);
      PUTS (" afiles ");
      print_int64 ((u_int32_t*)&sfsp->sf_afiles, UNSIGNED);
      PRINTF (" invar %lu", ntohl (sfsp->sf_invarsec));
    }
  }
  else
    PRINTF (" tsize %ld bsize %ld blocks %ld bfree %ld bavail %ld",
            ntohl (sfsp->sf_tsize),
            ntohl (sfsp->sf_bsize),
            ntohl (sfsp->sf_blocks),
            ntohl (sfsp->sf_bfree),
            ntohl (sfsp->sf_bavail));

  return (1);
trunc:
  return (0);
}

static int parserddires (const u_int32_t * dp)
{
  int er;

  dp = parsestatus (dp, &er);
  if (dp == NULL || er)
     return (0);
  if (qflag)
     return (1);

  TCHECK (dp[2]);
  PRINTF (" offset %lx size %ld ", ntohl (dp[0]), ntohl (dp[1]));
  if (dp[2])
     PUTS ("eof");

  return (1);
trunc:
  return (0);
}

static __inline const u_int32_t *parse_wcc_attr (const u_int32_t *dp)
{
  PUTS (" sz ");
  print_int64 (dp, UNSIGNED);
  PRINTF (" mtime %lu.%06lu ctime %lu.%06lu",
          ntohl (dp[2]), ntohl (dp[3]), ntohl (dp[4]), ntohl (dp[5]));
  return (dp + 6);
}

/*
 * Pre operation attributes. Print only if vflag > 1.
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -