Exemple #1
0
voidp
xmalloc(int len)
{
  voidp p;
  int retries = 600;

  /*
   * Avoid malloc's which return NULL for malloc(0)
   */
  if (len == 0)
    len = 1;

  do {
    p = (voidp) malloc((unsigned) len);
    if (p) {
#if defined(DEBUG) && defined(DEBUG_MEM)
      amuDebug(D_MEM)
	plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
      return p;
    }
    if (retries > 0) {
      plog(XLOG_ERROR, "Retrying memory allocation");
      sleep(1);
    }
  } while (--retries);

  plog(XLOG_FATAL, "Out of memory");
  going_down(1);

  abort();

  return 0;
}
Exemple #2
0
voidp
xrealloc(voidp ptr, int len)
{
  if (amuDebug(D_MEM))
    plog(XLOG_DEBUG, "Reallocated size %d; block %p", len, ptr);

  if (len == 0)
    len = 1;

  if (ptr)
    ptr = (voidp) realloc(ptr, (unsigned) len);
  else
    ptr = (voidp) xmalloc((unsigned) len);

  if (!ptr) {
    plog(XLOG_FATAL, "Out of memory in realloc");
    going_down(1);
    abort();
  }
  return ptr;
}
Exemple #3
0
voidp
xrealloc(voidp ptr, int len)
{
#if defined(DEBUG) && defined(DEBUG_MEM)
  amuDebug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
#endif /* defined(DEBUG) && defined(DEBUG_MEM) */

  if (len == 0)
    len = 1;

  if (ptr)
    ptr = (voidp) realloc(ptr, (unsigned) len);
  else
    ptr = (voidp) xmalloc((unsigned) len);

  if (!ptr) {
    plog(XLOG_FATAL, "Out of memory in realloc");
    going_down(1);
    abort();
  }
  return ptr;
}
Exemple #4
0
int
main(int argc, char *argv[])
{
  char *domdot, *verstr, *vertmp;
  int ppid = 0;
  int error;
  char *progname = NULL;		/* "amd" */
  char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */

  /*
   * Make sure some built-in assumptions are true before we start
   */
  assert(sizeof(nfscookie) >= sizeof(u_int));
  assert(sizeof(int) >= 4);

  /*
   * Set processing status.
   */
  amd_state = Start;

  /*
   * Determine program name
   */
  if (argv[0]) {
    progname = strrchr(argv[0], '/');
    if (progname && progname[1])
      progname++;
    else
      progname = argv[0];
  }
  if (!progname)
    progname = "amd";
  am_set_progname(progname);

  /*
   * Initialize process id.  This is kept
   * cached since it is used for generating
   * and using file handles.
   */
  am_set_mypid();

  /*
   * Get local machine name
   */
  if (gethostname(hostname, sizeof(hostname)) < 0) {
    plog(XLOG_FATAL, "gethostname: %m");
    going_down(1);
  }
  hostname[sizeof(hostname) - 1] = '\0';

  /*
   * Check it makes sense
   */
  if (!*hostname) {
    plog(XLOG_FATAL, "host name is not set");
    going_down(1);
  }

  /*
   * Initialize global options structure.
   */
  init_global_options();

  /*
   * Partially initialize hostd[].  This
   * is completed in get_args().
   */
  if ((domdot = strchr(hostname, '.'))) {
    /*
     * Hostname already contains domainname.
     * Split out hostname and domainname
     * components
     */
    *domdot++ = '\0';
    hostdomain = domdot;
  }
  xstrlcpy(hostd, hostname, sizeof(hostd));
  am_set_hostname(hostname);

  /*
   * Setup signal handlers
   */
  /* SIGINT: trap interrupts for shutdowns */
  setup_sighandler(SIGINT, sigterm);
  /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
  setup_sighandler(SIGTERM, sigterm);
  /* SIGHUP: hangups tell us to reload the cache */
  setup_sighandler(SIGHUP, sighup);
  /*
   * SIGCHLD: trap Death-of-a-child.  These allow us to pick up the exit
   * status of backgrounded mounts.  See "sched.c".
   */
  setup_sighandler(SIGCHLD, sigchld);
#ifdef HAVE_SIGACTION
  /* construct global "masked_sigs" used in nfs_start.c */
  sigemptyset(&masked_sigs);
  sigaddset(&masked_sigs, SIGINT);
  sigaddset(&masked_sigs, SIGTERM);
  sigaddset(&masked_sigs, SIGHUP);
  sigaddset(&masked_sigs, SIGCHLD);
#endif /* HAVE_SIGACTION */

  /*
   * Fix-up any umask problems.  Most systems default
   * to 002 which is not too convenient for our purposes
   */
  orig_umask = umask(0);

  /*
   * Figure out primary network name
   */
  getwire(&PrimNetName, &PrimNetNum);

  /*
   * Determine command-line arguments
   */
  get_args(argc, argv);

  /*
   * Log version information.
   */
  vertmp = get_version_string();
  verstr = strtok(vertmp, "\n");
  plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
  while (verstr) {
    plog(XLOG_INFO, "%s", verstr);
    verstr = strtok(NULL, "\n");
  }
  XFREE(vertmp);

  /*
   * Get our own IP address so that we can mount the automounter.  We pass
   * localhost_address which could be used as the default localhost
   * name/address in amu_get_myaddress().
   */
  amu_get_myaddress(&myipaddr, gopt.localhost_address);
  plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));

  /* avoid hanging on other NFS servers if started elsewhere */
  if (chdir("/") < 0)
    plog(XLOG_INFO, "cannot chdir to /: %m");

  /*
   * Now check we are root.
   */
  if (geteuid() != 0) {
    plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
    going_down(1);
  }

