Ejemplo n.º 1
0
/*
 * Find a file server.
 * Returns: fserver of found server, or NULL if not found.
 */
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
  char *cp, *ho;
  struct stat stb;

  if (mf->mf_fo == NULL) {
    plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
    return NULL;
  }
  ho = mf->mf_fo->opt_rhost;

  if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
    cp = mf->mf_fo->opt_sublink;
  else
    cp = mf->mf_fo->opt_fs;

  /*
   * If this host is not the same as $rhost, or if link does not exist,
   * call amfs_link_ops.ffserver().
   * If link value exists (or same host), then call ops_nfs.ffserver().
   */
  if ((!STRCEQ(ho, am_get_hostname()) &&
       !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
    return nfs_ops.ffserver(mf);
  } else {
    mf->mf_flags |= MFF_NFSLINK;
    /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
    mf->mf_fsflags &= ~FS_MKMNT;
    return amfs_link_ops.ffserver(mf);
  }
}
Ejemplo n.º 2
0
/*
 * Check that f/s has all needed fields.
 * Returns: matched string if found, NULL otherwise.
 */
static char *
amfs_nfsl_match(am_opts *fo)
{
  char *cp = fo->opt_fs;
  char *ho = fo->opt_rhost;
  struct stat stb;

  if (!cp || !ho) {
    plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
    return NULL;
  }

  /*
   * If this host is not the same as $rhost, or if link does not exist,
   * perform nfs_match(), same as for type:=nfs.
   * If link value exists (or same host), then perform amfs_link_match(),
   * same as for linkx.
   */
  if (!STRCEQ(ho, am_get_hostname())) {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
    return nfs_match(fo);
  } else if (lstat(cp, &stb) < 0) {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
    return nfs_match(fo);
  } else {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
    return amfs_link_match(fo);
  }
}
Ejemplo n.º 3
0
/*
 * Check that f/s has all needed fields.
 * Returns: matched string if found, NULL otherwise.
 */
static char *
amfs_nfsl_match(am_opts *fo)
{
  char *cp;
  char *ho = fo->opt_rhost;
  char *retval;
  struct stat stb;

  if (fo->opt_sublink && fo->opt_sublink[0])
    cp = fo->opt_sublink;
  else
    cp = fo->opt_fs;

  if (!cp || !ho) {
    plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
    return NULL;
  }

  /*
   * If this host is not the same as $rhost, or if link does not exist,
   * call nfs_ops.fs_match().
   * If link value exists (or same host), call amfs_link_ops.fs_match().
   */
  if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
	"or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
    retval = nfs_ops.fs_match(fo);
  } else if (lstat(cp, &stb) < 0) {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
    retval = nfs_ops.fs_match(fo);
  } else {
    plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
    retval = amfs_link_ops.fs_match(fo);
  }
  return retval;
}
Ejemplo n.º 4
0
/*
 * Output the time of day and hostname to the logfile
 */
