Beispiel #1
0
nfsdiropres *
nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
  static nfsdiropres res;
  am_node *mp;
  int retry;
  uid_t uid;
  gid_t gid;

  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "lookup:");

  /* finally, find the effective uid/gid from RPC request */
  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0)
    plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials");
  xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid);
  xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);

  mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
  if (mp == NULL) {
    if (retry < 0) {
      amd_stats.d_drops++;
      return 0;
    }
    res.dr_status = nfs_error(retry);
  } else {
    int error;
    am_node *ap;
    if (amuDebug(D_TRACE))
      plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name);
    ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE);
    if (ap && error < 0)
      ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error);
    if (ap == 0) {
      if (error < 0) {
	amd_stats.d_drops++;
	return 0;
      }
      res.dr_status = nfs_error(error);
    } else {
      /*
       * XXX: EXPERIMENTAL! Delay unmount of what was looked up.  This
       * should reduce the chance for race condition between unmounting an
       * entry synchronously, and re-mounting it asynchronously.
       */
      if (ap->am_ttl < mp->am_ttl)
 	ap->am_ttl = mp->am_ttl;
      mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle);
      res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr;
      res.dr_status = NFS_OK;
    }
    mp->am_stats.s_lookup++;
    /* reschedule_timeout_mp(); */
  }

  return &res;
}
Beispiel #2
0
nfsdiropres *
nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
  static nfsdiropres res;
  int idx;
  uid_t uid = (uid_t) INVALIDID;
  gid_t gid = (gid_t) INVALIDID;

  if (!started) {
    started++;
    rootfattr.na_ctime = startup;
    rootfattr.na_mtime = startup;
    slinkfattr.na_ctime = startup;
    slinkfattr.na_mtime = startup;
    un_fattr.na_ctime = startup;
    un_fattr.na_mtime = startup;
  }

  if (eq_fh(&argp->da_fhandle, &slink)) {
    res.dr_status = NFSERR_NOTDIR;
    return &res;
  }

  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
    res.dr_status = NFSERR_NOENT;
    return &res;
  }
  if (eq_fh(&argp->da_fhandle, &root)) {
    if (argp->da_name[0] == '.' &&
	(argp->da_name[1] == '\0' ||
	 (argp->da_name[1] == '.' &&
	  argp->da_name[2] == '\0'))) {
#if 0
    /*
     * XXX: increment mtime of parent directory, causes NFS clients to
     * invalidate their cache for that directory.
     * Some NFS clients may need this code.
     */
      if (uid != rootfattr.na_uid) {
	clocktime(&rootfattr.na_mtime);
	rootfattr.na_uid = uid;
      }
#endif /* 0 */
      res.dr_u.dr_drok_u.drok_fhandle = root;
      res.dr_u.dr_drok_u.drok_attributes = rootfattr;
      res.dr_status = NFS_OK;
      return &res;
    }

    if (STREQ(argp->da_name, slinkname)) {
#ifndef MNT2_NFS_OPT_SYMTTL
      /*
       * This code is needed to defeat Solaris 2.4's (and newer) symlink
       * values cache.  It forces the last-modified time of the symlink to be
       * current.  It is not needed if the O/S has an nfs flag to turn off the
       * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
       *
       * Additionally, Linux currently ignores the nt_useconds field,
       * so we must update the nt_seconds field every time.
       */
      if (uid != slinkfattr.na_uid) {
	clocktime(&slinkfattr.na_mtime);
	slinkfattr.na_uid = uid;
      }
#endif /* not MNT2_NFS_OPT_SYMTTL */
      res.dr_u.dr_drok_u.drok_fhandle = slink;
      res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
      res.dr_status = NFS_OK;
      return &res;
    }

    if (gid != hlfs_gid) {
      res.dr_status = NFSERR_NOENT;
      return &res;
    }

    /* if gets here, gid == hlfs_gid */
    if ((idx = untab_index(argp->da_name)) < 0) {
      res.dr_status = NFSERR_NOENT;
      return &res;
    } else {			/* entry found and gid is permitted */
      u_int xuid;
      un_fattr.na_fileid = untab[idx].uid;
      res.dr_u.dr_drok_u.drok_attributes = un_fattr;
      memset(&un_fhandle, 0, sizeof(am_nfs_fh));
      xuid = (u_int) untab[idx].uid;
      memcpy(un_fhandle.fh_data, &xuid, sizeof(xuid));
      xstrlcpy((char *) &un_fhandle.fh_data[sizeof(xuid)],
	       untab[idx].username,
	       sizeof(am_nfs_fh) - sizeof(xuid));
      res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
      res.dr_status = NFS_OK;
      dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
	   (long) uid, (long) gid, untab[idx].username);
      return &res;
    }
  } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */

  res.dr_status = NFSERR_STALE;
  return &res;
}
Beispiel #3
0
nfsreadlinkres *
nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
  static nfsreadlinkres res;
  uid_t userid = (uid_t) INVALIDID;
  gid_t groupid = hlfs_gid + 1;	/* anything not hlfs_gid */
  int retval = 0;
  char *path_val = NULL;
  char *username;
  static uid_t last_uid = (uid_t) INVALIDID;

  if (eq_fh(argp, &root)) {
    res.rlr_status = NFSERR_ISDIR;
  } else if (eq_fh(argp, &slink)) {
    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
      return (nfsreadlinkres *) NULL;

    clocktime(&slinkfattr.na_atime);

    res.rlr_status = NFS_OK;
    if (groupid == hlfs_gid) {
      res.rlr_u.rlr_data_u = DOTSTRING;
    } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
      /*
       * parent process (fork in homedir()) continues
       * processing, by getting a NULL returned as a
       * "special".  Child returns result.
       */
      return NULL;
    }

  } else {			/* check if asked for user mailbox */

    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
      return (nfsreadlinkres *) NULL;
    }

    if (groupid == hlfs_gid) {
      u_int xuserid;
      memcpy(&xuserid, argp->fh_data, sizeof(xuserid));
      userid = xuserid;
      username = (char *) &argp->fh_data[sizeof(xuserid)];
      if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
	return (nfsreadlinkres *) NULL;
    } else {
      res.rlr_status = NFSERR_STALE;
    }
  }

  /* print info, but try to avoid repetitions */
  if (userid != last_uid) {
    plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
	 (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
    last_uid = userid;
  }

  /* I don't think it will pass this if -D fork */
  if (serverpid == getpid())
    return &res;

  if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
    svcerr_systemerr(nfsxprt);

  /*
   * Child exists here.   We need to determine which
   * exist status to return.  The exit status
   * is gathered using wait() and determines
   * if we returned $HOME/.hlfsspool or $ALTDIR.  The parent
   * needs this info so it can update the lookup table.
   */
  if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
    retval = 1;		/* could not get real home dir (or uid 0 user) */
  else
    retval = 0;

  /*
   * If asked for -D nofork, then must return the value,
   * NOT exit, or else the main hlfsd server exits.
   * If -D fork (default), then we do want to exit from the process.
   * Bug: where is that status information being collected?
   */
  if (amuDebug(D_FORK))
    exit(retval);
  else
    return &res;
}
Beispiel #4
0
nfsattrstat *
nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
  static nfsattrstat res;
  uid_t uid = (uid_t) INVALIDID;
  gid_t gid = (gid_t) INVALIDID;

  if (!started) {
    started++;
    rootfattr.na_ctime = startup;
    rootfattr.na_mtime = startup;
    slinkfattr.na_ctime = startup;
    slinkfattr.na_mtime = startup;
    un_fattr.na_ctime = startup;
    un_fattr.na_mtime = startup;
  }

  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
    res.ns_status = NFSERR_STALE;
    return &res;
  }
  if (eq_fh(argp, &root)) {
#if 0
    /*
     * XXX: increment mtime of parent directory, causes NFS clients to
     * invalidate their cache for that directory.
     * Some NFS clients may need this code.
     */
    if (uid != rootfattr.na_uid) {
      clocktime(&rootfattr.na_mtime);
      rootfattr.na_uid = uid;
    }
#endif /* 0 */
    res.ns_status = NFS_OK;
    res.ns_u.ns_attr_u = rootfattr;
  } else if (eq_fh(argp, &slink)) {

#ifndef MNT2_NFS_OPT_SYMTTL
    /*
     * This code is needed to defeat Solaris 2.4's (and newer) symlink
     * values cache.  It forces the last-modified time of the symlink to be
     * current.  It is not needed if the O/S has an nfs flag to turn off the
     * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
     *
     * Additionally, Linux currently ignores the nt_useconds field,
     * so we must update the nt_seconds field every time.
     */
    if (uid != slinkfattr.na_uid) {
      clocktime(&slinkfattr.na_mtime);
      slinkfattr.na_uid = uid;
    }
#endif /* not MNT2_NFS_OPT_SYMTTL */

    res.ns_status = NFS_OK;
    res.ns_u.ns_attr_u = slinkfattr;
  } else {
    if (gid != hlfs_gid) {
      res.ns_status = NFSERR_STALE;
    } else {
      u_int xuid;
      memcpy(&xuid, argp->fh_data, sizeof(xuid));
      uid = xuid;
      if (plt_search(uid) != (uid2home_t *) NULL) {
	res.ns_status = NFS_OK;
	un_fattr.na_fileid = uid;
	res.ns_u.ns_attr_u = un_fattr;
	dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
	     (long) uid, (long) gid);
      } else {			/* not found */
	res.ns_status = NFSERR_STALE;
      }
    }
  }
  return &res;
}