#ifdef HAVE_MAP_NIS
  /*
   * If the domain was specified then bind it here
   * to circumvent any default bindings that may
   * be done in the C library.
   */
  if (gopt.nis_domain && yp_bind(gopt.nis_domain)) {
    plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain);
    going_down(1);
  }
#endif /* HAVE_MAP_NIS */

  if (!amuDebug(D_DAEMON))
    ppid = daemon_mode();

  /*
   * Lock process text and data segment in memory.
   */
  if (gopt.flags & CFM_PROCESS_LOCK) {
    do_memory_locking();
  }

  do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;

  /*
   * Register automounter with system.
   */
  error = mount_automounter(ppid);
  if (error && ppid)
    kill(ppid, SIGALRM);

#ifdef HAVE_FS_AUTOFS
  /*
   * XXX this should be part of going_down(), but I can't move it there
   * because it would be calling non-library code from the library... ugh
   */
  if (amd_use_autofs)
    destroy_autofs_service();
#endif /* HAVE_FS_AUTOFS */

  going_down(error);

  abort();
  return 1; /* should never get here */
}
Exemple #5
0
void
nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
{
  union {
    am_nfs_fh		nfsproc_getattr_2_arg;
    nfssattrargs	nfsproc_setattr_2_arg;
    nfsdiropargs	nfsproc_lookup_2_arg;
    am_nfs_fh		nfsproc_readlink_2_arg;
    nfsreadargs		nfsproc_read_2_arg;
    nfswriteargs	nfsproc_write_2_arg;
    nfscreateargs	nfsproc_create_2_arg;
    nfsdiropargs	nfsproc_remove_2_arg;
    nfsrenameargs	nfsproc_rename_2_arg;
    nfslinkargs		nfsproc_link_2_arg;
    nfssymlinkargs	nfsproc_symlink_2_arg;
    nfscreateargs	nfsproc_mkdir_2_arg;
    nfsdiropargs	nfsproc_rmdir_2_arg;
    nfsreaddirargs	nfsproc_readdir_2_arg;
    am_nfs_fh		nfsproc_statfs_2_arg;
  } argument;
  char *result;
  xdrproc_t xdr_argument, xdr_result;
  nfssvcproc_t local;

  nfs_program_2_transp = NULL;

  switch (rqstp->rq_proc) {

  case NFSPROC_NULL:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_null_2_svc;
    break;

  case NFSPROC_GETATTR:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_getattr_2_svc;
    break;

  case NFSPROC_SETATTR:
    xdr_argument = (xdrproc_t) xdr_sattrargs;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_setattr_2_svc;
    break;

  case NFSPROC_ROOT:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_root_2_svc;
    break;

  case NFSPROC_LOOKUP:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_lookup_2_svc;
    /*
     * Cheap way to pass transp down to afs_lookuppn so it can
     * be stored in the am_node structure and later used for
     * quick_reply().
     */
    nfs_program_2_transp = transp;
    break;

  case NFSPROC_READLINK:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_readlinkres;
    local = (nfssvcproc_t) nfsproc_readlink_2_svc;
    break;

  case NFSPROC_READ:
    xdr_argument = (xdrproc_t) xdr_readargs;
    xdr_result = (xdrproc_t) xdr_readres;
    local = (nfssvcproc_t) nfsproc_read_2_svc;
    break;

  case NFSPROC_WRITECACHE:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_writecache_2_svc;
    break;

  case NFSPROC_WRITE:
    xdr_argument = (xdrproc_t) xdr_writeargs;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_write_2_svc;
    break;

  case NFSPROC_CREATE:
    xdr_argument = (xdrproc_t) xdr_createargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_create_2_svc;
    break;

  case NFSPROC_REMOVE:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_remove_2_svc;
    break;

  case NFSPROC_RENAME:
    xdr_argument = (xdrproc_t) xdr_renameargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_rename_2_svc;
    break;

  case NFSPROC_LINK:
    xdr_argument = (xdrproc_t) xdr_linkargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_link_2_svc;
    break;

  case NFSPROC_SYMLINK:
    xdr_argument = (xdrproc_t) xdr_symlinkargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_symlink_2_svc;
    break;

  case NFSPROC_MKDIR:
    xdr_argument = (xdrproc_t) xdr_createargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_mkdir_2_svc;
    break;

  case NFSPROC_RMDIR:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_rmdir_2_svc;
    break;

  case NFSPROC_READDIR:
    xdr_argument = (xdrproc_t) xdr_readdirargs;
    xdr_result = (xdrproc_t) xdr_readdirres;
    local = (nfssvcproc_t) nfsproc_readdir_2_svc;
    break;

  case NFSPROC_STATFS:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_statfsres;
    local = (nfssvcproc_t) nfsproc_statfs_2_svc;
    break;

  default:
    svcerr_noproc(transp);
    return;
  }

  memset((char *) &argument, 0, sizeof(argument));
  if (!svc_getargs(transp,
		   (XDRPROC_T_TYPE) xdr_argument,
		   (SVC_IN_ARG_TYPE) &argument)) {
    plog(XLOG_ERROR,
	 "NFS xdr decode failed for %d %d %d",
	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
    svcerr_decode(transp);
    return;
  }
  result = (*local) (&argument, rqstp);

  nfs_program_2_transp = NULL;

  if (result != NULL && !svc_sendreply(transp,
				       (XDRPROC_T_TYPE) xdr_result,
				       result)) {
    svcerr_systemerr(transp);
  }
  if (!svc_freeargs(transp,
		    (XDRPROC_T_TYPE) xdr_argument,
		    (SVC_IN_ARG_TYPE) & argument)) {
    plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2");
    going_down(1);
  }
}
Exemple #6
0
void
nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
{
  union {
    am_nfs_fh		nfsproc_getattr_2_arg;
    nfssattrargs	nfsproc_setattr_2_arg;
    nfsdiropargs	nfsproc_lookup_2_arg;
    am_nfs_fh		nfsproc_readlink_2_arg;
    nfsreadargs		nfsproc_read_2_arg;
    nfswriteargs	nfsproc_write_2_arg;
    nfscreateargs	nfsproc_create_2_arg;
    nfsdiropargs	nfsproc_remove_2_arg;
    nfsrenameargs	nfsproc_rename_2_arg;
    nfslinkargs		nfsproc_link_2_arg;
    nfssymlinkargs	nfsproc_symlink_2_arg;
    nfscreateargs	nfsproc_mkdir_2_arg;
    nfsdiropargs	fsproc_rmdir_2_arg;
    nfsreaddirargs	nfsproc_readdir_2_arg;
    am_nfs_fh		nfsproc_statfs_2_arg;
  } argument;
  char *result;
  xdrproc_t xdr_argument, xdr_result;
  nfssvcproc_t local;

#ifdef HAVE_TRANSPORT_TYPE_TLI
  /*
   * On TLI systems we don't use an INET network type, but a "ticlts" (see
   * /etc/netconfig and conf/transp_tli.c:create_nfs_service).  This means
   * that packets could only come from the loopback interface, and we don't
   * need to check them and filter possibly spoofed packets.  Therefore we
   * only need to check if the UID caller is correct.
   */
# ifdef HAVE___RPC_GET_LOCAL_UID
  uid_t u;
  /* extern definition for an internal libnsl function */
  extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
  if (__rpc_get_local_uid(transp, &u) >= 0  &&  u != 0) {
    plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
    return;
  }
# else /* not HAVE___RPC_GET_LOCAL_UID */
  dlog("cannot verify local uid for rpc request");
# endif /* HAVE___RPC_GET_LOCAL_UID */
#else /* not HAVE_TRANPORT_TYPE_TLI */
  struct sockaddr_in *sinp;
  char dq[20], dq2[28];
  sinp = amu_svc_getcaller(rqstp->rq_xprt);
# ifdef MNT2_NFS_OPT_RESVPORT
  /* Verify that the request comes from a reserved port */
  if (sinp &&
      ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
      !(gopt.flags & CFM_NFS_INSECURE_PORT)) {
    plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
	 inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
	 ntohs(sinp->sin_port));
    return;
  }
# endif /* MNT2_NFS_OPT_RESVPORT */
  /* if the address does not match, ignore the request */
  if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) {
    if (gopt.flags & CFM_NFS_ANY_INTERFACE) {
      if (!is_interface_local(sinp->sin_addr.s_addr)) {
	plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
	     inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
	     ntohs(sinp->sin_port));
      }
    } else {
      plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
	   inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
	   ntohs(sinp->sin_port),
	   inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
      return;
    }
  }