static void
show_time_host_and_name(int lvl)
{
  static time_t last_t = 0;
  static char *last_ctime = 0;
  time_t t = clocktime();
  char *sev;

  if (t != last_t) {
    last_ctime = ctime(&t);
    last_t = t;
  }
  switch (lvl) {
  case XLOG_FATAL:
    sev = "fatal:";
    break;
  case XLOG_ERROR:
    sev = "error:";
    break;
  case XLOG_USER:
    sev = "user: "******"warn: ";
    break;
  case XLOG_INFO:
    sev = "info: ";
    break;
  case XLOG_DEBUG:
    sev = "debug:";
    break;
  case XLOG_MAP:
    sev = "map:  ";
    break;
  case XLOG_STATS:
    sev = "stats:";
    break;
  default:
    sev = "hmm:  ";
    break;
  }
  fprintf(logfp, "%15.15s %s %s[%ld]/%s ",
	  last_ctime + 4, am_get_hostname(),
	  am_get_progname(),
	  (long) am_mypid,
	  sev);
}
Ejemplo n.º 5
0
/*
 * Find a file server.
 * Returns: fserver of found server, or NULL if not found.
 */
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
  char *cp = mf->mf_fo->opt_fs;
  char *ho = mf->mf_fo->opt_rhost;
  struct stat stb;

  /*
   * If this host is not the same as $rhost, or if link does not exist,
   * perform find_nfs_srvr(), same as for type:=nfs.
   * If link value exists (or same host), then perform
   * find_amfs_auto_srvr(), same as for linkx.
   */
  if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
    return find_nfs_srvr(mf);
  } else {
    mf->mf_flags |= MFF_NFSLINK;
    return find_amfs_auto_srvr(mf);
  }
}
Ejemplo n.º 6
0
int
eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char *map)
{
  int ok = TRUE;

  free_opts(fo);

  /*
   * Clear out the option table
   */
  memset((voidp) &fs_static, 0, sizeof(fs_static));
  memset((voidp) vars, 0, sizeof(vars));
  memset((voidp) fo, 0, sizeof(*fo));

  /* set hostname */
  opt_host = (char *) am_get_hostname();

  /*
   * Set key, map & path before expansion
   */
  opt_key = key;
  opt_map = map;
  opt_path = path;

  opt_dkey = strchr(key, '.');
  if (!opt_dkey) {
    opt_dkey = NullStr;
    opt_keyd = key;
  } else {
    opt_keyd = strnsave(key, opt_dkey - key);
    opt_dkey++;
    if (*opt_dkey == '\0')	/* check for 'host.' */
      opt_dkey = NullStr;
  }

  /*
   * Expand global options
   */
  fs_static.fs_glob = expand_selectors(g_opts);

  /*
   * Expand local options
   */
  fs_static.fs_local = expand_selectors(opts);

  /* break global options into fs_static fields */
  if ((ok = split_opts(fs_static.fs_glob, key))) {
    dlog("global split_opts ok");
    /*
     * evaluate local selectors
     */
    if ((ok = eval_selectors(fs_static.fs_local, key))) {
      dlog("local eval_selectors ok");
      /* if the local selectors matched, then do the local overrides */
      ok = split_opts(fs_static.fs_local, key);
      if (ok)
	dlog("local split_opts ok");
    }
  }

  /*
   * Normalize remote host name.
   * 1.  Expand variables
   * 2.  Normalize relative to host tables
   * 3.  Strip local domains from the remote host
   *     name before using it in other expansions.
   *     This makes mount point names and other things
   *     much shorter, while allowing cross domain
   *     sharing of mount maps.
   */
  apply_opts(expand_opts, rhost_expansion, FALSE);
  if (ok && fs_static.opt_rhost && *fs_static.opt_rhost)
    host_normalize(&fs_static.opt_rhost);

  /*
   * Macro expand the options.
   * Do this regardless of whether we are accepting
   * this mount - otherwise nasty things happen
   * with memory allocation.
   */
  apply_opts(expand_opts, expansions, FALSE);

  /*
   * Strip trailing slashes from local pathname...
   */
  deslashify(fs_static.opt_fs);

  /*
   * ok... copy the data back out.
   */
  *fo = fs_static;

  /*
   * Clear defined options
   */
  if (opt_keyd != key && opt_keyd != nullstr)
    XFREE(opt_keyd);
  opt_keyd = nullstr;
  opt_dkey = NullStr;
  opt_key = opt_map = opt_path = nullstr;

  return ok;
}
Ejemplo n.º 7
0
/*
 * Return the version string (dynamic buffer)
 */
