diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2007-12-05 16:57:05 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2007-12-05 16:57:05 +0000 |
commit | aa1670f3e4eb7d6c1cc2d154c0c1b23e00259e32 (patch) | |
tree | e7b85ce620ca0374e09e7d585e7a5276830543ab /contrib/amd/amd | |
parent | 1e2f6b2e5fbfd49bab3ea57cbebfeac155ac573d (diff) | |
download | src-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.c | 124 | ||||
-rw-r--r-- | contrib/amd/amd/get_args.c | 250 | ||||
-rw-r--r-- | contrib/amd/amd/nfs_prot_svc.c | 66 | ||||
-rw-r--r-- | contrib/amd/amd/ops_pcfs.c | 92 | ||||
-rw-r--r-- | contrib/amd/amd/srvr_nfs.c | 589 |
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; } /* |