#endif /* not HAVE_TRANPORT_TYPE_TLI */

  current_transp = NULL;

  switch (rqstp->rq_proc) {

  case NFSPROC_NULL:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_null_2_svc;
    break;

  case NFSPROC_GETATTR:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_getattr_2_svc;
    break;

  case NFSPROC_SETATTR:
    xdr_argument = (xdrproc_t) xdr_sattrargs;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_setattr_2_svc;
    break;

  case NFSPROC_ROOT:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_root_2_svc;
    break;

  case NFSPROC_LOOKUP:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_lookup_2_svc;
    /*
     * Cheap way to pass transp down to amfs_auto_lookuppn so it can
     * be stored in the am_node structure and later used for
     * quick_reply().
     */
    current_transp = transp;
    break;

  case NFSPROC_READLINK:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_readlinkres;
    local = (nfssvcproc_t) nfsproc_readlink_2_svc;
    break;

  case NFSPROC_READ:
    xdr_argument = (xdrproc_t) xdr_readargs;
    xdr_result = (xdrproc_t) xdr_readres;
    local = (nfssvcproc_t) nfsproc_read_2_svc;
    break;

  case NFSPROC_WRITECACHE:
    xdr_argument = (xdrproc_t) xdr_void;
    xdr_result = (xdrproc_t) xdr_void;
    local = (nfssvcproc_t) nfsproc_writecache_2_svc;
    break;

  case NFSPROC_WRITE:
    xdr_argument = (xdrproc_t) xdr_writeargs;
    xdr_result = (xdrproc_t) xdr_attrstat;
    local = (nfssvcproc_t) nfsproc_write_2_svc;
    break;

  case NFSPROC_CREATE:
    xdr_argument = (xdrproc_t) xdr_createargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_create_2_svc;
    break;

  case NFSPROC_REMOVE:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_remove_2_svc;
    break;

  case NFSPROC_RENAME:
    xdr_argument = (xdrproc_t) xdr_renameargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_rename_2_svc;
    break;

  case NFSPROC_LINK:
    xdr_argument = (xdrproc_t) xdr_linkargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_link_2_svc;
    break;

  case NFSPROC_SYMLINK:
    xdr_argument = (xdrproc_t) xdr_symlinkargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_symlink_2_svc;
    break;

  case NFSPROC_MKDIR:
    xdr_argument = (xdrproc_t) xdr_createargs;
    xdr_result = (xdrproc_t) xdr_diropres;
    local = (nfssvcproc_t) nfsproc_mkdir_2_svc;
    break;

  case NFSPROC_RMDIR:
    xdr_argument = (xdrproc_t) xdr_diropargs;
    xdr_result = (xdrproc_t) xdr_nfsstat;
    local = (nfssvcproc_t) nfsproc_rmdir_2_svc;
    break;

  case NFSPROC_READDIR:
    xdr_argument = (xdrproc_t) xdr_readdirargs;
    xdr_result = (xdrproc_t) xdr_readdirres;
    local = (nfssvcproc_t) nfsproc_readdir_2_svc;
    break;

  case NFSPROC_STATFS:
    xdr_argument = (xdrproc_t) xdr_nfs_fh;
    xdr_result = (xdrproc_t) xdr_statfsres;
    local = (nfssvcproc_t) nfsproc_statfs_2_svc;
    break;

  default:
    svcerr_noproc(transp);
    return;
  }

  memset((char *) &argument, 0, sizeof(argument));
  if (!svc_getargs(transp,
		   (XDRPROC_T_TYPE) xdr_argument,
		   (SVC_IN_ARG_TYPE) &argument)) {
    plog(XLOG_ERROR,
	 "NFS xdr decode failed for %d %d %d",
	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
    svcerr_decode(transp);
    return;
  }
  result = (*local) (&argument, rqstp);

  current_transp = NULL;

  if (result != NULL && !svc_sendreply(transp,
				       (XDRPROC_T_TYPE) xdr_result,
				       result)) {
    svcerr_systemerr(transp);
  }
  if (!svc_freeargs(transp,
		    (XDRPROC_T_TYPE) xdr_argument,
		    (SVC_IN_ARG_TYPE) & argument)) {
    plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2");
    going_down(1);
  }
}
Exemple #7
0
/*
 * Fill in the many possible fields and flags of struct nfs_args.
 *
 * nap:		pre-allocated structure to fill in.
 * mntp:	mount entry structure (includes options)
 * genflags:	generic mount flags already determined
 * nfsncp:	(TLI only) netconfig entry for this NFS mount
 * ip_addr:	IP address of file server
 * nfs_version:	2, 3, (4 in the future), or 0 if unknown
 * nfs_proto:	"udp", "tcp", or NULL.
 * fhp:		file handle structure pointer
 * host_name:	name of remote NFS host
 * fs_name:	remote file system name to mount
 */