char *
get_version_string(void)
{
  char *vers = NULL;
  char tmpbuf[1024];
  char *wire_buf;
  int wire_buf_len = 0;
  size_t len;		  /* max allocated length (to avoid buf overflow) */

  /*
   * First get dynamic string listing all known networks.
   * This could be a long list, if host has lots of interfaces.
   */
  wire_buf = print_wires();
  if (wire_buf)
    wire_buf_len = strlen(wire_buf);

  len = 2048 + wire_buf_len;
  vers = xmalloc(len);
  xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
	    "Copyright (c) 1997-2006 Erez Zadok",
	    "Copyright (c) 1990 Jan-Simon Pendry",
	    "Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
	    "Copyright (c) 1990 The Regents of the University of California.");
  xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
	    PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
	    USER_NAME, HOST_NAME, CONFIG_DATE);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s.\n",
	    BUILD_USER, BUILD_HOST);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
	    cpu, endian, gopt.arch, gopt.karch);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
	    gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
  strlcat(vers, tmpbuf, len);
  xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
	    hostdomain, am_get_hostname(), hostd);
  strlcat(vers, tmpbuf, len);

  strlcat(vers, "Map support for: ", len);
  mapc_showtypes(tmpbuf, sizeof(tmpbuf));
  strlcat(vers, tmpbuf, len);
  strlcat(vers, ".\nAMFS: ", len);
  ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
  strlcat(vers, tmpbuf, len);
  strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
  ops_showfstypes(tmpbuf, sizeof(tmpbuf));
  strlcat(vers, tmpbuf, len);

  /* append list of networks if available */
  if (wire_buf) {
    strlcat(vers, wire_buf, len);
    XFREE(wire_buf);
  }

  return vers;
}
Ejemplo n.º 8
0
Archivo: xutil.c Proyecto: 0mp/freebsd
/*
 * Output the time of day and hostname to the logfile
 */
static void
show_time_host_and_name(int lvl)
{
  static time_t last_t = 0;
  static char *last_ctime = NULL;
  time_t t;
#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
  struct timespec ts;
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
  char nsecs[11];		/* '.' + 9 digits + '\0' */
  char *sev;

  nsecs[0] = '\0';

#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
  /*
   * Some systems (AIX 4.3) seem to implement clock_gettime() as stub
   * returning ENOSYS.
   */
  if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
    t = ts.tv_sec;
    if (amuDebug(D_HRTIME))
      xsnprintf(nsecs, sizeof(nsecs), ".%09ld", ts.tv_nsec);
  }
  else
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
    t = clocktime(NULL);

  if (t != last_t) {
    last_ctime = ctime(&t);
    last_t = t;
  }

  switch (lvl) {
  case XLOG_FATAL:
    sev = "fatal:";
    break;
  case XLOG_ERROR:
    sev = "error:";
    break;
  case XLOG_USER:
    sev = "user: "******"warn: ";
    break;
  case XLOG_INFO:
    sev = "info: ";
    break;
  case XLOG_DEBUG:
    sev = "debug:";
    break;
  case XLOG_MAP:
    sev = "map:  ";
    break;
  case XLOG_STATS:
    sev = "stats:";
    break;
  default:
    sev = "hmm:  ";
    break;
  }
  fprintf(logfp, "%15.15s%s %s %s[%ld]/%s ",
	  last_ctime + 4, nsecs, am_get_hostname(),
	  am_get_progname(),
	  (long) am_mypid,
	  sev);
}
Ejemplo n.º 9
0
/*
 * Mount an automounter directory.
 * The automounter is connected into the system
 * as a user-level NFS server.  mount_amfs_toplvl constructs
 * the necessary NFS parameters to be given to the
 * kernel so that it will talk back to us.
 *
 * NOTE: automounter mounts in themselves are using NFS Version 2.
 */
