aboutsummaryrefslogtreecommitdiff
path: root/contrib/amd/amd
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>2007-12-05 16:57:05 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>2007-12-05 16:57:05 +0000
commitaa1670f3e4eb7d6c1cc2d154c0c1b23e00259e32 (patch)
treee7b85ce620ca0374e09e7d585e7a5276830543ab /contrib/amd/amd
parent1e2f6b2e5fbfd49bab3ea57cbebfeac155ac573d (diff)
downloadsrc-aa1670f3e4eb7d6c1cc2d154c0c1b23e00259e32.tar.gz
src-aa1670f3e4eb7d6c1cc2d154c0c1b23e00259e32.zip
Put stock 6.1.5 file into HEAD.
Notes
Notes: svn path=/head/; revision=174313
Diffstat (limited to 'contrib/amd/amd')
-rw-r--r--contrib/amd/amd/amq_subr.c124
-rw-r--r--contrib/amd/amd/get_args.c250
-rw-r--r--contrib/amd/amd/nfs_prot_svc.c66
-rw-r--r--contrib/amd/amd/ops_pcfs.c92
-rw-r--r--contrib/amd/amd/srvr_nfs.c589
5 files changed, 720 insertions, 401 deletions
diff --git a/contrib/amd/amd/amq_subr.c b/contrib/amd/amd/amq_subr.c
index a5c7f247c68e..79ecafc3d9b3 100644
--- a/contrib/amd/amd/amq_subr.c
+++ b/contrib/amd/amd/amq_subr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2004 Erez Zadok
+ * 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.
@@ -36,10 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * %W% (Berkeley) %G%
*
- * $Id: amq_subr.c,v 1.6.2.6 2004/01/19 00:25:55 ezk Exp $
- * $FreeBSD$
+ * File: am-utils/amd/amq_subr.c
*
*/
/*
@@ -112,8 +110,10 @@ amq_mount_tree_list *
amqproc_export_1_svc(voidp argp, struct svc_req *rqstp)
{
static amq_mount_tree_list aml;
+ static am_node *mp;
- aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0];
+ mp = get_exported_ap(0);
+ aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp);
aml.amq_mount_tree_list_len = 1; /* XXX */
return &aml;
@@ -131,16 +131,14 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
switch (opt->as_opt) {
case AMOPT_DEBUG:
-#ifdef DEBUG
if (debug_option(opt->as_str))
-#endif /* DEBUG */
rc = EINVAL;
break;
case AMOPT_LOGFILE:
if (gopt.logfile && opt->as_str
&& STREQ(gopt.logfile, opt->as_str)) {
- if (switch_to_logfile(opt->as_str, orig_umask))
+ if (switch_to_logfile(opt->as_str, orig_umask, 0))
rc = EINVAL;
} else {
rc = EACCES;
@@ -156,8 +154,8 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
if (amd_state == Run) {
plog(XLOG_INFO, "amq says flush cache");
do_mapc_reload = 0;
- flush_nfs_fhandle_cache((fserver *) 0);
- flush_srvr_nfs_cache();
+ flush_nfs_fhandle_cache((fserver *) NULL);
+ flush_srvr_nfs_cache((fserver *) NULL);
}
break;
}
@@ -169,7 +167,7 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
amq_mount_info_list *
amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
{
- return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
+ return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
}
@@ -195,6 +193,64 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
/*
+ * Process PAWD string of remote pawd tool.
+ *
+ * We repeat the resolution of the string until the resolved string resolves
+ * to itself. This ensures that we follow path resolutions through all
+ * possible Amd mount points until we reach some sort of convergence. To
+ * prevent possible infinite loops, we break out of this loop if the strings
+ * do not converge after MAX_PAWD_TRIES times.
+ */
+amq_string *
+amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
+{
+ static amq_string res;
+#define MAX_PAWD_TRIES 10
+ int index, len, maxagain = MAX_PAWD_TRIES;
+ am_node *mp;
+ char *mountpoint;
+ char *dir = *(char **) argp;
+ static char tmp_buf[MAXPATHLEN];
+ char prev_buf[MAXPATHLEN];
+
+ tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
+ do {
+ for (mp = get_first_exported_ap(&index);
+ mp;
+ mp = get_next_exported_ap(&index)) {
+ if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
+ continue;
+ if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
+ continue;
+ mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+ len = strlen(mountpoint);
+ if (len == 0)
+ continue;
+ if (!NSTREQ(mountpoint, dir, len))
+ continue;
+ if (dir[len] != '\0' && dir[len] != '/')
+ continue;
+ xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
+ xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
+ break;
+ } /* end of "for" loop */
+ /* once tmp_buf and prev_buf are equal, break out of "do" loop */
+ if (STREQ(tmp_buf, prev_buf))
+ break;
+ else
+ xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
+ } while (--maxagain);
+ /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
+ if (maxagain <= 0)
+ plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
+ tmp_buf, MAX_PAWD_TRIES);
+
+ res = tmp_buf;
+ return &res;
+}
+
+
+/*
* XDR routines.
*/
@@ -202,7 +258,7 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
bool_t
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
{
- if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) {
+ if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
@@ -267,10 +323,16 @@ xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
return (FALSE);
}
- if (!xdr_pointer(xdrs, (char **) &mp->am_osib, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+ if (!xdr_pointer(xdrs,
+ (char **) ((voidp) &mp->am_osib),
+ sizeof(amq_mount_tree),
+ (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
- if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+ if (!xdr_pointer(xdrs,
+ (char **) ((voidp) &mp->am_child),
+ sizeof(amq_mount_tree),
+ (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
return (TRUE);
@@ -281,15 +343,21 @@ bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{
am_node *mp = (am_node *) objp;
- am_node *mnil = 0;
+ am_node *mnil = NULL;
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
return (FALSE);
}
- if (!xdr_pointer(xdrs, (char **) ((void *)&mnil), sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+ if (!xdr_pointer(xdrs,
+ (char **) ((voidp) &mnil),
+ sizeof(amq_mount_tree),
+ (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
- if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+ if (!xdr_pointer(xdrs,
+ (char **) ((voidp) &mp->am_child),
+ sizeof(amq_mount_tree),
+ (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
return (TRUE);
@@ -333,7 +401,7 @@ bool_t
xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
{
if (!xdr_array(xdrs,
- (char **) &objp->amq_mount_tree_list_val,
+ (char **) ((voidp) &objp->amq_mount_tree_list_val),
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),
@@ -355,7 +423,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
u_int len = 0;
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
- if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+ if (!(mf->mf_fsflags & FS_AMQINFO))
continue;
len++;
}
@@ -366,7 +434,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
*/
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
int up;
- if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+ if (!(mf->mf_fsflags & FS_AMQINFO))
continue;
if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
@@ -387,20 +455,12 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
if (!xdr_int(xdrs, &mf->mf_refc)) {
return (FALSE);
}
- if (mf->mf_server->fs_flags & FSF_ERROR)
+ if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
up = 0;
+ else if (FSRV_ISUP(mf->mf_server))
+ up = 1;
else
- switch (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) {
- case FSF_DOWN | FSF_VALID:
- up = 0;
- break;
- case FSF_VALID:
- up = 1;
- break;
- default:
- up = -1;
- break;
- }
+ up = -1;
if (!xdr_int(xdrs, &up)) {
return (FALSE);
}
diff --git a/contrib/amd/amd/get_args.c b/contrib/amd/amd/get_args.c
index e5c3edf09359..12a7d07efd59 100644
--- a/contrib/amd/amd/get_args.c
+++ b/contrib/amd/amd/get_args.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2004 Erez Zadok
+ * 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.
@@ -36,10 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * %W% (Berkeley) %G%
*
- * $Id: get_args.c,v 1.7.2.6 2004/01/06 03:15:16 ezk Exp $
- * $FreeBSD$
+ * File: am-utils/amd/get_args.c
*
*/
@@ -56,17 +54,12 @@
/* include auto-generated version file */
#include <build_version.h>
-char *conf_file = "/etc/amd.conf"; /* default amd configuration file */
+char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
char *conf_tag = NULL; /* default conf file tags to use */
int usage = 0;
int use_conf_file = 0; /* default don't use amd.conf file */
char *mnttab_file_name = NULL; /* symbol must be available always */
-#if 0
-#ifdef DEBUG
-int debug_flags = D_AMQ /* Register AMQ */
- | D_DAEMON; /* Enter daemon mode */
-#endif /* DEBUG */
-#endif
+
/*
* Return the version string (dynamic buffer)
@@ -74,48 +67,61 @@ int debug_flags = D_AMQ /* Register AMQ */
char *
get_version_string(void)
{
- static char *vers = NULL;
+ 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 */
+ /*
+ * 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);
- vers = xmalloc(2048 + wire_buf_len);
- sprintf(vers, "%s\n%s\n%s\n%s\n",
- "Copyright (c) 1997-2004 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.");
- sprintf(tmpbuf, "%s version %s (build %d).\n",
- PACKAGE, VERSION, AMU_BUILD_VERSION);
- strcat(vers, tmpbuf);
- sprintf(tmpbuf, "Built by %s@%s on date %s.\n",
- USER_NAME, HOST_NAME, CONFIG_DATE);
- strcat(vers, tmpbuf);
- sprintf(tmpbuf, "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
- cpu, endian, gopt.arch, gopt.karch);
- strcat(vers, tmpbuf);
- sprintf(tmpbuf, "full_os=%s, os=%s, osver=%s, vendor=%s.\n",
- gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor);
- strcat(vers, tmpbuf);
-
- strcat(vers, "Map support for: ");
- mapc_showtypes(tmpbuf);
- strcat(vers, tmpbuf);
- strcat(vers, ".\nAMFS: ");
- ops_showamfstypes(tmpbuf);
- strcat(vers, tmpbuf);
- strcat(vers, ".\nFS: ");
- ops_showfstypes(tmpbuf);
- strcat(vers, tmpbuf);
+ 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 on date %s.\n",
+ BUILD_USER, BUILD_HOST, BUILD_DATE);
+ 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) {
- strcat(vers, wire_buf);
+ strlcat(vers, wire_buf, len);
XFREE(wire_buf);
}
@@ -123,13 +129,48 @@ get_version_string(void)
}
+static void
+show_usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
+\t[-k kernel_arch] [-l logfile%s\n\
+\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
+\t[-o op_sys_ver] [-O op_sys_name]\n\
+\t[-F conf_file] [-T conf_tag]", am_get_progname(),
+#ifdef HAVE_SYSLOG
+# ifdef LOG_DAEMON
+ "|\"syslog[:facility]\"]"
+# else /* not LOG_DAEMON */
+ "|\"syslog\"]"
+# endif /* not LOG_DAEMON */
+#else /* not HAVE_SYSLOG */
+ "]"
+#endif /* not HAVE_SYSLOG */
+ );
+
+#ifdef HAVE_MAP_NIS
+ fputs(" [-y nis-domain]\n", stderr);
+#else /* not HAVE_MAP_NIS */
+ fputc('\n', stderr);
+#endif /* HAVE_MAP_NIS */
+
+ show_opts('x', xlog_opt);
+#ifdef DEBUG
+ show_opts('D', dbg_opt);
+#endif /* DEBUG */
+ fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
+}
+
+
void
get_args(int argc, char *argv[])
{
- int opt_ch;
+ int opt_ch, i;
FILE *fp = stdin;
- char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:H";
+ char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
char *getopt_args;
+ int print_version = 0; /* 1 means we should print version info */
#ifdef HAVE_GNU_GETOPT
getopt_args = getopt_arguments;
@@ -188,24 +229,30 @@ get_args(int argc, char *argv[])
break;
case 't':
- /* timeo.retrans */
+ /* timeo.retrans (also affects toplvl mounts) */
{
char *dot = strchr(optarg, '.');
+ int i;
if (dot)
*dot = '\0';
if (*optarg) {
- gopt.amfs_auto_timeo = atoi(optarg);
+ for (i=0; i<AMU_TYPE_MAX; ++i)
+ gopt.amfs_auto_timeo[i] = atoi(optarg);
}
if (dot) {
- gopt.amfs_auto_retrans = atoi(dot + 1);
+ for (i=0; i<AMU_TYPE_MAX; ++i)
+ gopt.amfs_auto_retrans[i] = atoi(dot + 1);
*dot = '.';
}
}
break;
case 'v':
- fputs(get_version_string(), stderr);
- exit(0);
+ /*
+ * defer to print version info after every variable had been
+ * initialized.
+ */
+ print_version++;
break;
case 'w':
@@ -226,6 +273,10 @@ get_args(int argc, char *argv[])
#endif /* not HAVE_MAP_NIS */
break;
+ case 'A':
+ gopt.arch = optarg;
+ break;
+
case 'C':
gopt.cluster = optarg;
break;
@@ -240,12 +291,13 @@ get_args(int argc, char *argv[])
break;
case 'F':
- conf_file = optarg;
+ amu_conf_file = optarg;
use_conf_file = 1;
break;
case 'H':
- goto show_usage;
+ show_usage();
+ exit(1);
break;
case 'O':
@@ -270,18 +322,19 @@ get_args(int argc, char *argv[])
* specified, then use that amd.conf file. If the file cannot be opened,
* abort amd. If it can be found, open it, parse it, and then close it.
*/
- if (use_conf_file && conf_file) {
- fp = fopen(conf_file, "r");
+ if (use_conf_file && amu_conf_file) {
+ fp = fopen(amu_conf_file, "r");
if (!fp) {
char buf[128];
- sprintf(buf, "Amd configuration file (%s)", conf_file);
+ xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
+ amu_conf_file);
perror(buf);
exit(1);
}
yyin = fp;
yyparse();
fclose(fp);
- if (process_last_regular_map() != 0)
+ if (process_all_regular_maps() != 0)
exit(1);
}
@@ -294,8 +347,8 @@ get_args(int argc, char *argv[])
#endif /* DEBUG */
/* log information regarding amd.conf file */
- if (use_conf_file && conf_file)
- plog(XLOG_INFO, "using configuration file %s", conf_file);
+ if (use_conf_file && amu_conf_file)
+ plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
#ifdef HAVE_MAP_LDAP
/* ensure that if ldap_base is specified, that also ldap_hostports is */
@@ -305,8 +358,10 @@ get_args(int argc, char *argv[])
}
#endif /* HAVE_MAP_LDAP */
- if (usage)
- goto show_usage;
+ if (usage) {
+ show_usage();
+ exit(1);
+ }
while (optind <= argc - 2) {
char *dir = argv[optind++];
@@ -328,76 +383,55 @@ get_args(int argc, char *argv[])
hostdomain = gopt.sub_domain;
if (*hostdomain == '.')
hostdomain++;
- strcat(hostd, ".");
- strcat(hostd, hostdomain);
+ xstrlcat(hostd, ".", sizeof(hostd));
+ xstrlcat(hostd, hostdomain, sizeof(hostd));
#ifdef MOUNT_TABLE_ON_FILE
-# ifdef DEBUG
- if (debug_flags & D_MTAB)
- mnttab_file_name = DEBUG_MNTTAB;
+ if (amuDebug(D_MTAB))
+ if (gopt.debug_mtab_file)
+ mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
+ else
+ mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
else
-# endif /* DEBUG */
mnttab_file_name = MNTTAB_FILE_NAME;
#else /* not MOUNT_TABLE_ON_FILE */
-# ifdef DEBUG
- if (debug_flags & D_MTAB)
+ if (amuDebug(D_MTAB))
dlog("-D mtab option ignored");
-# endif /* DEBUG */
# ifdef MNTTAB_FILE_NAME
mnttab_file_name = MNTTAB_FILE_NAME;
# endif /* MNTTAB_FILE_NAME */
#endif /* not MOUNT_TABLE_ON_FILE */
- if (switch_to_logfile(gopt.logfile, orig_umask) != 0)
- plog(XLOG_USER, "Cannot switch logfile");
-
/*
* If the kernel architecture was not specified
* then use the machine architecture.
*/
- if (gopt.karch == 0)
+ if (gopt.karch == NULL)
gopt.karch = gopt.arch;
- if (gopt.cluster == 0)
+ if (gopt.cluster == NULL)
gopt.cluster = hostdomain;
- if (gopt.amfs_auto_timeo <= 0)
- gopt.amfs_auto_timeo = AMFS_AUTO_TIMEO;
- if (gopt.amfs_auto_retrans <= 0)
- gopt.amfs_auto_retrans = AMFS_AUTO_RETRANS;
- if (gopt.amfs_auto_retrans <= 0)
- gopt.amfs_auto_retrans = 3; /* XXX */
- return;
+ /* sanity checking, normalize values just in case (toplvl too) */
+ for (i=0; i<AMU_TYPE_MAX; ++i) {
+ if (gopt.amfs_auto_timeo[i] == 0)
+ gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
+ if (gopt.amfs_auto_retrans[i] == 0)
+ gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
+ if (gopt.amfs_auto_retrans[i] == 0)
+ gopt.amfs_auto_retrans[i] = 3; /* under very unusual circumstances, could be zero */
+ }
}
-show_usage:
- fprintf(stderr,
- "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
-\t[-k kernel_arch] [-l logfile%s\n\
-\t[-t timeout.retrans] [-w wait_timeout] [-C cluster_name]\n\
-\t[-o op_sys_ver] [-O op_sys_name]\n\
-\t[-F conf_file] [-T conf_tag]", am_get_progname(),
-#ifdef HAVE_SYSLOG
-# ifdef LOG_DAEMON
- "|\"syslog[:facility]\"]"
-# else /* not LOG_DAEMON */
- "|\"syslog\"]"
-# endif /* not LOG_DAEMON */
-#else /* not HAVE_SYSLOG */
- "]"
-#endif /* not HAVE_SYSLOG */
- );
+ /* finally print version string and exit, if asked for */
+ if (print_version) {
+ fputs(get_version_string(), stderr);
+ exit(0);
+ }
-#ifdef HAVE_MAP_NIS
- fputs(" [-y nis-domain]\n", stderr);
-#else /* not HAVE_MAP_NIS */
- fputc('\n', stderr);
-#endif /* HAVE_MAP_NIS */
+ if (switch_to_logfile(gopt.logfile, orig_umask,
+ (gopt.flags & CFM_TRUNCATE_LOG)) != 0)
+ plog(XLOG_USER, "Cannot switch logfile");
- show_opts('x', xlog_opt);
-#ifdef DEBUG
- show_opts('D', dbg_opt);
-#endif /* DEBUG */
- fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
- exit(1);
+ return;
}
diff --git a/contrib/amd/amd/nfs_prot_svc.c b/contrib/amd/amd/nfs_prot_svc.c
index 8d67d1bc14cb..0dd6992cf9e7 100644
--- a/contrib/amd/amd/nfs_prot_svc.c
+++ b/contrib/amd/amd/nfs_prot_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2004 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,10 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * %W% (Berkeley) %G%
*
- * $Id: nfs_prot_svc.c,v 1.5.2.6 2004/01/21 04:04:58 ib42 Exp $
- * $FreeBSD$
+ * File: am-utils/amd/nfs_prot_svc.c
*
*/
@@ -70,7 +68,7 @@ extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
/* global variables */
-SVCXPRT *nfs_program_2_transp;
+SVCXPRT *current_transp;
/* typedefs */
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
@@ -99,30 +97,60 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
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
+# ifdef MNT2_NFS_OPT_RESVPORT
/* Verify that the request comes from a reserved port */
- if ((ntohs(sinp->sin_port) >= IPPORT_RESERVED) &&
+ 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, sinp->sin_addr.s_addr),
+ inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
ntohs(sinp->sin_port));
return;
}
-#endif /* MNT2_NFS_OPT_RESVPORT */
+# endif /* MNT2_NFS_OPT_RESVPORT */
/* if the address does not match, ignore the request */
- if (sinp->sin_addr.s_addr && sinp->sin_addr.s_addr != myipaddr.s_addr) {
- plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
- inet_dquad(dq, sinp->sin_addr.s_addr),
- ntohs(sinp->sin_port),
- inet_dquad(dq2, myipaddr.s_addr));
- return;
+ 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 */
- nfs_program_2_transp = NULL;
+ current_transp = NULL;
switch (rqstp->rq_proc) {
@@ -159,7 +187,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
* be stored in the am_node structure and later used for
* quick_reply().
*/
- nfs_program_2_transp = transp;
+ current_transp = transp;
break;
case NFSPROC_READLINK:
@@ -257,7 +285,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
}
result = (*local) (&argument, rqstp);
- nfs_program_2_transp = NULL;
+ current_transp = NULL;
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
diff --git a/contrib/amd/amd/ops_pcfs.c b/contrib/amd/amd/ops_pcfs.c
index 5552c4302cd1..527dc926ca77 100644
--- a/contrib/amd/amd/ops_pcfs.c
+++ b/contrib/amd/amd/ops_pcfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2004 Erez Zadok
+ * 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.
@@ -36,10 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * %W% (Berkeley) %G%
*
- * $Id: ops_pcfs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
- * $FreeBSD$
+ * File: am-utils/amd/ops_pcfs.c
*
*/
@@ -55,8 +53,8 @@
/* forward definitions */
static char *pcfs_match(am_opts *fo);
-static int pcfs_fmount(mntfs *mf);
-static int pcfs_fumount(mntfs *mf);
+static int pcfs_mount(am_node *am, mntfs *mf);
+static int pcfs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@@ -66,17 +64,20 @@ am_ops pcfs_ops =
"pcfs",
pcfs_match,
0, /* pcfs_init */
- amfs_auto_fmount,
- pcfs_fmount,
- amfs_auto_fumount,
- pcfs_fumount,
- amfs_error_lookuppn,
+ pcfs_mount,
+ pcfs_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
amfs_error_readdir,
0, /* pcfs_readlink */
0, /* pcfs_mounted */
0, /* pcfs_umounted */
- find_amfs_auto_srvr,
- FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
+ amfs_generic_find_srvr,
+ 0, /* pcfs_get_wchan */
+ FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_PCFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
};
@@ -91,9 +92,7 @@ pcfs_match(am_opts *fo)
plog(XLOG_USER, "pcfs: no source device specified");
return 0;
}
-#ifdef DEBUG
dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -103,11 +102,17 @@ pcfs_match(am_opts *fo)
static int
-mount_pcfs(char *dir, char *fs_name, char *opts)
+mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
pcfs_args_t pcfs_args;
mntent_t mnt;
int flags;
+#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
+ int mask;
+#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
+#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
+ char *str;
+#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */
/*
* Figure out the name of the file system type.
@@ -120,12 +125,18 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
- mnt.mnt_dir = dir;
+ mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_PCFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+ if (on_autofs)
+ flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);
#ifdef HAVE_PCFS_ARGS_T_FSPEC
pcfs_args.fspec = fs_name;
@@ -133,18 +144,46 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
#ifdef HAVE_PCFS_ARGS_T_MASK
pcfs_args.mask = 0777; /* this may be the msdos file modes */
+ if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
+ pcfs_args.mask = mask;
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
#endif /* HAVE_PCFS_ARGS_T_MASK */
#ifdef HAVE_PCFS_ARGS_T_DIRMASK
- pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */
+ pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */
+ if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
+ pcfs_args.dirmask = mask;
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
#endif /* HAVE_PCFS_ARGS_T_DIRMASK */
#ifdef HAVE_PCFS_ARGS_T_UID
- pcfs_args.uid = 0; /* root */
+ pcfs_args.uid = 0; /* default to root */
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
+ struct passwd *pw;
+ if ((pw = getpwnam(str)) != NULL)
+ pcfs_args.uid = pw->pw_uid;
+ else /* maybe used passed a UID number, not user name */
+ pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
+ XFREE(str);
+ }
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
#endif /* HAVE_PCFS_ARGS_T_UID */
#ifdef HAVE_PCFS_ARGS_T_GID
- pcfs_args.gid = 0; /* wheel */
+ pcfs_args.gid = 0; /* default to wheel/root group */
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
+ struct group *gr;
+ if ((gr = getgrnam(str)) != NULL)
+ pcfs_args.gid = gr->gr_gid;
+ else /* maybe used passed a GID number, not group name */
+ pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
+ XFREE(str);
+ }
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
#endif /* HAVE_PCFS_ARGS_T_GID */
#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
@@ -157,16 +196,17 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
/*
* Call generic mount routine
*/
- return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name);
+ return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
-pcfs_fmount(mntfs *mf)
+pcfs_mount(am_node *am, mntfs *mf)
{
+ int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
- error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+ error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_pcfs: %m");
@@ -178,7 +218,9 @@ pcfs_fmount(mntfs *mf)
static int
-pcfs_fumount(mntfs *mf)
+pcfs_umount(am_node *am, mntfs *mf)
{
- return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+ int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+ return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}
diff --git a/contrib/amd/amd/srvr_nfs.c b/contrib/amd/amd/srvr_nfs.c
index 67d1724707fb..0c74a658e5ee 100644
--- a/contrib/amd/amd/srvr_nfs.c
+++ b/contrib/amd/amd/srvr_nfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2004 Erez Zadok
+ * 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.
@@ -36,10 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * %W% (Berkeley) %G%
*
- * $Id: srvr_nfs.c,v 1.7.2.11 2004/01/06 03:15:16 ezk Exp $
- * $FreeBSD$
+ * File: am-utils/amd/srvr_nfs.c
*
*/
@@ -73,8 +71,6 @@
*/
#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */
-#define NPXID_ALLOC(struct ) (++np_xid)
-
/* structures and typedefs */
typedef struct nfs_private {
u_short np_mountd; /* Mount daemon port number */
@@ -89,9 +85,16 @@ typedef struct nfs_private {
qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list};
/* statics */
-static int np_xid; /* For NFS pings */
-static int ping_len;
-static char ping_buf[sizeof(struct rpc_msg) + 32];
+static int global_xid; /* For NFS pings */
+#define XID_ALLOC() (++global_xid)
+
+#ifdef HAVE_FS_NFS3
+# define NUM_NFS_VERS 2
+#else /* not HAVE_FS_NFS3 */
+# define NUM_NFS_VERS 1
+#endif /* not HAVE_FS_NFS3 */
+static int ping_len[NUM_NFS_VERS];
+static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32];
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
/*
@@ -100,6 +103,8 @@ static char ping_buf[sizeof(struct rpc_msg) + 32];
* Note that Solaris 8 and newer NetBSD systems are switching to UDP first,
* so this order may have to be adjusted for Amd in the future once more
* vendors make that change. -Erez 11/24/2000
+ *
+ * Or we might simply make this is a platform-specific order. -Ion 09/13/2003
*/
static char *protocols[] = { "tcp", "udp", NULL };
#endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
@@ -108,20 +113,21 @@ static char *protocols[] = { "tcp", "udp", NULL };
static void nfs_keepalive(voidp);
-
/*
- * Flush any cached data
+ * Flush cached data for an fserver (or for all, if fs==NULL)
*/
void
-flush_srvr_nfs_cache(void)
+flush_srvr_nfs_cache(fserver *fs)
{
- fserver *fs = 0;
+ fserver *fs2 = NULL;
- ITER(fs, fserver, &nfs_srvr_list) {
- nfs_private *np = (nfs_private *) fs->fs_private;
- if (np) {
- np->np_mountd_inval = TRUE;
- np->np_error = -1;
+ ITER(fs2, fserver, &nfs_srvr_list) {
+ if (fs == NULL || fs == fs2) {
+ nfs_private *np = (nfs_private *) fs2->fs_private;
+ if (np) {
+ np->np_mountd_inval = TRUE;
+ np->np_error = -1;
+ }
}
}
}
@@ -131,7 +137,7 @@ flush_srvr_nfs_cache(void)
* Startup the NFS ping for a particular version.
*/
static void
-start_ping(u_long nfs_version)
+create_ping_payload(u_long nfs_version)
{
XDR ping_xdr;
struct rpc_msg ping_msg;
@@ -141,16 +147,16 @@ start_ping(u_long nfs_version)
*/
if (nfs_version == 0) {
nfs_version = NFS_VERSION;
- plog(XLOG_WARNING, "start_ping: nfs_version = 0 fixed");
- }
- plog(XLOG_INFO, "start_ping: nfs_version: %d", (int) nfs_version);
+ plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
+ } else
+ plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
/*
* Create an XDR endpoint
*/
- xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
+ xdrmem_create(&ping_xdr, ping_buf[nfs_version - NFS_VERSION], sizeof(ping_buf[0]), XDR_ENCODE);
/*
* Create the NFS ping message
@@ -162,7 +168,7 @@ start_ping(u_long nfs_version)
/*
* Find out how long it is
*/
- ping_len = xdr_getpos(&ping_xdr);
+ ping_len[nfs_version - NFS_VERSION] = xdr_getpos(&ping_xdr);
/*
* Destroy the XDR endpoint - we don't need it anymore
@@ -184,7 +190,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
* Find which fileserver we are talking about
*/
ITER(fs, fserver, &nfs_srvr_list)
- if (fs == fs2)
+ if (fs == fs2)
break;
if (fs == fs2) {
@@ -193,9 +199,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
nfs_private *np = (nfs_private *) fs->fs_private;
if (!error && port) {
-#ifdef DEBUG
dlog("got port (%d) for mountd on %s", (int) port, fs->fs_host);
-#endif /* DEBUG */
/*
* Grab the port number. Portmap sends back
* an u_long in native ordering, so it
@@ -206,10 +210,8 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
np->np_mountd_inval = FALSE;
np->np_error = 0;
} else {
-#ifdef DEBUG
dlog("Error fetching port for mountd on %s", fs->fs_host);
dlog("\t error=%d, port=%d", error, (int) port);
-#endif /* DEBUG */
/*
* Almost certainly no mountd running on remote host
*/
@@ -219,13 +221,9 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
if (fs->fs_flags & FSF_WANT)
wakeup_srvr(fs);
} else if (done) {
-#ifdef DEBUG
dlog("Got portmap for old port request");
-#endif /* DEBUG */
} else {
-#ifdef DEBUG
dlog("portmap request timed out");
-#endif /* DEBUG */
}
}
@@ -259,7 +257,7 @@ call_portmap(fserver *fs, AUTH *auth, u_long prog, u_long vers, u_long prot)
memset((voidp) &sin, 0, sizeof(sin));
sin = *fs->fs_ip;
sin.sin_port = htons(PMAPPORT);
- error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
+ error = fwd_packet(RPC_XID_PORTMAP, iobuf, len,
&sin, &sin, (voidp) fs, got_portmap);
} else {
error = -len;
@@ -275,6 +273,12 @@ recompute_portmap(fserver *fs)
int error;
u_long mnt_version;
+ /*
+ * No portmap calls for pure WebNFS servers.
+ */
+ if (fs->fs_flags & FSF_WEBNFS)
+ return;
+
if (nfs_auth)
error = 0;
else
@@ -289,10 +293,11 @@ recompute_portmap(fserver *fs)
if (fs->fs_version == 0)
plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
- plog(XLOG_INFO, "recompute_portmap: NFS version %d", (int) fs->fs_version);
+ plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
+ (int) fs->fs_version, fs->fs_host);
#ifdef HAVE_FS_NFS3
if (fs->fs_version == NFS_VERSION3)
- mnt_version = MOUNTVERS3;
+ mnt_version = AM_MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@@ -302,19 +307,61 @@ recompute_portmap(fserver *fs)
}
+int
+get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
+{
+ int error = -1;
+ if (FSRV_ISDOWN(fs))
+ return EWOULDBLOCK;
+
+ if (FSRV_ISUP(fs)) {
+ nfs_private *np = (nfs_private *) fs->fs_private;
+ if (np->np_error == 0) {
+ *port = np->np_mountd;
+ error = 0;
+ } else {
+ error = np->np_error;
+ }
+ /*
+ * Now go get the port mapping again in case it changed.
+ * Note that it is used even if (np_mountd_inval)
+ * is True. The flag is used simply as an
+ * indication that the mountd may be invalid, not
+ * that it is known to be invalid.
+ */
+ if (np->np_mountd_inval)
+ recompute_portmap(fs);
+ else
+ np->np_mountd_inval = TRUE;
+ }
+ if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
+ /*
+ * If a wait channel is supplied, and no
+ * error has yet occurred, then arrange
+ * that a wakeup is done on the wait channel,
+ * whenever a wakeup is done on this fs node.
+ * Wakeup's are done on the fs node whenever
+ * it changes state - thus causing control to
+ * come back here and new, better things to happen.
+ */
+ fs->fs_flags |= FSF_WANT;
+ sched_task(wakeup_task, wchan, (wchan_t) fs);
+ }
+ return error;
+}
+
+
/*
* This is called when we get a reply to an RPC ping.
* The value of id was taken from the nfs_private
* structure when the ping was transmitted.
*/
static void
-nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
+nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
{
- int xid = (long) idv; /* for 64-bit archs */
+ int xid = (long) idv; /* cast needed for 64-bit archs */
fserver *fs;
-#ifdef DEBUG
int found_map = 0;
-#endif /* DEBUG */
if (!done)
return;
@@ -337,19 +384,15 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
} else {
if (np->np_ping > 1)
srvrlog(fs, "ok");
-#ifdef DEBUG
else
srvrlog(fs, "starts up");
-#endif /* DEBUG */
fs->fs_flags |= FSF_VALID;
}
map_flush_srvr(fs);
} else {
if (fs->fs_flags & FSF_VALID) {
-#ifdef DEBUG
dlog("file server %s type nfs is still up", fs->fs_host);
-#endif /* DEBUG */
} else {
if (np->np_ping > 1)
srvrlog(fs, "ok");
@@ -366,13 +409,13 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
/*
* Update ttl for this server
*/
- np->np_ttl = clocktime() +
+ np->np_ttl = clocktime(NULL) +
(MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
/*
* New RPC xid...
*/
- np->np_xid = NPXID_ALLOC(struct );
+ np->np_xid = XID_ALLOC();
/*
* Failed pings is zero...
@@ -385,17 +428,53 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
if (np->np_mountd_inval)
recompute_portmap(fs);
-#ifdef DEBUG
found_map++;
-#endif /* DEBUG */
break;
}
}
-#ifdef DEBUG
if (found_map == 0)
dlog("Spurious ping packet");
-#endif /* DEBUG */
+}
+
+
+static void
+check_fs_addr_change(fserver *fs)
+{
+ struct hostent *hp = NULL;
+ struct in_addr ia;
+ char *old_ipaddr, *new_ipaddr;
+
+ hp = gethostbyname(fs->fs_host);
+ if (!hp ||
+ hp->h_addrtype != AF_INET ||
+ !STREQ((char *) hp->h_name, fs->fs_host) ||
+ memcmp((voidp) &fs->fs_ip->sin_addr,
+ (voidp) hp->h_addr,
+ sizeof(fs->fs_ip->sin_addr)) == 0)
+ return;
+ /* if got here: downed server changed IP address */
+ old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
+ memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
+ new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
+ plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s",
+ fs->fs_host, old_ipaddr, new_ipaddr);
+ XFREE(old_ipaddr);
+ /* copy new IP addr */
+ memmove((voidp) &fs->fs_ip->sin_addr,
+ (voidp) hp->h_addr,
+ sizeof(fs->fs_ip->sin_addr));
+ /* XXX: do we need to un/set these flags? */
+ fs->fs_flags &= ~FSF_DOWN;
+ fs->fs_flags |= FSF_VALID | FSF_WANT;
+ map_flush_srvr(fs); /* XXX: a race with flush_srvr_nfs_cache? */
+ flush_srvr_nfs_cache(fs);
+ fs->fs_flags |= FSF_FORCE_UNMOUNT;
+
+#if 0
+ flush_nfs_fhandle_cache(fs); /* done in caller: nfs_keepalive_timeout */
+ /* XXX: need to purge nfs_private so that somehow it will get re-initialized? */
+#endif
}
@@ -403,7 +482,7 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
* Called when no ping-reply received
*/
static void
-nfs_timed_out(voidp v)
+nfs_keepalive_timeout(voidp v)
{
fserver *fs = v;
nfs_private *np = (nfs_private *) fs->fs_private;
@@ -424,11 +503,9 @@ nfs_timed_out(voidp v)
/*
* If ttl has expired then guess that it is dead
*/
- if (np->np_ttl < clocktime()) {
+ if (np->np_ttl < clocktime(NULL)) {
int oflags = fs->fs_flags;
-#ifdef DEBUG
dlog("ttl has expired");
-#endif /* DEBUG */
if ((fs->fs_flags & FSF_DOWN) == 0) {
/*
* Server was up, but is now down.
@@ -442,14 +519,13 @@ nfs_timed_out(voidp v)
*/
flush_nfs_fhandle_cache(fs);
np->np_error = -1;
+ check_fs_addr_change(fs); /* check if IP addr of fserver changed */
} else {
/*
* Known to be down
*/
-#ifdef DEBUG
if ((fs->fs_flags & FSF_VALID) == 0)
srvrlog(fs, "starts down");
-#endif /* DEBUG */
fs->fs_flags |= FSF_VALID;
}
if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT))
@@ -459,17 +535,15 @@ nfs_timed_out(voidp v)
*/
np->np_ping = 0;
} else {
-#ifdef DEBUG
if (np->np_ping > 1)
dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
-#endif /* DEBUG */
}
/*
* New RPC xid, so any late responses to the previous ping
* get ignored...
*/
- np->np_xid = NPXID_ALLOC(struct );
+ np->np_xid = XID_ALLOC();
/*
* Run keepalive again
@@ -493,19 +567,19 @@ nfs_keepalive(voidp v)
* Send an NFS ping to this node
*/
- if (ping_len == 0)
- start_ping(fs->fs_version);
+ if (ping_len[fs->fs_version - NFS_VERSION] == 0)
+ create_ping_payload(fs->fs_version);
/*
* Queue the packet...
*/
error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
- (voidp) ping_buf,
- ping_len,
+ ping_buf[fs->fs_version - NFS_VERSION],
+ ping_len[fs->fs_version - NFS_VERSION],
fs->fs_ip,
(struct sockaddr_in *) 0,
- (voidp) ((long) np->np_xid), /* for 64-bit archs */
- nfs_pinged);
+ (voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
+ nfs_keepalive_callback);
/*
* See if a hard error occurred
@@ -518,7 +592,7 @@ nfs_keepalive(voidp v)
np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
np->np_ttl = (time_t) 0;
/*
- * This causes an immediate call to nfs_timed_out
+ * This causes an immediate call to nfs_keepalive_timeout
* whenever the server was thought to be up.
* See +++ below.
*/
@@ -526,15 +600,13 @@ nfs_keepalive(voidp v)
break;
case 0:
-#ifdef DEBUG
dlog("Sent NFS ping to %s", fs->fs_host);
-#endif /* DEBUG */
break;
}
/*
* Back off the ping interval if we are not getting replies and
- * the remote system is know to be down.
+ * the remote system is known to be down.
*/
switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) {
case FSF_VALID: /* Up */
@@ -551,73 +623,41 @@ nfs_keepalive(voidp v)
break;
}
-#ifdef DEBUG
dlog("NFS timeout in %d seconds", fstimeo);
-#endif /* DEBUG */
- fs->fs_cid = timeout(fstimeo, nfs_timed_out, (voidp) fs);
-}
-
-
-int
-nfs_srvr_port(fserver *fs, u_short *port, voidp wchan)
-{
- int error = -1;
- if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
- if ((fs->fs_flags & FSF_DOWN) == 0) {
- nfs_private *np = (nfs_private *) fs->fs_private;
- if (np->np_error == 0) {
- *port = np->np_mountd;
- error = 0;
- } else {
- error = np->np_error;
- }
- /*
- * Now go get the port mapping again in case it changed.
- * Note that it is used even if (np_mountd_inval)
- * is True. The flag is used simply as an
- * indication that the mountd may be invalid, not
- * that it is known to be invalid.
- */
- if (np->np_mountd_inval)
- recompute_portmap(fs);
- else
- np->np_mountd_inval = TRUE;
- } else {
- error = EWOULDBLOCK;
- }
- }
- if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
- /*
- * If a wait channel is supplied, and no
- * error has yet occurred, then arrange
- * that a wakeup is done on the wait channel,
- * whenever a wakeup is done on this fs node.
- * Wakeup's are done on the fs node whenever
- * it changes state - thus causing control to
- * come back here and new, better things to happen.
- */
- fs->fs_flags |= FSF_WANT;
- sched_task(wakeup_task, wchan, (voidp) fs);
- }
- return error;
+ fs->fs_cid = timeout(fstimeo, nfs_keepalive_timeout, (voidp) fs);
}
static void
start_nfs_pings(fserver *fs, int pingval)
{
- if (fs->fs_flags & FSF_PINGING) {
-#ifdef DEBUG
- dlog("Already running pings to %s", fs->fs_host);
-#endif /* DEBUG */
+ if (pingval == 0) /* could be because ping mnt option not found */
+ pingval = AM_PINGER;
+ /* if pings haven't been initalized, then init them for first time */
+ if (fs->fs_flags & FSF_PING_UNINIT) {
+ fs->fs_flags &= ~FSF_PING_UNINIT;
+ plog(XLOG_INFO, "initializing %s's pinger to %d sec", fs->fs_host, pingval);
+ goto do_pings;
+ }
+
+ if ((fs->fs_flags & FSF_PINGING) && fs->fs_pinger == pingval) {
+ dlog("already running pings to %s", fs->fs_host);
return;
}
+ /* if got here, then we need to update the ping value */
+ plog(XLOG_INFO, "changing %s's ping value from %d%s to %d%s",
+ fs->fs_host,
+ fs->fs_pinger, (fs->fs_pinger < 0 ? " (off)" : ""),
+ pingval, (pingval < 0 ? " (off)" : ""));
+ do_pings:
+ fs->fs_pinger = pingval;
+
if (fs->fs_cid)
untimeout(fs->fs_cid);
if (pingval < 0) {
- srvrlog(fs, "wired up");
+ srvrlog(fs, "wired up (pings disabled)");
fs->fs_flags |= FSF_VALID;
fs->fs_flags &= ~FSF_DOWN;
} else {
@@ -634,17 +674,18 @@ fserver *
find_nfs_srvr(mntfs *mf)
{
char *host = mf->mf_fo->opt_rhost;
- char *nfs_proto = NULL;
fserver *fs;
int pingval;
mntent_t mnt;
nfs_private *np;
- struct hostent *hp = 0;
- struct sockaddr_in *ip;
+ struct hostent *hp = NULL;
+ struct sockaddr_in *ip = NULL;
u_long nfs_version = 0; /* default is no version specified */
-#ifdef MNTTAB_OPT_PROTO
- char *rfsname = mf->mf_fo->opt_rfs;
-#endif /* MNTTAB_OPT_PROTO */
+ u_long best_nfs_version = 0;
+ char *nfs_proto = NULL; /* no IP protocol either */
+ int nfs_port = 0;
+ int nfs_port_opt = 0;
+ int fserver_is_down = 0;
/*
* Get ping interval from mount options.
@@ -654,49 +695,60 @@ find_nfs_srvr(mntfs *mf)
mnt.mnt_opts = mf->mf_mopts;
pingval = hasmntval(&mnt, "ping");
- /*
- * Get the NFS version from the mount options. This is used
- * to decide the highest NFS version to try.
- */
+ if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
+ /*
+ * the server granted us a filehandle, but we were unable to mount it.
+ * therefore, scale down to NFSv2/UDP and try again.
+ */
+ nfs_version = NFS_VERSION;
+ nfs_proto = "udp";
+ plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
+ mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
+ } else {
+ /*
+ * Get the NFS version from the mount options. This is used
+ * to decide the highest NFS version to try.
+ */
#ifdef MNTTAB_OPT_VERS
- nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
+ nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
#endif /* MNTTAB_OPT_VERS */
#ifdef MNTTAB_OPT_PROTO
- {
- char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
- if (proto_opt) {
- char **p;
- for (p = protocols; *p; p ++)
- if (NSTREQ(proto_opt, *p, strlen(*p))) {
- nfs_proto = *p;
- break;
- }
- if (*p == NULL)
- plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
- host, rfsname);
+ {
+ char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
+ if (proto_opt) {
+ char **p;
+ for (p = protocols; *p; p++)
+ if (NSTREQ(proto_opt, *p, strlen(*p))) {
+ nfs_proto = *p;
+ break;
+ }
+ if (*p == NULL)
+ plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
+ host, mf->mf_fo->opt_rfs);
+ }
}
- }
#endif /* MNTTAB_OPT_PROTO */
#ifdef HAVE_NFS_NFSV2_H
- /* allow overriding if nfsv2 option is specified in mount options */
- if (hasmntopt(&mnt, "nfsv2")) {
- nfs_version = (u_long) 2; /* nullify any ``vers=X'' statements */
- nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
- plog(XLOG_WARNING, "found compatiblity option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
- }
+ /* allow overriding if nfsv2 option is specified in mount options */
+ if (amu_hasmntopt(&mnt, "nfsv2")) {
+ nfs_version = NFS_VERSION;/* nullify any ``vers=X'' statements */
+ nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
+ plog(XLOG_WARNING, "found compatibility option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
+ }
#endif /* HAVE_NFS_NFSV2_H */
- /* check if we globally overridden the NFS version/protocol */
- if (gopt.nfs_vers) {
- nfs_version = gopt.nfs_vers;
- plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
- (int) nfs_version);
- }
- if (gopt.nfs_proto) {
- nfs_proto = gopt.nfs_proto;
- plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
+ /* check if we've globally overridden the NFS version/protocol */
+ if (gopt.nfs_vers) {
+ nfs_version = gopt.nfs_vers;
+ plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
+ (int) nfs_version);
+ }
+ if (gopt.nfs_proto) {
+ nfs_proto = gopt.nfs_proto;
+ plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
+ }
}
/*
@@ -719,72 +771,148 @@ find_nfs_srvr(mntfs *mf)
case AF_INET:
ip = ALLOC(struct sockaddr_in);
memset((voidp) ip, 0, sizeof(*ip));
+ /* as per POSIX, sin_len need not be set (used internally by kernel) */
ip->sin_family = AF_INET;
memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
-
- ip->sin_port = htons(NFS_PORT);
break;
default:
- ip = 0;
- break;
+ plog(XLOG_USER, "No IP address for host %s", host);
+ goto no_dns;
}
} else {
plog(XLOG_USER, "Unknown host: %s", host);
- ip = 0;
+ goto no_dns;
}
/*
- * Get the NFS Version, and verify server is up. Probably no
- * longer need to start server down below.
+ * This may not be the best way to do things, but it really doesn't make
+ * sense to query a file server which is marked as 'down' for any
+ * version/proto combination.
*/
- if (ip) {
+ ITER(fs, fserver, &nfs_srvr_list) {
+ if (FSRV_ISDOWN(fs) &&
+ STREQ(host, fs->fs_host)) {
+ plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host);
+ fs->fs_refc++;
+ if (ip)
+ XFREE(ip);
+ return fs;
+ }
+ }
+
+ /*
+ * Get the NFS Version, and verify server is up.
+ * If the client only supports NFSv2, hardcode it but still try to
+ * contact the remote portmapper to see if the service is running.
+ */
+#ifndef HAVE_FS_NFS3
+ nfs_version = NFS_VERSION;
+ nfs_proto = "udp";
+ plog(XLOG_INFO, "The client supports only NFS(2,udp)");
+#endif /* not HAVE_FS_NFS3 */
+
+
+ if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) {
+ /*
+ * Use WebNFS to obtain file handles.
+ */
+ mf->mf_flags |= MFF_WEBNFS;
+ plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s",
+ MNTTAB_OPT_PUBLIC, host);
+ /*
+ * Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7).
+ */
+ if (!nfs_version) {
#ifdef HAVE_FS_NFS3
+ nfs_version = NFS_VERSION3;
+#else /* not HAVE_FS_NFS3 */
+ nfs_version = NFS_VERSION;
+#endif /* not HAVE_FS_NFS3 */
+ plog(XLOG_INFO, "No NFS version specified, will use NFSv%d",
+ (int) nfs_version);
+ }
+ if (!nfs_proto) {
+#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
+ nfs_proto = "tcp";
+#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+ nfs_proto = "udp";
+#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+ plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
+ nfs_proto);
+ }
+ } else {
/*
* Find the best combination of NFS version and protocol.
* When given a choice, use the highest available version,
* and use TCP over UDP if available.
*/
- if (nfs_proto)
- nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
- else {
- int best_nfs_version = 0;
- int proto_nfs_version;
- char **p;
-
- for (p = protocols; *p; p++) {
- proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
-
- if (proto_nfs_version > best_nfs_version) {
- best_nfs_version = proto_nfs_version;
- nfs_proto = *p;
+ if (check_pmap_up(host, ip)) {
+ if (nfs_proto) {
+ best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
+ nfs_port = ip->sin_port;
+ }
+#ifdef MNTTAB_OPT_PROTO
+ else {
+ u_int proto_nfs_version;
+ char **p;
+
+ for (p = protocols; *p; p++) {
+ proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
+
+ if (proto_nfs_version > best_nfs_version) {
+ best_nfs_version = proto_nfs_version;
+ nfs_proto = *p;
+ nfs_port = ip->sin_port;
+ }
}
}
- nfs_version = best_nfs_version;
+#endif /* MNTTAB_OPT_PROTO */
+ } else {
+ plog(XLOG_INFO, "portmapper service not running on %s", host);
}
- if (!nfs_version) {
+ /* use the portmapper results only nfs_version is not set yet */
+ if (!best_nfs_version) {
/*
* If the NFS server is down or does not support the portmapper call
* (such as certain Novell NFS servers) we mark it as version 2 and we
- * let the nfs code deal with the case that is down. If when the
- * server comes back up, it can support NFS V.3 and/or TCP, it will
+ * let the nfs code deal with the case when it is down. If/when the
+ * server comes back up and it can support NFSv3 and/or TCP, it will
* use those.
*/
- nfs_version = NFS_VERSION;
- nfs_proto = "udp";
+ if (nfs_version == 0) {
+ nfs_version = NFS_VERSION;
+ nfs_proto = "udp";
+ }
+ plog(XLOG_INFO, "NFS service not running on %s", host);
+ fserver_is_down = 1;
+ } else {
+ if (nfs_version == 0)
+ nfs_version = best_nfs_version;
+ plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
+ (int) nfs_version, nfs_proto, host);
}
-#else /* not HAVE_FS_NFS3 */
- nfs_version = NFS_VERSION;
-#endif /* not HAVE_FS_NFS3 */
}
- if (!nfs_proto)
- nfs_proto = "udp";
+ /*
+ * Determine the NFS port.
+ *
+ * A valid "port" mount option overrides anything else.
+ * If the port has been determined from the portmapper, use that.
+ * Default to NFS_PORT otherwise (cf. RFC 2054, 3).
+ */
+ nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT);
+ if (nfs_port_opt > 0)
+ nfs_port = htons(nfs_port_opt);
+ if (!nfs_port)
+ nfs_port = htons(NFS_PORT);
- plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
- (int) nfs_version, nfs_proto, host);
+ dlog("find_nfs_srvr: using port %d for nfs on %s",
+ (int) ntohs(nfs_port), host);
+ ip->sin_port = nfs_port;
+no_dns:
/*
* Try to find an existing fs server structure for this host.
* Note that differing versions or protocols have their own structures.
@@ -796,16 +924,46 @@ find_nfs_srvr(mntfs *mf)
nfs_version == fs->fs_version &&
STREQ(nfs_proto, fs->fs_proto)) {
/*
- * following if statement from Mike Mitchell
- * <mcm@unx.sas.com>
- * Initialize the ping data if we aren't pinging
- * now. The np_ttl and np_ping fields are
- * especially important.
+ * fill in the IP address -- this is only needed
+ * if there is a chance an IP address will change
+ * between mounts.
+ * Mike Mitchell, mcm@unx.sas.com, 09/08/93
+ */
+ if (hp && fs->fs_ip &&
+ memcmp((voidp) &fs->fs_ip->sin_addr,
+ (voidp) hp->h_addr,
+ sizeof(fs->fs_ip->sin_addr)) != 0) {
+ struct in_addr ia;
+ char *old_ipaddr, *new_ipaddr;
+ old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
+ memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
+ new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
+ plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s",
+ fs->fs_host, old_ipaddr, new_ipaddr);
+ XFREE(old_ipaddr);
+ flush_nfs_fhandle_cache(fs);
+ memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
+ }
+
+ /*
+ * If the new file systems doesn't use WebNFS, the nfs pings may
+ * try to contact the portmapper.
+ */
+ if (!(mf->mf_flags & MFF_WEBNFS))
+ fs->fs_flags &= ~FSF_WEBNFS;
+
+ /* check if pingval needs to be updated/set/reset */
+ start_nfs_pings(fs, pingval);
+
+ /*
+ * Following if statement from Mike Mitchell <mcm@unx.sas.com>
+ * Initialize the ping data if we aren't pinging now. The np_ttl and
+ * np_ping fields are especially important.
*/
if (!(fs->fs_flags & FSF_PINGING)) {
np = (nfs_private *) fs->fs_private;
np->np_mountd_inval = TRUE;
- np->np_xid = NPXID_ALLOC(struct );
+ np->np_xid = XID_ALLOC();
np->np_error = -1;
np->np_ping = 0;
/*
@@ -813,18 +971,12 @@ find_nfs_srvr(mntfs *mf)
* after MAX_ALLOWED_PINGS of the fast variety
* have failed.
*/
- np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1;
+ np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1;
+ start_nfs_pings(fs, pingval);
+ if (fserver_is_down)
+ fs->fs_flags |= FSF_VALID | FSF_DOWN;
}
- /*
- * fill in the IP address -- this is only needed
- * if there is a chance an IP address will change
- * between mounts.
- * Mike Mitchell, mcm@unx.sas.com, 09/08/93
- */
- if (hp && fs->fs_ip)
- memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
- start_nfs_pings(fs, pingval);
fs->fs_refc++;
if (ip)
XFREE(ip);
@@ -853,29 +1005,32 @@ find_nfs_srvr(mntfs *mf)
mf->mf_flags |= MFF_ERROR;
mf->mf_error = ENOENT;
}
+ if (mf->mf_flags & MFF_WEBNFS)
+ fs->fs_flags |= FSF_WEBNFS;
fs->fs_version = nfs_version;
fs->fs_proto = nfs_proto;
fs->fs_type = MNTTAB_TYPE_NFS;
fs->fs_pinger = AM_PINGER;
+ fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */
np = ALLOC(struct nfs_private);
memset((voidp) np, 0, sizeof(*np));
np->np_mountd_inval = TRUE;
- np->np_xid = NPXID_ALLOC(struct );
+ np->np_xid = XID_ALLOC();
np->np_error = -1;
/*
* Initially the server will be deemed dead after
* MAX_ALLOWED_PINGS of the fast variety have failed.
*/
- np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
+ np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
fs->fs_private = (voidp) np;
fs->fs_prfree = (void (*)(voidp)) free;
- if (!(fs->fs_flags & FSF_ERROR)) {
- /*
- * Start of keepalive timer
- */
+ if (!FSRV_ERROR(fs)) {
+ /* start of keepalive timer, first updating pingval */
start_nfs_pings(fs, pingval);
+ if (fserver_is_down)
+ fs->fs_flags |= FSF_VALID | FSF_DOWN;
}
/*