void
compute_nfs_args(nfs_args_t *nap,
		 mntent_t *mntp,
		 int genflags,
		 struct netconfig *nfsncp,
		 struct sockaddr_in *ip_addr,
		 u_long nfs_version,
		 char *nfs_proto,
		 am_nfs_handle_t *fhp,
		 char *host_name,
		 char *fs_name)
{
  /* initialize just in case */
  memset((voidp) nap, 0, sizeof(nfs_args_t));

  /* compute all of the NFS attribute-cache flags */
  compute_nfs_attrcache_flags(nap, mntp);

  /************************************************************************/
  /***	FILEHANDLE DATA AND LENGTH					***/
  /************************************************************************/
#ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3) {
# if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
    /*
     * Some systems (Irix/bsdi3) have a separate field in nfs_args for
     * the length of the file handle for NFS V3.  They insist that
     * the file handle set in nfs_args be plain bytes, and not
     * include the length field.
     */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
# else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
# endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
# ifdef MNT2_NFS_OPT_NFSV3
    nap->flags |= MNT2_NFS_OPT_NFSV3;
# endif /* MNT2_NFS_OPT_NFSV3 */
# ifdef MNT2_NFS_OPT_VER3
    nap->flags |= MNT2_NFS_OPT_VER3;
# endif /* MNT2_NFS_OPT_VER3 */
  } else