static int
mount_amfs_toplvl(char *dir, char *opts)
{
    char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
    int retry, error, genflags;
    mntent_t mnt;
    nfs_args_t nfs_args;
    am_nfs_fh *fhp;
    am_nfs_handle_t anh;
    MTYPE_TYPE type = MOUNT_TYPE_NFS;
#ifndef HAVE_TRANSPORT_TYPE_TLI
    u_short port;
    struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    memset((voidp) &mnt, 0, sizeof(mnt));
    mnt.mnt_dir = dir;
    mnt.mnt_fsname = pid_fsname;
    mnt.mnt_opts = opts;

    /*
     * Make sure that amd's top-level NFS mounts are hidden by default
     * from df.
     * If they don't appear to support the either the "ignore" mnttab
     * option entry, or the "auto" one, set the mount type to "nfs".
     */
    mnt.mnt_type = HIDE_MOUNT_TYPE;

    retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
    if (retry <= 0)
        retry = 2;			/* XXX */

    /*
     * SET MOUNT ARGS
     */
    /*
     * get fhandle of remote path for automount point
     */
    fhp = root_fh(dir);
    if (!fhp) {
        plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
        return EINVAL;
    }

#ifndef HAVE_TRANSPORT_TYPE_TLI
    /*
     * Create sockaddr to point to the local machine.  127.0.0.1
     * is not used since that will not work in HP-UX clusters and
     * this is no more expensive.
     */
    memset((voidp) &sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr = myipaddr;
    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
    if (port) {
        sin.sin_port = htons(port);
    } else {
        plog(XLOG_ERROR, "no port number specified for %s", dir);
        return EINVAL;
    }
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*
     * Make a ``hostname'' string for the kernel
     */
    sprintf(fs_hostname, "pid%ld@%s:%s",
            (long) (foreground ? am_mypid : getppid()),
            am_get_hostname(),
            dir);
    /*
     * Most kernels have a name length restriction (64 bytes)...
     */
    if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
        strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
#ifdef HOSTNAMESZ
    /*
     * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
     * If you need to get the definition for HOSTNAMESZ found, you may
     * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
     */
    if (strlen(fs_hostname) >= HOSTNAMESZ)
        strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
#endif /* HOSTNAMESZ */

    /*
     * Finally we can compute the mount genflags set above,
     * and add any automounter specific flags.
     */
    genflags = compute_mount_flags(&mnt);
    genflags |= compute_automounter_mount_flags(&mnt);

    /* setup the many fields and flags within nfs_args */
    memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
    compute_nfs_args(&nfs_args,
                     &mnt,
                     genflags,
                     nfsncp,
                     NULL,	/* remote host IP addr is set below */
                     NFS_VERSION,	/* version 2 */
                     "udp",
                     &anh,
                     fs_hostname,
                     pid_fsname);
    /*
     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
     * be done using the normal mechanism of compute_nfs_args(), because
     * that one will allocate a new address and use NFS_SA_DREF() to copy
     * parts to it, while assuming that the ip_addr passed is always
     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
     * because they define a special macro HOST_SELF which is DIFFERENT
     * than localhost (127.0.0.1)!
     */
    nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
    compute_nfs_args(&nfs_args,
                     &mnt,
                     genflags,
                     &sin,
                     NFS_VERSION,	/* version 2 */
                     "udp",
                     &anh,
                     fs_hostname,
                     pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*************************************************************************
     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	   *
     * the toplvl one is not, and so some options must be corrected by hand  *
     * more carefully, *after* compute_nfs_args() runs.			   *
     *************************************************************************/
    compute_automounter_nfs_args(&nfs_args, &mnt);

    /* This is it!  Here we try to mount amd on its mount points */
#ifdef DEBUG
    amuDebug(D_TRACE) {
        print_nfs_args(&nfs_args, 0);
        plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
    }
#endif /* DEBUG */
    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
                     0, NULL, mnttab_file_name);

#ifdef HAVE_TRANSPORT_TYPE_TLI
    free_knetconfig(nfs_args.knconf);
    /*
     * local automounter mounts do not allocate a special address, so
     * no need to XFREE(nfs_args.addr) under TLI.
     */
#endif /* HAVE_TRANSPORT_TYPE_TLI */

    return error;
}
Ejemplo n.º 10
0
/*
 * Map from conventional mount arguments to AIX 3,x style arguments.
 * But we avoid all the messy BIS stuff for AIX 5.x
 */
int
mount_aix3(char *fsname, char *dir, int flags, int type, void *data, char *mnt_opts)
{
  char buf[4096];
  int size, ret;
  int real_size = sizeof(nfs_args_t); /* size passed to aix5_mkvp() */
  char *real_args = data;	/* args passed to aix5_mkvp() */
  char *host, *rfs, *idx;
  int aix_type = type;
#ifdef HAVE_FS_NFS3
  struct nfs_args v2args;
  nfs_args_t *v3args = (nfs_args_t *) data;
#endif /* HAVE_FS_NFS3 */

#ifdef DEBUG
  dlog("mount_aix3: fsname %s, dir %s, type %d", fsname, dir, type);
#endif /* DEBUG */

  switch (aix_type) {

  case MOUNT_TYPE_NFS:

#ifdef HAVE_FS_NFS3
    /*
     * This is tricky.  If we have v3 support, but this nfs mount is v2,
     * then I must copy the arguments from the v3 nfs_args to the v2 one.
     */
    memmove((voidp) &v2args.addr, (voidp) &v3args->addr, sizeof(struct sockaddr_in));
    v2args.hostname = v3args->hostname;
    v2args.netname = v3args->netname;
    memmove((voidp) v2args.fh.x, v3args->fh, FHSIZE);
    v2args.flags = v3args->flags;
    v2args.wsize = v3args->wsize;
    v2args.rsize = v3args->rsize;
    v2args.timeo = v3args->timeo;
    v2args.retrans = v3args->retrans;
    v2args.acregmin = v3args->acregmin;
    v2args.acregmax = v3args->acregmax;
    v2args.acdirmin = v3args->acdirmin;
    v2args.acdirmax = v3args->acdirmax;
    v2args.pathconf = v3args->pathconf;

    /* now set real_* stuff */
    real_size = sizeof(v2args);
    real_args = (char *) &v2args;

  case MOUNT_TYPE_NFS3:
#endif /* HAVE_FS_NFS3 */

    idx = strchr(fsname, ':');
    if (idx) {
      *idx = '\0';
      rfs = strdup(idx + 1);
      host = strdup(fsname);
      *idx = ':';
    } else {
      rfs = strdup(fsname);
      host = strdup(am_get_hostname());
    }

    size = aix5_mkvp(buf, type, flags, rfs, dir, host,
		     real_args, real_size, mnt_opts);
    XFREE(rfs);
    XFREE(host);
    break;

  case MOUNT_TYPE_UFS:
    /* Need to open block device and extract log device info from sblk. */
    return EINVAL;

  default:
    return EINVAL;
  }

  /*
   * XXX: Warning, if vmount() hangs your amd in AIX 5.1, it
   * is because of a kernel bug in the NFS code.  Get a patch from IBM
   * or upgrade to 5.2.
   */
  ret = vmount((struct vmount *)buf, size);
  if (ret < 0) {
    plog(XLOG_ERROR, "mount_aix3: vmount failed with errno %d", errno);
    perror ("vmount");
  }
  return ret;
}
Ejemplo n.º 11
0
int
mount_automounter(int ppid)
{
  /*
   * Old code replaced by rpc-trash patch.
   * Erez Zadok <*****@*****.**>
   int so = socket(AF_INET, SOCK_DGRAM, 0);
   */
  SVCXPRT *udp_amqp = NULL, *tcp_amqp = NULL;
  int nmount, ret;
  int soNFS;
  int udp_soAMQ, tcp_soAMQ;
  struct netconfig *udp_amqncp, *tcp_amqncp;

  /*
   * This must be done first, because it attempts to bind
   * to various UDP ports and we don't want anything else
   * potentially taking over those ports before we get a chance
   * to reserve them.
   */
  if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
    restart_automounter_nodes();

  /*
   * Start RPC forwarding
   */
  if (fwd_init() != 0)
    return 3;

  /*
   * Construct the root automount node
   */
  make_root_node();

  /*
   * Pick up the pieces from a previous run
   * This is likely to (indirectly) need the rpc_fwd package
   * so it *must* come after the call to fwd_init().
   */
  if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
    restart();

  /*
   * Create the nfs service for amd
   * If nfs_port is already initialized, it means we
   * already created the service during restart_automounter_nodes().
   */
  if (nfs_port == 0) {
    ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
    if (ret != 0)
      return ret;
  }
  xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
	    am_get_hostname(), (long) am_mypid, nfs_port);

  /* security: if user sets -D noamq, don't even create listening socket */
  if (amuDebug(D_AMQ)) {
    ret = create_amq_service(&udp_soAMQ,
			     &udp_amqp,
			     &udp_amqncp,
			     &tcp_soAMQ,
			     &tcp_amqp,
			     &tcp_amqncp,
			     gopt.preferred_amq_port);
    if (ret != 0)
      return ret;
  }

#ifdef HAVE_FS_AUTOFS
  if (amd_use_autofs) {
    /*
     * Create the autofs service for amd.
     */
    ret = create_autofs_service();
    /* if autofs service fails it is OK if using a test amd */
    if (ret != 0) {
      plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
      amd_use_autofs = 0;
    }
  }
#endif /* HAVE_FS_AUTOFS */

  /*
   * Mount the top-level auto-mountpoints
   */
  nmount = mount_exported();

  /*
   * Now safe to tell parent that we are up and running
   */
  if (ppid)
    kill(ppid, SIGQUIT);

  if (nmount == 0) {
    plog(XLOG_FATAL, "No work to do - quitting");
    amd_state = Done;
    return 0;
  }

  if (amuDebug(D_AMQ)) {
    /*
     * Complete registration of amq (first TCP service then UDP)
     */
    int tcp_ok = 0, udp_ok = 0;

    unregister_amq();	 /* unregister leftover Amd, if any, just in case */

    tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
			      amq_program_1, IPPROTO_TCP, tcp_amqncp);
    if (!tcp_ok)
      plog(XLOG_FATAL,
	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
	   get_amd_program_number());

    udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
			      amq_program_1, IPPROTO_UDP, udp_amqncp);
    if (!udp_ok)
      plog(XLOG_FATAL,
	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
	   get_amd_program_number());

    /* return error only if both failed */
    if (!tcp_ok && !udp_ok) {
      amd_state = Done;
      return 3;
    }
  }

  /*
   * Start timeout_mp rolling
   */
  reschedule_timeout_mp();

  /*
   * Start the server
   */
  if (run_rpc() != Done) {
    plog(XLOG_FATAL, "run_rpc failed");
    amd_state = Done;
  }
  return 0;
}
Ejemplo n.º 12
0
Archivo: autil.c Proyecto: 0mp/freebsd
/*
 * Mount an automounter directory.
 * The automounter is connected into the system
 * as a user-level NFS server.  amfs_mount constructs
 * the necessary NFS parameters to be given to the
 * kernel so that it will talk back to us.
 *
 * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
 *
 * NEW: on certain systems, mounting can be done using the
 * kernel-level automount (autofs) support. In that case,
 * we don't need NFS at all here.
 */
