aboutsummaryrefslogtreecommitdiffstats
path: root/libamu/mount_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libamu/mount_fs.c')
-rw-r--r--libamu/mount_fs.c1097
1 files changed, 795 insertions, 302 deletions
diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c
index 74f064ede648..b5576bdc6d14 100644
--- a/libamu/mount_fs.c
+++ b/libamu/mount_fs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgment:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -46,6 +42,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
+#include <nfs_common.h>
/* ensure that mount table options are delimited by a comma */
@@ -105,6 +102,30 @@ struct opt_tab mnt_flags[] =
{MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
#endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
+#if defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG)
+ {MNTTAB_OPT_LOG, MNT2_GEN_OPT_LOG},
+#endif /* defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) */
+
+#if defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME)
+ {MNTTAB_OPT_NOATIME, MNT2_GEN_OPT_NOATIME},
+#endif /* defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) */
+
+#if defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME)
+ {MNTTAB_OPT_NODEVMTIME, MNT2_GEN_OPT_NODEVMTIME},
+#endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) */
+
+#if defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP)
+ {MNTTAB_OPT_SOFTDEP, MNT2_GEN_OPT_SOFTDEP},
+#endif /* defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) */
+
+#if defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM)
+ {MNTTAB_OPT_SYMPERM, MNT2_GEN_OPT_SYMPERM},
+#endif /* defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) */
+
+#if defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION)
+ {MNTTAB_OPT_UNION, MNT2_GEN_OPT_UNION},
+#endif /* defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) */
+
/*
* Do not define MNT2_NFS_OPT_* entries here! This is for generic
* mount(2) options only, not for NFS mount options. If you need to put
@@ -158,6 +179,25 @@ compute_automounter_mount_flags(mntent_t *mntp)
}
+#if defined(MOUNT_TABLE_ON_FILE) && defined(MNTTAB_OPT_VERS)
+/*
+ * add the extra vers={2,3} field to the mount table,
+ * unless already specified by user
+ */
+static void
+addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers,
+ u_long want_vers)
+{
+ if (have_vers == want_vers &&
+ hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) {
+ char optsbuf[48];
+ xsnprintf(optsbuf, sizeof(optsbuf),
+ "%s=%d", MNTTAB_OPT_VERS, want_vers);
+ append_opts(zopts, l, optsbuf);
+ }
+}
+#endif /* MOUNT_TABLE_ON_FILE && MNTTAB_OPT_VERS */
+
int
mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs)
{
@@ -166,17 +206,17 @@ mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type,
char *zopts = NULL, *xopts = NULL;
size_t l;
#endif /* MOUNT_TABLE_ON_FILE */
- char *mnt_dir = 0;
+ char *mnt_dir = NULL;
#ifdef NEED_AUTOFS_SPACE_HACK
- char *old_mnt_dir = 0;
+ char *old_mnt_dir = NULL;
/* perform space hack */
if (on_autofs) {
old_mnt_dir = mnt->mnt_dir;
mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
} else
#endif /* NEED_AUTOFS_SPACE_HACK */
- mnt_dir = strdup(mnt->mnt_dir);
+ mnt_dir = xstrdup(mnt->mnt_dir);
dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
@@ -256,19 +296,15 @@ again:
}
# endif /* MNTTAB_OPT_DEV */
+# if defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS)
+ addvers(zopts, l, mnt, nfs_version, NFS_VERSION4);
+# endif /* defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) */
# if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
- /*
- * add the extra vers={2,3} field to the mount table,
- * unless already specified by user
- */
- if (nfs_version == NFS_VERSION3 &&
- hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
- char optsbuf[48];
- xsnprintf(optsbuf, sizeof(optsbuf),
- "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
- append_opts(zopts, l, optsbuf);
- }
+ addvers(zopts, l, mnt, nfs_version, NFS_VERSION3);
# endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
+# ifdef MNTTAB_OPT_VERS
+ addvers(zopts, l, mnt, nfs_version, NFS_VERSION2);
+# endif /* MNTTAB_OPT_VERS */
# ifdef MNTTAB_OPT_PROTO
/*
@@ -333,7 +369,7 @@ again:
* with caution.
*/
static void
-compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
+compute_nfs_attrcache_flags(struct nfs_common_args *nap, mntent_t *mntp)
{
int acval = 0;
int err_acval = 1; /* 1 means we found no 'actimeo' value */
@@ -365,7 +401,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
nap->acregmin = acval; /* min ac timeout for reg files (sec) */
} else {
# ifdef MNTTAB_OPT_ACREGMIN
- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, (int *) &nap->acregmin);
+ int tmp;
+ err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp);
+ nap->acregmin = tmp;
# else /* not MNTTAB_OPT_ACREGMIN */
nap->acregmin = 0;
# endif /* not MNTTAB_OPT_ACREGMIN */
@@ -384,7 +422,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
nap->acregmax = acval; /* max ac timeout for reg files (sec) */
} else {
# ifdef MNTTAB_OPT_ACREGMAX
- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, (int *) &nap->acregmax);
+ int tmp;
+ err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp);
+ nap->acregmax = tmp;
# else /* not MNTTAB_OPT_ACREGMAX */
nap->acregmax = 0;
# endif /* not MNTTAB_OPT_ACREGMAX */
@@ -403,7 +443,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
} else {
# ifdef MNTTAB_OPT_ACDIRMIN
- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, (int *) &nap->acdirmin);
+ int tmp;
+ err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp);
+ nap->acdirmin = tmp;
# else /* not MNTTAB_OPT_ACDIRMIN */
nap->acdirmin = 0;
# endif /* not MNTTAB_OPT_ACDIRMIN */
@@ -422,7 +464,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
} else {
# ifdef MNTTAB_OPT_ACDIRMAX
- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, (int *) &nap->acdirmax);
+ int tmp;
+ err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp);
+ nap->acdirmax = tmp;
# else /* not MNTTAB_OPT_ACDIRMAX */
nap->acdirmax = 0;
# endif /* not MNTTAB_OPT_ACDIRMAX */
@@ -443,148 +487,16 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
}
-/*
- * Fill in the many possible fields and flags of struct nfs_args.
- *
- * nap: pre-allocated structure to fill in.
- * mntp: mount entry structure (includes options)
- * genflags: generic mount flags already determined
- * nfsncp: (TLI only) netconfig entry for this NFS mount
- * ip_addr: IP address of file server
- * nfs_version: 2, 3, (4 in the future), or 0 if unknown
- * nfs_proto: "udp", "tcp", or NULL.
- * fhp: file handle structure pointer
- * host_name: name of remote NFS host
- * fs_name: remote file system name to mount
- */
-void
-compute_nfs_args(nfs_args_t *nap,
- mntent_t *mntp,
- int genflags,
- struct netconfig *nfsncp,
- struct sockaddr_in *ip_addr,
- u_long nfs_version,
- char *nfs_proto,
- am_nfs_handle_t *fhp,
- char *host_name,
- char *fs_name)
-{
- /* initialize just in case */
- memset((voidp) nap, 0, sizeof(nfs_args_t));
-
- /* compute all of the NFS attribute-cache flags */
- compute_nfs_attrcache_flags(nap, mntp);
-
- /************************************************************************/
- /*** FILEHANDLE DATA AND LENGTH ***/
- /************************************************************************/
-#ifdef HAVE_FS_NFS3
- if (nfs_version == NFS_VERSION3) {
-# if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
- /*
- * Some systems (Irix/bsdi3) have a separate field in nfs_args for
- * the length of the file handle for NFS V3. They insist that
- * the file handle set in nfs_args be plain bytes, and not
- * include the length field.
- */
- NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
-# else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
- NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
-# endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
-# ifdef MNT2_NFS_OPT_NFSV3
- nap->flags |= MNT2_NFS_OPT_NFSV3;
-# endif /* MNT2_NFS_OPT_NFSV3 */
-# ifdef MNT2_NFS_OPT_VER3
- nap->flags |= MNT2_NFS_OPT_VER3;
-# endif /* MNT2_NFS_OPT_VER3 */
- } else
-#endif /* HAVE_FS_NFS3 */
- NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
-
-#ifdef HAVE_NFS_ARGS_T_FHSIZE
-# ifdef HAVE_FS_NFS3
- if (nfs_version == NFS_VERSION3)
- nap->fhsize = fhp->v3.am_fh3_length;
- else
-# endif /* HAVE_FS_NFS3 */
- nap->fhsize = FHSIZE;
-#endif /* HAVE_NFS_ARGS_T_FHSIZE */
-
- /* this is the version of the nfs_args structure, not of NFS! */
-#ifdef HAVE_NFS_ARGS_T_FH_LEN
-# ifdef HAVE_FS_NFS3
- if (nfs_version == NFS_VERSION3)
- nap->fh_len = fhp->v3.am_fh3_length;
- else
-# endif /* HAVE_FS_NFS3 */
- nap->fh_len = FHSIZE;
-#endif /* HAVE_NFS_ARGS_T_FH_LEN */
- /************************************************************************/
- /*** HOST NAME ***/
- /************************************************************************/
- /*
- * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
- * struct nfs_args, or truncate our concocted "hostname:/path"
- * string prematurely.
- */
- NFS_HN_DREF(nap->hostname, host_name);
-#ifdef MNT2_NFS_OPT_HOSTNAME
- nap->flags |= MNT2_NFS_OPT_HOSTNAME;
-#endif /* MNT2_NFS_OPT_HOSTNAME */
-
- /************************************************************************/
- /*** IP ADDRESS OF REMOTE HOST ***/
- /************************************************************************/
- if (ip_addr) {
-#ifdef HAVE_TRANSPORT_TYPE_TLI
- nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
- NFS_SA_DREF(nap, ip_addr);
- }
-
- /************************************************************************/
- /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
- /************************************************************************/
+static void
+compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp,
+ const char *nfs_proto, u_long nfs_version)
+{
#ifdef MNT2_NFS_OPT_TCP
if (nfs_proto && STREQ(nfs_proto, "tcp"))
nap->flags |= MNT2_NFS_OPT_TCP;
#endif /* MNT2_NFS_OPT_TCP */
-#ifdef HAVE_NFS_ARGS_T_SOTYPE
- /* bsdi3 uses this */
- if (nfs_proto) {
- if (STREQ(nfs_proto, "tcp"))
- nap->sotype = SOCK_STREAM;
- else if (STREQ(nfs_proto, "udp"))
- nap->sotype = SOCK_DGRAM;
- }
-#endif /* HAVE_NFS_ARGS_T_SOTYPE */
-
-#ifdef HAVE_NFS_ARGS_T_PROTO
- nap->proto = 0; /* bsdi3 sets this field to zero */
-# ifdef IPPROTO_TCP
- if (nfs_proto) {
- if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
- nap->proto = IPPROTO_TCP;
- else if (STREQ(nfs_proto, "udp"))
- nap->proto = IPPROTO_UDP;
- }
-# endif /* IPPROTO_TCP */
-#endif /* HAVE_NFS_ARGS_T_SOTYPE */
-
-#ifdef HAVE_NFS_ARGS_T_VERSION
-# ifdef NFS_ARGSVERSION
- nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
-# endif /* NFS_ARGSVERSION */
-# ifdef DG_MOUNT_NFS_VERSION
- nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
-# endif /* DG_MOUNT_NFS_VERSION */
-#endif /* HAVE_NFS_ARGS_VERSION */
-
- /************************************************************************/
- /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
- /************************************************************************/
#ifdef MNT2_NFS_OPT_NOCONN
/* check if user specified to use unconnected or connected sockets */
if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
@@ -624,28 +536,6 @@ compute_nfs_args(nfs_args_t *nap,
# endif /* not MNTTAB_OPT_RESVPORT */
#endif /* MNT2_NFS_OPT_RESVPORT */
- /************************************************************************/
- /*** OTHER FLAGS AND OPTIONS ***/
- /************************************************************************/
-
-#ifdef HAVE_TRANSPORT_TYPE_TLI
- /* set up syncaddr field */
- nap->syncaddr = (struct netbuf *) NULL;
-
- /* set up knconf field */
- if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
- plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
- going_down(1);
- }
- /* update the flags field for knconf */
- nap->flags |= MNT2_NFS_OPT_KNCONF;
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
-
-#ifdef MNT2_NFS_OPT_FSNAME
- nap->fsname = fs_name;
- nap->flags |= MNT2_NFS_OPT_FSNAME;
-#endif /* MNT2_NFS_OPT_FSNAME */
-
nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
#ifdef MNT2_NFS_OPT_RSIZE
if (nap->rsize)
@@ -674,11 +564,6 @@ compute_nfs_args(nfs_args_t *nap,
nap->flags |= MNT2_NFS_OPT_RETRANS;
#endif /* MNT2_NFS_OPT_RETRANS */
-#ifdef MNT2_NFS_OPT_BIODS
- if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
- nap->flags |= MNT2_NFS_OPT_BIODS;
-#endif /* MNT2_NFS_OPT_BIODS */
-
#ifdef MNT2_NFS_OPT_SOFT
if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
nap->flags |= MNT2_NFS_OPT_SOFT;
@@ -687,7 +572,7 @@ compute_nfs_args(nfs_args_t *nap,
#ifdef MNT2_NFS_OPT_SPONGY
if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
nap->flags |= MNT2_NFS_OPT_SPONGY;
- if (nap->flags & MNT2_NFS_OPT_SOFT) {
+ if (*flags & MNT2_NFS_OPT_SOFT) {
plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
nap->flags &= ~MNT2_NFS_OPT_SOFT;
}
@@ -720,6 +605,11 @@ compute_nfs_args(nfs_args_t *nap,
# endif /* MNT2_NFS_OPT_NOINT */
#endif /* MNTTAB_OPT_INTR */
+#ifdef MNT2_NFS_OPT_NOACL
+ if (amu_hasmntopt(mntp, MNTTAB_OPT_NOACL) != NULL)
+ nap->flags |= MNT2_NFS_OPT_NOACL;
+#endif /* MNT2_NFS_OPT_NOACL */
+
#ifdef MNTTAB_OPT_NODEVS
if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
nap->flags |= MNT2_NFS_OPT_NODEVS;
@@ -735,39 +625,17 @@ compute_nfs_args(nfs_args_t *nap,
nap->flags |= MNT2_NFS_OPT_PRIVATE;
#endif /* MNTTAB_OPT_PRIVATE */
-#ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
- if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
- nap->flags |= MNT2_NFS_OPT_SYMTTL;
-#endif /* MNTTAB_OPT_SYMTTL */
-
-#ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
- if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
- nap->flags |= MNT2_NFS_OPT_PGTHRESH;
-#endif /* MNT2_NFS_OPT_PGTHRESH */
#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
nap->flags |= MNT2_NFS_OPT_NOCTO;
#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
-#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
- if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
- nap->flags |= MNT2_NFS_OPT_POSIX;
- nap->pathconf = NULL;
- }
-#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
-
#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
nap->flags |= MNT2_NFS_OPT_PROPLIST;
#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */
-#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
- nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
- if (nap->maxgrouplist != 0)
- nap->flags |= MNT2_NFS_OPT_MAXGRPS;
-#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
-
#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
nap->flags |= MNT2_NFS_OPT_NONLM;
@@ -777,77 +645,35 @@ compute_nfs_args(nfs_args_t *nap,
if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */
-
-#ifdef HAVE_NFS_ARGS_T_OPTSTR
- nap->optstr = mntp->mnt_opts;
-#endif /* HAVE_NFS_ARGS_T_OPTSTR */
-
- /************************************************************************/
- /*** FINAL ACTIONS ***/
- /************************************************************************/
-
-#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
- /* Ultrix stores generic flags in nfs_args.gfs_flags. */
- nap->gfs_flags = genflags;
-#endif /* HAVE_NFS_ARGS_T_FLAGS */
-
- return; /* end of compute_nfs_args() function */
}
-
-/*
- * Fill in special values for flags and fields of nfs_args, for an
- * automounter NFS mount.
- */
-void
-compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
+static void
+print_nfs_common_args(const struct nfs_common_args *a)
{
-#ifdef MNT2_NFS_OPT_SYMTTL
- /*
- * Don't let the kernel cache symbolic links we generate, or else lookups
- * will bypass amd and fail to remount stuff as needed.
- */
- plog(XLOG_INFO, "turning on NFS option symttl and setting value to 0");
- nap->flags |= MNT2_NFS_OPT_SYMTTL;
- nap->symttl = 0;
-#endif /* MNT2_NFS_OPT_SYMTTL */
-
- /*
- * This completes the flags for the HIDE_MOUNT_TYPE code in the
- * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
- * Some systems don't have a mount type, but a mount flag.
- */
-#ifdef MNT2_NFS_OPT_AUTO
- nap->flags |= MNT2_NFS_OPT_AUTO;
-#endif /* MNT2_NFS_OPT_AUTO */
-#ifdef MNT2_NFS_OPT_IGNORE
- nap->flags |= MNT2_NFS_OPT_IGNORE;
-#endif /* MNT2_NFS_OPT_IGNORE */
-#ifdef MNT2_GEN_OPT_AUTOMNTFS
- nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
-#endif /* not MNT2_GEN_OPT_AUTOMNTFS */
+ plog(XLOG_DEBUG, "NA->flags = 0x%lx", a->flags);
-#ifdef MNT2_NFS_OPT_DUMBTIMR
- /*
- * Don't let the kernel start computing throughput of Amd. The numbers
- * will be meaningless because of the way Amd does mount retries.
- */
- plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
- nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
-#endif /* MNT2_NFS_OPT_DUMBTIMR */
-
- /* compute all of the NFS attribute-cache flags */
- compute_nfs_attrcache_flags(nap, mntp);
+ plog(XLOG_DEBUG, "NA->rsize = %lu", a->rsize);
+ plog(XLOG_DEBUG, "NA->wsize = %lu", a->wsize);
+ plog(XLOG_DEBUG, "NA->timeo = %lu", a->timeo);
+ plog(XLOG_DEBUG, "NA->retrans = %lu", a->retrans);
- /*
- * Provide a slight bit more security by requiring the kernel to use
- * reserved ports.
- */
-#ifdef MNT2_NFS_OPT_RESVPORT
- nap->flags |= MNT2_NFS_OPT_RESVPORT;
-#endif /* MNT2_NFS_OPT_RESVPORT */
+#ifdef HAVE_NFS_ARGS_T_ACREGMIN
+ plog(XLOG_DEBUG, "NA->acregmin = %lu", a->acregmin);
+ plog(XLOG_DEBUG, "NA->acregmax = %lu", a->acregmax);
+ plog(XLOG_DEBUG, "NA->acdirmin = %lu", a->acdirmin);
+ plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax);
+#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
}
+static void
+discard_nfs23_args(nfs_args_t *nap)
+{
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ free_knetconfig(nap->knconf);
+ if (nap->addr)
+ XFREE(nap->addr); /* allocated in compute_nfs_args() */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+}
#ifdef DEBUG
/* get string version (in hex) of identifier */
@@ -855,29 +681,48 @@ static char *
get_hex_string(u_int len, const char *fhdata)
{
u_int i;
- static char buf[128]; /* better not go over it! */
+ static u_int xlen;
+ static char *buf;
+ static u_short *arr;
char str[16];
- short int arr[64];
- if (!fhdata)
+ if (!fhdata || len == 0 || len > 10240)
return NULL;
+ i = len * 4 + 1;
+ if (xlen < i) {
+ buf = xrealloc(buf, i);
+ arr = xrealloc(arr, len * sizeof(*arr));
+ xlen = i;
+ }
+
buf[0] = '\0';
- memset(&arr[0], 0, (64 * sizeof(short int)));
- memcpy(&arr[0], &fhdata[0], len);
- for (i=0; i<len/sizeof(unsigned short int); i++) {
+ memset(arr, 0, len * sizeof(*arr));
+ memcpy(arr, fhdata, len);
+ len /= sizeof(*arr);
+ for (i = 0; i < len; i++) {
xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i]));
- xstrlcat(buf, str, sizeof(buf));
+ xstrlcat(buf, str, xlen);
}
return buf;
}
+static void
+print_nfs_sockaddr_in(const char *tag, const struct sockaddr_in *sap)
+{
+ char name[64];
+ plog(XLOG_DEBUG, "NA->%s.sin_family = %d", tag, sap->sin_family);
+ plog(XLOG_DEBUG, "NA->%s.sin_port = %d", tag, ntohs(sap->sin_port));
+ if (inet_ntop(AF_INET, &sap->sin_addr, name, sizeof(name)) == NULL)
+ return;
+ plog(XLOG_DEBUG, "NA->%s.sin_addr = \"%s\"", tag, name);
+}
/*
* print a subset of fields from "struct nfs_args" that are otherwise
* not being provided anywhere else.
*/
-void
-print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
+static void
+print_nfs23_args(const nfs_args_t *nap, u_long nfs_version)
{
int fhlen = 32; /* default: NFS V.2 file handle length is 32 */
#ifdef HAVE_TRANSPORT_TYPE_TLI
@@ -886,6 +731,7 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
#else /* not HAVE_TRANSPORT_TYPE_TLI */
struct sockaddr_in *sap;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+ struct nfs_common_args a;
if (!nap) {
plog(XLOG_DEBUG, "NULL nfs_args!");
@@ -919,17 +765,11 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
# else /* not NFS_ARGS_T_ADDR_IS_POINTER */
sap = (struct sockaddr_in *) &nap->addr;
# endif /* not NFS_ARGS_T_ADDR_IS_POINTER */
- plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
- (int) sizeof(struct sockaddr_in),
- get_hex_string(sizeof(struct sockaddr_in), (const char *)sap));
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
/* as per POSIX, sin_len need not be set (used internally by kernel) */
plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- plog(XLOG_DEBUG, "NA->addr.sin_family = %d", sap->sin_family);
- plog(XLOG_DEBUG, "NA->addr.sin_port = %d", sap->sin_port);
- plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"",
- get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr));
+ print_nfs_sockaddr_in("addr", sap);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
#ifdef HAVE_NFS_ARGS_T_ADDRLEN
plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen);
@@ -972,22 +812,13 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
plog(XLOG_DEBUG, "NA->version = %d", nap->version);
#endif /* HAVE_NFS_ARGS_T_VERSION */
- plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags);
+ put_nfs_common_args(nap, a);
+ print_nfs_common_args(&a);
- plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize);
- plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize);
#ifdef HAVE_NFS_ARGS_T_BSIZE
plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
#endif /* HAVE_NFS_ARGS_T_BSIZE */
- plog(XLOG_DEBUG, "NA->timeo = %d", (int) nap->timeo);
- plog(XLOG_DEBUG, "NA->retrans = %d", (int) nap->retrans);
-#ifdef HAVE_NFS_ARGS_T_ACREGMIN
- plog(XLOG_DEBUG, "NA->acregmin = %d", (int) nap->acregmin);
- plog(XLOG_DEBUG, "NA->acregmax = %d", (int) nap->acregmax);
- plog(XLOG_DEBUG, "NA->acdirmin = %d", (int) nap->acdirmin);
- plog(XLOG_DEBUG, "NA->acdirmax = %d", (int) nap->acdirmax);
-#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
#ifdef MNTTAB_OPT_SYMTTL
plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
#endif /* MNTTAB_OPT_SYMTTL */
@@ -1001,3 +832,665 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
}
#endif /* DEBUG */
+
+/*
+ * Fill in the many possible fields and flags of struct nfs_args.
+ *
+ * nap: pre-allocated structure to fill in.
+ * mntp: mount entry structure (includes options)
+ * genflags: generic mount flags already determined
+ * nfsncp: (TLI only) netconfig entry for this NFS mount
+ * ip_addr: IP address of file server
+ * nfs_version: 2, 3, or 0 if unknown
+ * nfs_proto: "udp", "tcp", or NULL.
+ * fhp: file handle structure pointer
+ * host_name: name of remote NFS host
+ * fs_name: remote file system name to mount
+ */
+static void
+compute_nfs23_args(nfs_args_t *nap,
+ mntent_t *mntp,
+ int genflags,
+ struct netconfig *nfsncp,
+ struct sockaddr_in *ip_addr,
+ u_long nfs_version,
+ char *nfs_proto,
+ am_nfs_handle_t *fhp,
+ char *host_name,
+ char *fs_name)
+{
+ struct nfs_common_args a;
+ /* initialize just in case */
+ memset((voidp) nap, 0, sizeof(nfs_args_t));
+
+ /* compute all of the NFS attribute-cache flags */
+ memset(&a, 0, sizeof(a));
+ compute_nfs_attrcache_flags(&a, mntp);
+ compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
+ get_nfs_common_args(nap, a);
+
+ /************************************************************************/
+ /*** FILEHANDLE DATA AND LENGTH ***/
+ /************************************************************************/
+#ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3) {
+ if (fhp == NULL) {
+ plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
+ going_down(1);
+ return;
+ }
+
+# if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
+ /*
+ * Some systems (Irix/bsdi3) have a separate field in nfs_args for
+ * the length of the file handle for NFS V3. They insist that
+ * the file handle set in nfs_args be plain bytes, and not
+ * include the length field.
+ */
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
+# else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
+# endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
+# ifdef MNT2_NFS_OPT_NFSV3
+ nap->flags |= MNT2_NFS_OPT_NFSV3;
+# endif /* MNT2_NFS_OPT_NFSV3 */
+# ifdef MNT2_NFS_OPT_VER3
+ nap->flags |= MNT2_NFS_OPT_VER3;
+# endif /* MNT2_NFS_OPT_VER3 */
+ } else
+#endif /* HAVE_FS_NFS3 */
+ {
+ if (fhp == NULL) {
+ plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
+ going_down(1);
+ return;
+ }
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
+ }
+
+#ifdef HAVE_NFS_ARGS_T_FHSIZE
+# ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3)
+ nap->fhsize = fhp->v3.am_fh3_length;
+ else
+# endif /* HAVE_FS_NFS3 */
+ nap->fhsize = FHSIZE;
+#endif /* HAVE_NFS_ARGS_T_FHSIZE */
+
+ /* this is the version of the nfs_args structure, not of NFS! */
+#ifdef HAVE_NFS_ARGS_T_FH_LEN
+# ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3)
+ nap->fh_len = fhp->v3.am_fh3_length;
+ else
+# endif /* HAVE_FS_NFS3 */
+ nap->fh_len = FHSIZE;
+#endif /* HAVE_NFS_ARGS_T_FH_LEN */
+
+ /************************************************************************/
+ /*** HOST NAME ***/
+ /************************************************************************/
+ /*
+ * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
+ * struct nfs_args, or truncate our concocted "hostname:/path"
+ * string prematurely.
+ */
+ NFS_HN_DREF(nap->hostname, host_name);
+#ifdef MNT2_NFS_OPT_HOSTNAME
+ nap->flags |= MNT2_NFS_OPT_HOSTNAME;
+#endif /* MNT2_NFS_OPT_HOSTNAME */
+
+ /************************************************************************/
+ /*** IP ADDRESS OF REMOTE HOST ***/
+ /************************************************************************/
+ if (ip_addr) {
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+ NFS_SA_DREF(nap, ip_addr);
+ }
+
+ /************************************************************************/
+ /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
+ /************************************************************************/
+#ifdef HAVE_NFS_ARGS_T_SOTYPE
+ /* bsdi3 uses this */
+ if (nfs_proto) {
+ if (STREQ(nfs_proto, "tcp"))
+ nap->sotype = SOCK_STREAM;
+ else if (STREQ(nfs_proto, "udp"))
+ nap->sotype = SOCK_DGRAM;
+ }
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
+
+#ifdef HAVE_NFS_ARGS_T_PROTO
+ nap->proto = 0; /* bsdi3 sets this field to zero */
+# ifdef IPPROTO_TCP
+ if (nfs_proto) {
+ if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
+ nap->proto = IPPROTO_TCP;
+ else if (STREQ(nfs_proto, "udp"))
+ nap->proto = IPPROTO_UDP;
+ }
+# endif /* IPPROTO_TCP */
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
+
+#ifdef HAVE_NFS_ARGS_T_VERSION
+# ifdef NFS_ARGSVERSION
+ nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
+# endif /* NFS_ARGSVERSION */
+# ifdef DG_MOUNT_NFS_VERSION
+ nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
+# endif /* DG_MOUNT_NFS_VERSION */
+#endif /* HAVE_NFS_ARGS_VERSION */
+
+ /************************************************************************/
+ /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
+ /************************************************************************/
+
+ /************************************************************************/
+ /*** OTHER FLAGS AND OPTIONS ***/
+ /************************************************************************/
+
+#ifdef MNT2_NFS_OPT_BIODS
+ if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
+ nap->flags |= MNT2_NFS_OPT_BIODS;
+#endif /* MNT2_NFS_OPT_BIODS */
+
+#ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
+ if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
+ nap->args.flags |= MNT2_NFS_OPT_SYMTTL;
+#endif /* MNTTAB_OPT_SYMTTL */
+
+#ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
+ if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
+ nap->args.flags |= MNT2_NFS_OPT_PGTHRESH;
+#endif /* MNT2_NFS_OPT_PGTHRESH */
+
+#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
+ if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+ nap->flags |= MNT2_NFS_OPT_POSIX;
+# ifdef HAVE_NFS_ARGS_T_PATHCONF
+ nap->pathconf = NULL;
+# endif /* HAVE_NFS_ARGS_T_PATHCONF */
+ }
+#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ /* set up syncaddr field */
+ nap->syncaddr = (struct netbuf *) NULL;
+
+ /* set up knconf field */
+ if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
+ plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
+ going_down(1);
+ return;
+ }
+ /* update the flags field for knconf */
+ nap->args.flags |= MNT2_NFS_OPT_KNCONF;
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+
+#ifdef MNT2_NFS_OPT_FSNAME
+ nap->fsname = fs_name;
+ nap->args.flags |= MNT2_NFS_OPT_FSNAME;
+#endif /* MNT2_NFS_OPT_FSNAME */
+
+
+#ifdef HAVE_NFS_ARGS_T_OPTSTR
+ nap->optstr = mntp->mnt_opts;
+#endif /* HAVE_NFS_ARGS_T_OPTSTR */
+
+#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
+ nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
+ if (nap->maxgrouplist != 0)
+ nap->flags |= MNT2_NFS_OPT_MAXGRPS;
+#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
+
+ /************************************************************************/
+ /*** FINAL ACTIONS ***/
+ /************************************************************************/
+
+#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
+ /* Ultrix stores generic flags in nfs_args.gfs_flags. */
+ nap->gfs_flags = genflags;
+#endif /* HAVE_NFS_ARGS_T_FLAGS */
+
+ return; /* end of compute_nfs_args() function */
+}
+
+#ifdef HAVE_FS_NFS4
+
+#define RPC_AUTH_GSS_KRB5 390003
+#define RPC_AUTH_GSS_KRB5I 390004
+#define RPC_AUTH_GSS_KRB5P 390005
+#define RPC_AUTH_GSS_LKEY 390006
+#define RPC_AUTH_GSS_LKEYI 390007
+#define RPC_AUTH_GSS_LKEYP 390008
+#define RPC_AUTH_GSS_SPKM 390009
+#define RPC_AUTH_GSS_SPKMI 390010
+#define RPC_AUTH_GSS_SPKMP 390011
+
+struct {
+ const char *name;
+ int num;
+} flavours[] = {
+ { "unix", AUTH_UNIX },
+ { "krb5", RPC_AUTH_GSS_KRB5 },
+ { "krb5i", RPC_AUTH_GSS_KRB5I },
+ { "krb5p", RPC_AUTH_GSS_KRB5P },
+ { "lkey", RPC_AUTH_GSS_LKEY },
+ { "lkeyi", RPC_AUTH_GSS_LKEYI },
+ { "lkeyp", RPC_AUTH_GSS_LKEYP },
+ { "spkm", RPC_AUTH_GSS_SPKM },
+ { "spkmi", RPC_AUTH_GSS_SPKMI },
+ { "spkmp", RPC_AUTH_GSS_SPKMP },
+};
+
+static char *
+set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp)
+{
+ const char *o = hasmnteq(mntp, MNTTAB_OPT_SEC);
+ char *q, *s, *ss;
+ size_t l, i;
+
+ if (o == NULL)
+ o = "unix";
+
+ for (l = 1, q = strchr(o, ','); q; q = strchr(q + 1, ','))
+ l++;
+
+ nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours));
+
+ s = ss = xstrdup(o);
+ for (;;) {
+ q = strchr(s, ',');
+ if (q)
+ *q = '\0';
+
+ for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++)
+ if (strcmp(flavours[i].name, s) == 0) {
+ nap->auth_flavours[l++] = flavours[i].num;
+ break;
+ }
+
+ if (i == sizeof(flavours) / sizeof(flavours[0]))
+ plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %s\n", s);
+
+ if (q == NULL)
+ break;
+
+ *q = ':';
+ s = ++q;
+ }
+
+ nap->auth_flavourlen = l;
+ return ss;
+}
+
+static int
+get_my_ipv4addr(struct nfs_string *ns)
+{
+ struct hostent *hp;
+ char myname[MAXHOSTNAMELEN];
+
+ if (gethostname(myname, sizeof(myname)) == -1)
+ return -1;
+ if ((hp = gethostbyname(myname)) == NULL)
+ return -1;
+ if (inet_ntop(AF_INET, hp->h_addr, myname, sizeof(myname)) == NULL)
+ return -1;
+ ns->len = strlen(myname);
+ ns->data = xmalloc(ns->len + 1);
+ memcpy(ns->data, myname, ns->len + 1);
+ return 0;
+}
+
+static void
+add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec)
+{
+ char *opts = mntp->mnt_opts;
+ char buf[1024], addr[128];
+ size_t len = strlen(mntp->mnt_opts);
+
+ if (inet_ntop(AF_INET,
+ &((const struct sockaddr_in *)nap->host_addr)->sin_addr,
+ addr, sizeof(addr)) == NULL)
+ return;
+
+ xsnprintf(buf, sizeof(buf), ",clientaddr=%s,addr=%s", nap->client_addr.data,
+ addr);
+
+ len += strlen(buf) + 1;
+
+ if (sec && strcmp(sec, "unix") != 0) {
+ len += strlen(sec) + strlen(MNTTAB_OPT_SEC) + 2; /* 2 = ",=" */
+ } else
+ sec = NULL;
+
+ opts = xrealloc(mntp->mnt_opts, len);
+ xstrlcat(opts, buf, len);
+
+ if (sec) {
+ xstrlcat(opts, ",", len);
+ xstrlcat(opts, MNTTAB_OPT_SEC, len);
+ xstrlcat(opts, "=", len);
+ xstrlcat(opts, sec, len);
+ }
+
+ mntp->mnt_opts = opts;
+}
+
+static void
+print_nfs4_security(const nfs4_args_t *nap)
+{
+ char buf[1024];
+ char num[64];
+ size_t i, j;
+
+ buf[0] = '\0';
+
+ for (i = 0; i < nap->auth_flavourlen; i++) {
+
+ for (j = 0; j < sizeof(flavours) / sizeof(flavours[0]); j++)
+ if (flavours[j].num == nap->auth_flavours[i]) {
+ xstrlcpy(num, flavours[j].name, sizeof(num));
+ break;
+ }
+
+ if (j == sizeof(flavours) / sizeof(flavours[0])) {
+ plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %d\n",
+ nap->auth_flavours[i]);
+ xsnprintf(num, sizeof(num), "*%d*", nap->auth_flavours[i]);
+ }
+
+ if (buf[0])
+ xstrlcat(buf, ":", sizeof(buf));
+
+ xstrlcat(buf, num, sizeof(buf));
+ }
+
+ plog(XLOG_DEBUG, "NA->auth_flavours \"%s\"\n", buf);
+}
+
+static void
+discard_nfs4_args(nfs4_args_t *nap)
+{
+ if (nap->client_addr.data)
+ free(nap->client_addr.data);
+ if (nap->hostname.data)
+ free(nap->hostname.data);
+ if (nap->mnt_path.data)
+ free(nap->mnt_path.data);
+ if (nap->host_addr)
+ free(nap->host_addr);
+ if (nap->auth_flavours)
+ free(nap->auth_flavours);
+}
+
+/*
+ * Fill in the many possible fields and flags of struct nfs4_args.
+ *
+ * nap: pre-allocated structure to fill in.
+ * mntp: mount entry structure (includes options)
+ * genflags: generic mount flags already determined
+ * nfsncp: (TLI only) netconfig entry for this NFS mount
+ * ip_addr: IP address of file server
+ * nfs_version: 4, or 0 if unknown
+ * nfs_proto: "udp", "tcp", or NULL.
+ * fhp: file handle structure pointer
+ * host_name: name of remote NFS host
+ * fs_name: remote file system name to mount
+ */
+static void
+compute_nfs4_args(nfs4_args_t *nap,
+ mntent_t *mntp,
+ int genflags,
+ struct netconfig *nfsncp,
+ struct sockaddr_in *ip_addr,
+ u_long nfs_version,
+ char *nfs_proto,
+ am_nfs_handle_t *fhp,
+ char *host_name,
+ char *fs_name)
+{
+ char *s;
+ struct nfs_common_args a;
+ uint16_t nfs_port;
+
+ /* initialize just in case */
+ memset((voidp) nap, 0, sizeof(nfs4_args_t));
+
+ /* compute all of the NFS attribute-cache flags */
+ memset(&a, 0, sizeof(a));
+ compute_nfs_attrcache_flags(&a, mntp);
+ compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
+ get_nfs_common_args(nap, a);
+
+ get_my_ipv4addr(&nap->client_addr);
+
+ /************************************************************************/
+ /*** HOST NAME ***/
+ /************************************************************************/
+ nap->hostname.len = strlen(host_name);
+ nap->hostname.data = xmalloc(nap->hostname.len + 1);
+ memcpy(nap->hostname.data, host_name, nap->hostname.len + 1);
+
+ if ((s = strchr(fs_name, ':')) != NULL)
+ s++;
+ else
+ s = fs_name;
+
+ nap->mnt_path.len = strlen(s);
+ nap->mnt_path.data = xmalloc(nap->mnt_path.len + 1);
+ memcpy(nap->mnt_path.data, s, nap->mnt_path.len + 1);
+ plog(XLOG_DEBUG, "dir name %s\n", nap->mnt_path.data);
+
+ /************************************************************************/
+ /*** IP ADDRESS OF REMOTE HOST ***/
+ /************************************************************************/
+ nap->host_addrlen = sizeof(*ip_addr);
+ nap->host_addr = xmalloc(nap->host_addrlen);
+ memcpy(nap->host_addr, ip_addr, nap->host_addrlen);
+
+ nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT);
+ if (nfs_port == 0)
+ nfs_port = htons(NFS_PORT);
+ else
+ nfs_port = htons(nfs_port);
+
+ ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port;
+
+ nap->proto = 0; /* bsdi3 sets this field to zero */
+ if (nfs_proto) {
+ if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
+ nap->proto = IPPROTO_TCP;
+ else if (STREQ(nfs_proto, "udp"))
+ nap->proto = IPPROTO_UDP;
+ }
+
+ nap->version = NFS4_MOUNT_VERSION; /* BSDI 3.0 and OpenBSD 2.2 */
+
+ /************************************************************************/
+ /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
+ /************************************************************************/
+
+
+ /************************************************************************/
+ /*** OTHER FLAGS AND OPTIONS ***/
+ /************************************************************************/
+
+#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
+ if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+ nap->args.flags |= MNT2_NFS_OPT_POSIX;
+# ifdef HAVE_NFS_ARGS_T_PATHCONF
+ nap->pathconf = NULL;
+# endif /* HAVE_NFS_ARGS_T_PATHCONF */
+ }
+#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
+
+#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
+ nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
+ if (nap->maxgrouplist != 0)
+ nap->args.flags |= MNT2_NFS_OPT_MAXGRPS;
+#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
+
+#ifdef HAVE_NFS_ARGS_T_OPTSTR
+ nap->optstr = mntp->mnt_opts;
+#endif /* HAVE_NFS_ARGS_T_OPTSTR */
+
+ /************************************************************************/
+ /*** FINAL ACTIONS ***/
+ /************************************************************************/
+
+#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
+ /* Ultrix stores generic flags in nfs_args.gfs_flags. */
+ nap->gfs_flags = genflags;
+#endif /* HAVE_NFS_ARGS_T_FLAGS */
+
+ s = set_nfs4_security(nap, mntp);
+
+ /* Add addresses to the mount options */
+ add_nfs4_mntopts(nap, mntp, s);
+
+ return; /* end of compute_nfs4_args() function */
+}
+
+#ifdef DEBUG
+static void
+print_nfs4_args(const nfs4_args_t *nap, u_long nfs_version)
+{
+ struct sockaddr_in *sap;
+ struct nfs_common_args a;
+
+ if (!nap) {
+ plog(XLOG_DEBUG, "NULL nfs_args!");
+ return;
+ }
+
+ plog(XLOG_DEBUG, "NA->client_addr \"%s\"\n", nap->client_addr.data);
+ plog(XLOG_DEBUG, "NA->mnt_path = \"%s\"", nap->mnt_path.data);
+ plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname.data);
+ sap = (struct sockaddr_in *) nap->host_addr;
+ print_nfs_sockaddr_in("host_addr", sap);
+ plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
+#ifdef HAVE_NFS_ARGS_T_VERSION
+ plog(XLOG_DEBUG, "NA->version = %d", nap->version);
+#endif /* HAVE_NFS_ARGS_T_VERSION */
+ print_nfs4_security(nap);
+
+ put_nfs_common_args(nap, a);
+ print_nfs_common_args(&a);
+}
+#endif
+#endif /* HAVE_FS_NFS4 */
+
+void
+compute_nfs_args(void *nap,
+ mntent_t *mntp,
+ int genflags,
+ struct netconfig *nfsncp,
+ struct sockaddr_in *ip_addr,
+ u_long nfs_version,
+ char *nfs_proto,
+ am_nfs_handle_t *fhp,
+ char *host_name,
+ char *fs_name)
+{
+#ifdef HAVE_FS_NFS4
+ if (nfs_version == NFS_VERSION4)
+ compute_nfs4_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
+ nfs_proto, fhp, host_name, fs_name);
+ else
+#endif /* HAVE_FS_NFS4 */
+ compute_nfs23_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
+ nfs_proto, fhp, host_name, fs_name);
+}
+
+void
+discard_nfs_args(void *nap, u_long nfs_version)
+{
+#ifdef HAVE_FS_NFS4
+ if (nfs_version == NFS_VERSION4)
+ discard_nfs4_args(nap);
+ else
+#endif /* HAVE_FS_NFS4 */
+ discard_nfs23_args(nap);
+}
+
+#ifdef DEBUG
+void
+print_nfs_args(const void *nap, u_long nfs_version)
+{
+#ifdef HAVE_FS_NFS4
+ if (nfs_version == NFS_VERSION4)
+ print_nfs4_args(nap, nfs_version);
+ else
+#endif /* HAVE_FS_NFS4 */
+ print_nfs23_args(nap, nfs_version);
+}
+#endif
+
+
+/*
+ * Fill in special values for flags and fields of nfs_args, for an
+ * automounter NFS mount.
+ */
+void
+compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
+{
+ struct nfs_common_args a;
+
+#ifdef MNT2_NFS_OPT_SYMTTL
+ /*
+ * Don't let the kernel cache symbolic links we generate, or else lookups
+ * will bypass amd and fail to remount stuff as needed.
+ */
+ plog(XLOG_INFO, "turning on NFS option symttl and setting value to 0");
+ nap->flags |= MNT2_NFS_OPT_SYMTTL;
+ nap->symttl = 0;
+#endif /* MNT2_NFS_OPT_SYMTTL */
+
+ /*
+ * This completes the flags for the HIDE_MOUNT_TYPE code in the
+ * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
+ * Some systems don't have a mount type, but a mount flag.
+ */
+#ifdef MNT2_NFS_OPT_AUTO
+ nap->flags |= MNT2_NFS_OPT_AUTO;
+#endif /* MNT2_NFS_OPT_AUTO */
+#ifdef MNT2_NFS_OPT_IGNORE
+ nap->flags |= MNT2_NFS_OPT_IGNORE;
+#endif /* MNT2_NFS_OPT_IGNORE */
+#ifdef MNT2_GEN_OPT_AUTOMNTFS
+ nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
+#endif /* not MNT2_GEN_OPT_AUTOMNTFS */
+
+#ifdef MNT2_NFS_OPT_DUMBTIMR
+ /*
+ * Don't let the kernel start computing throughput of Amd. The numbers
+ * will be meaningless because of the way Amd does mount retries.
+ */
+ plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
+ nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
+#endif /* MNT2_NFS_OPT_DUMBTIMR */
+
+ /* compute all of the NFS attribute-cache flags */
+ memset(&a, 0, sizeof(a));
+ a.flags = nap->flags;
+ compute_nfs_attrcache_flags(&a, mntp);
+ get_nfs_common_args(nap, a);
+
+ /*
+ * Provide a slight bit more security by requiring the kernel to use
+ * reserved ports.
+ */
+#ifdef MNT2_NFS_OPT_RESVPORT
+ nap->flags |= MNT2_NFS_OPT_RESVPORT;
+#endif /* MNT2_NFS_OPT_RESVPORT */
+}
+
+int
+nfs_valid_version(u_long v)
+{
+ return v >= NFS_VERS_MIN && v <= NFS_VERS_MAX;
+}