#endif /* HAVE_FS_NFS3 */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);

#ifdef HAVE_NFS_ARGS_T_FHSIZE
# ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3)
    nap->fhsize = fhp->v3.am_fh3_length;
  else
# endif /* HAVE_FS_NFS3 */
    nap->fhsize = FHSIZE;
#endif /* HAVE_NFS_ARGS_T_FHSIZE */

  /* this is the version of the nfs_args structure, not of NFS! */
#ifdef HAVE_NFS_ARGS_T_FH_LEN
# ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3)
    nap->fh_len = fhp->v3.am_fh3_length;
  else
# endif /* HAVE_FS_NFS3 */
    nap->fh_len = FHSIZE;
#endif /* HAVE_NFS_ARGS_T_FH_LEN */

  /************************************************************************/
  /***	HOST NAME							***/
  /************************************************************************/
  /*
   * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
   * struct nfs_args, or truncate our concocted "hostname:/path"
   * string prematurely.
   */
  NFS_HN_DREF(nap->hostname, host_name);
#ifdef MNT2_NFS_OPT_HOSTNAME
  nap->flags |= MNT2_NFS_OPT_HOSTNAME;
#endif /* MNT2_NFS_OPT_HOSTNAME */

  /************************************************************************/
  /***	IP ADDRESS OF REMOTE HOST					***/
  /************************************************************************/
  if (ip_addr) {
#ifdef HAVE_TRANSPORT_TYPE_TLI
    nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
    NFS_SA_DREF(nap, ip_addr);
  }

  /************************************************************************/
  /***	NFS PROTOCOL (UDP, TCP) AND VERSION				***/
  /************************************************************************/