int
amfs_mount(am_node *mp, mntfs *mf, char *opts)
{
  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
  int retry, error = 0, genflags;
  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
  char *dir = mf->mf_mount;
  mntent_t mnt;
  MTYPE_TYPE type;
  int forced_unmount = 0;	/* are we using forced unmounts? */
  u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);

  memset(&mnt, 0, sizeof(mnt));
  mnt.mnt_dir = dir;
  mnt.mnt_fsname = pid_fsname;
  mnt.mnt_opts = opts;

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_IS_AUTOFS) {
    type = MOUNT_TYPE_AUTOFS;
    /*
     * Make sure that amd's top-level autofs mounts are hidden by default
     * from df.
     * XXX: It works ok on Linux, might not work on other systems.
     */
    mnt.mnt_type = "autofs";
  } else
#endif /* HAVE_FS_AUTOFS */
  {
    type = MOUNT_TYPE_NFS;
    /*
     * Make sure that amd's top-level NFS mounts are hidden by default
     * from df.
     * If they don't appear to support the either the "ignore" mnttab
     * option entry, or the "auto" one, set the mount type to "nfs".
     */
    mnt.mnt_type = HIDE_MOUNT_TYPE;
  }

  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
  if (retry <= 0)
    retry = 2;			/* XXX: default to 2 retries */

  /*
   * SET MOUNT ARGS
   */

  /*
   * Make a ``hostname'' string for the kernel
   */
  xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
	    get_server_pid(), am_get_hostname(), dir);
  /*
   * Most kernels have a name length restriction (64 bytes)...
   */
  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
    xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
	     sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