#ifdef MNT2_NFS_OPT_TCP
  if (nfs_proto && STREQ(nfs_proto, "tcp"))
    nap->flags |= MNT2_NFS_OPT_TCP;
#endif /* MNT2_NFS_OPT_TCP */

#ifdef HAVE_NFS_ARGS_T_SOTYPE
  /* bsdi3 uses this */
  if (nfs_proto) {
    if (STREQ(nfs_proto, "tcp"))
      nap->sotype = SOCK_STREAM;
    else if (STREQ(nfs_proto, "udp"))
      nap->sotype = SOCK_DGRAM;
  }
#endif /* HAVE_NFS_ARGS_T_SOTYPE */

#ifdef HAVE_NFS_ARGS_T_PROTO
  nap->proto = 0;		/* bsdi3 sets this field to zero  */
# ifdef IPPROTO_TCP
  if (nfs_proto) {
    if (STREQ(nfs_proto, "tcp"))	/* AIX 4.2.x needs this */
      nap->proto = IPPROTO_TCP;
    else if (STREQ(nfs_proto, "udp"))
      nap->proto = IPPROTO_UDP;
  }
# endif /* IPPROTO_TCP */
#endif /* HAVE_NFS_ARGS_T_SOTYPE */

#ifdef HAVE_NFS_ARGS_T_VERSION
# ifdef NFS_ARGSVERSION
  nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
# endif /* NFS_ARGSVERSION */
# ifdef DG_MOUNT_NFS_VERSION
  nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
# endif /* DG_MOUNT_NFS_VERSION */
#endif /* HAVE_NFS_ARGS_VERSION */

  /************************************************************************/
  /***	OTHER NFS SOCKET RELATED OPTIONS AND FLAGS			***/
  /************************************************************************/
#ifdef MNT2_NFS_OPT_NOCONN
  /* check if user specified to use unconnected or connected sockets */
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
    nap->flags |= MNT2_NFS_OPT_NOCONN;
  else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
    nap->flags &= ~MNT2_NFS_OPT_NOCONN;
  else {
    /*
     * Some OSs want you to set noconn always.  Some want you to always turn
     * it off.  Others want you to turn it on/off only if NFS V.3 is used.
     * And all of that changes from revision to another.  This is
     * particularly true of OpenBSD, NetBSD, and FreeBSD.  So, rather than
     * attempt to auto-detect this, I'm forced to "fix" it in the individual
     * conf/nfs_prot/nfs_prot_*.h files.
     */
# ifdef USE_UNCONNECTED_NFS_SOCKETS
    if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
      nap->flags |= MNT2_NFS_OPT_NOCONN;
      plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
    }
# endif /* USE_UNCONNECTED_NFS_SOCKETS */
# ifdef USE_CONNECTED_NFS_SOCKETS
    if (nap->flags & MNT2_NFS_OPT_NOCONN) {
      nap->flags &= ~MNT2_NFS_OPT_NOCONN;
      plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
    }
# endif /* USE_CONNECTED_NFS_SOCKETS */
  }
#endif /* MNT2_NFS_OPT_NOCONN */

#ifdef MNT2_NFS_OPT_RESVPORT
# ifdef MNTTAB_OPT_RESVPORT
  if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
    nap->flags |= MNT2_NFS_OPT_RESVPORT;
# else /* not MNTTAB_OPT_RESVPORT */
  nap->flags |= MNT2_NFS_OPT_RESVPORT;
# endif /* not MNTTAB_OPT_RESVPORT */
#endif /* MNT2_NFS_OPT_RESVPORT */

  /************************************************************************/
  /***	OTHER FLAGS AND OPTIONS						***/
  /************************************************************************/

#ifdef HAVE_TRANSPORT_TYPE_TLI
  /* set up syncaddr field */
  nap->syncaddr = (struct netbuf *) NULL;

  /* set up knconf field */
  if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
    plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
    going_down(1);
  }
  /* update the flags field for knconf */
  nap->flags |= MNT2_NFS_OPT_KNCONF;
#endif /* HAVE_TRANSPORT_TYPE_TLI */

#ifdef MNT2_NFS_OPT_FSNAME
  nap->fsname = fs_name;
  nap->flags |= MNT2_NFS_OPT_FSNAME;
#endif /* MNT2_NFS_OPT_FSNAME */

  nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
#ifdef MNT2_NFS_OPT_RSIZE
  if (nap->rsize)
    nap->flags |= MNT2_NFS_OPT_RSIZE;
#endif /* MNT2_NFS_OPT_RSIZE */
  if (nfs_version == NFS_VERSION && nap->rsize > 8192)
    nap->rsize = 8192;

  nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
#ifdef MNT2_NFS_OPT_WSIZE
  if (nap->wsize)
    nap->flags |= MNT2_NFS_OPT_WSIZE;
#endif /* MNT2_NFS_OPT_WSIZE */
  if (nfs_version == NFS_VERSION && nap->wsize > 8192)
    nap->wsize = 8192;

  nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
#ifdef MNT2_NFS_OPT_TIMEO
  if (nap->timeo)
    nap->flags |= MNT2_NFS_OPT_TIMEO;
#endif /* MNT2_NFS_OPT_TIMEO */

  nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
#ifdef MNT2_NFS_OPT_RETRANS
  if (nap->retrans)
    nap->flags |= MNT2_NFS_OPT_RETRANS;
#endif /* MNT2_NFS_OPT_RETRANS */

#ifdef MNT2_NFS_OPT_BIODS
  if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
    nap->flags |= MNT2_NFS_OPT_BIODS;
#endif /* MNT2_NFS_OPT_BIODS */

#ifdef MNT2_NFS_OPT_SOFT
  if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
    nap->flags |= MNT2_NFS_OPT_SOFT;