#ifdef HOSTNAMESZ
  /*
   * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
   * If you need to get the definition for HOSTNAMESZ found, you may
   * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
   */
  if (strlen(fs_hostname) >= HOSTNAMESZ)
    xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
	     sizeof(fs_hostname) - HOSTNAMESZ + 3);
#endif /* HOSTNAMESZ */

  /*
   * Finally we can compute the mount genflags set above,
   * and add any automounter specific flags.
   */
  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
  genflags |= compute_automounter_mount_flags(&mnt);

again:
  if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
    nfs_args_t nfs_args;
    am_nfs_handle_t *fhp, anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
    u_short port;
    struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*
     * get fhandle of remote path for automount point
     */
    fhp = get_root_nfs_fh(dir, &anh);
    if (!fhp) {
      plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
      return EINVAL;
    }

#ifndef HAVE_TRANSPORT_TYPE_TLI
    /*
     * Create sockaddr to point to the local machine.
     */
    memset(&sin, 0, sizeof(sin));
    /* as per POSIX, sin_len need not be set (used internally by kernel) */
    sin.sin_family = AF_INET;
    sin.sin_addr = myipaddr;
    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
    if (port) {
      sin.sin_port = htons(port);
    } else {
      plog(XLOG_ERROR, "no port number specified for %s", dir);
      return EINVAL;
    }
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     nfsncp,
		     NULL,	/* remote host IP addr is set below */
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
    /*
     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
     * be done using the normal mechanism of compute_nfs_args(), because
     * that one will allocate a new address and use NFS_SA_DREF() to copy
     * parts to it, while assuming that the ip_addr passed is always
     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
     * because they define a special macro HOST_SELF which is DIFFERENT
     * than localhost (127.0.0.1)!
     */
    nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     NULL,
		     &sin,
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*************************************************************************
     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	     *
     * the toplvl one is not quite regular, and so some options must be      *
     * corrected by hand more carefully, *after* compute_nfs_args() runs.    *
     *************************************************************************/
    compute_automounter_nfs_args(&nfs_args, &mnt);

    if (amuDebug(D_TRACE)) {
      print_nfs_args(&nfs_args, 0);
      plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
    }

    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);

#ifdef HAVE_TRANSPORT_TYPE_TLI
    free_knetconfig(nfs_args.knconf);
    /*
     * local automounter mounts do not allocate a special address, so
     * no need to XFREE(nfs_args.addr) under TLI.
     */
#endif /* HAVE_TRANSPORT_TYPE_TLI */

#ifdef HAVE_FS_AUTOFS
  } else {
    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);
#endif /* HAVE_FS_AUTOFS */
  }
  if (error == 0 || forced_unmount)
     return error;

  /*
   * If user wants forced/lazy unmount semantics, then try it iff the
   * current mount failed with EIO or ESTALE.
   */
  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
    switch (errno) {
    case ESTALE:
    case EIO:
      forced_unmount = errno;
      plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
      if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
			     AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
	plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
	errno = forced_unmount;
      } else
	goto again;
    default:
      break;
    }
  }

  return error;
}