#endif /* MNT2_NFS_OPT_SOFT */

#ifdef MNT2_NFS_OPT_SPONGY
  if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
    nap->flags |= MNT2_NFS_OPT_SPONGY;
    if (nap->flags & MNT2_NFS_OPT_SOFT) {
      plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
      nap->flags &= ~MNT2_NFS_OPT_SOFT;
    }
  }
#endif /* MNT2_NFS_OPT_SPONGY */

#if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
  /* Ultrix has separate generic and NFS ro flags */
  if (genflags & MNT2_GEN_OPT_RONLY)
    nap->flags |= MNT2_NFS_OPT_RONLY;
#endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */

#ifdef MNTTAB_OPT_INTR
  if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
    /*
     * Either turn on the "allow interrupts" option, or
     * turn off the "disallow interrupts" option"
     */
# ifdef MNT2_NFS_OPT_INTR
    nap->flags |= MNT2_NFS_OPT_INTR;
# endif /* MNT2_NFS_OPT_INTR */
# ifdef MNT2_NFS_OPT_NOINTR
    nap->flags &= ~MNT2_NFS_OPT_NOINTR;
# endif /* MNT2_NFS_OPT_NOINTR */
# ifdef MNT2_NFS_OPT_INT
    nap->flags |= MNT2_NFS_OPT_INT;
# endif /* MNT2_NFS_OPT_INT */
# ifdef MNT2_NFS_OPT_NOINT
    nap->flags &= ~MNT2_NFS_OPT_NOINT;
# endif /* MNT2_NFS_OPT_NOINT */
#endif /* MNTTAB_OPT_INTR */

#ifdef MNTTAB_OPT_NODEVS
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
    nap->flags |= MNT2_NFS_OPT_NODEVS;
#endif /* MNTTAB_OPT_NODEVS */

#ifdef MNTTAB_OPT_COMPRESS
  if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
    nap->flags |= MNT2_NFS_OPT_COMPRESS;
#endif /* MNTTAB_OPT_COMPRESS */

#ifdef MNTTAB_OPT_PRIVATE	/* mount private, single-client tree */
  if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
    nap->flags |= MNT2_NFS_OPT_PRIVATE;
#endif /* MNTTAB_OPT_PRIVATE */

#ifdef MNTTAB_OPT_SYMTTL	/* symlink cache time-to-live */
  if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
    nap->flags |= MNT2_NFS_OPT_SYMTTL;
#endif /* MNTTAB_OPT_SYMTTL */

#ifdef MNT2_NFS_OPT_PGTHRESH	/* paging threshold */
  if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
    nap->flags |= MNT2_NFS_OPT_PGTHRESH;
#endif /* MNT2_NFS_OPT_PGTHRESH */

#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
    nap->flags |= MNT2_NFS_OPT_NOCTO;
#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */

#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
    nap->flags |= MNT2_NFS_OPT_POSIX;
# ifdef HAVE_NFS_ARGS_T_PATHCONF
    nap->pathconf = NULL;
# endif /* HAVE_NFS_ARGS_T_PATHCONF */
  }
#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */

#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
    nap->flags |= MNT2_NFS_OPT_PROPLIST;
#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */

#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
  nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
  if (nap->maxgrouplist != 0)
    nap->flags |= MNT2_NFS_OPT_MAXGRPS;
#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */

#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
    nap->flags |= MNT2_NFS_OPT_NONLM;
#endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */

#if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
    nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */

#ifdef HAVE_NFS_ARGS_T_OPTSTR
  nap->optstr = mntp->mnt_opts;
#endif /* HAVE_NFS_ARGS_T_OPTSTR */

  /************************************************************************/
  /***	FINAL ACTIONS							***/
  /************************************************************************/

#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
  /* Ultrix stores generic flags in nfs_args.gfs_flags. */
  nap->gfs_flags = genflags;
#endif /* HAVE_NFS_ARGS_T_FLAGS */

  return;			/* end of compute_nfs_args() function */
}