+++ /dev/null
---- util-linux-2.10m/mount/nfs_mount4.h.compat Sun Apr 16 14:48:48 2000
-+++ util-linux-2.10m/mount/nfs_mount4.h Thu Jun 29 20:51:22 2000
-@@ -4,11 +4,16 @@
- * Thus, if necessary we teach nfsmount.c the structure of new fields
- * that will come later.
- *
-- * Moreover, the new kernel includes conflict with glibc includes
-- * so it is easiest to ignore the kernel altogether (at compile time).
- */
-
-+#include "nfs_mountversion.h"
-+
- #define NFS_MOUNT_VERSION 4
-+
-+#if KERNEL_NFS_MOUNT_VERSION >= 4
-+#define NFS_FHSIZE 32
-+#define NFS_PORT 2049
-+#endif
-
- struct nfs2_fh {
- char data[32];
---- util-linux-2.10m/mount/Makefile.compat Thu Jun 29 20:49:43 2000
-+++ util-linux-2.10m/mount/Makefile Thu Jun 29 20:50:23 2000
-@@ -108,7 +108,10 @@ nfsmount.h nfsmount_xdr.c nfsmount_clnt.
- cp $(RPCSVCDIR)/nfsmount_clnt.c .
- endif
-
--nfsmount.o: nfs_mount4.h
-+nfsmount.o: nfs_mount4.h nfs_mountversion.h
-+
-+nfs_mountversion.h: /usr/include/linux/nfs_mount.h
-+ grep NFS_MOUNT_VERSION $< | sed -e 's/NFS/KERNEL_NFS/' > $@
-
- swapargs.h:
- sh swap.configure
+++ /dev/null
-
-Miscellaneous nfs mount changes from Trond.
-
----
-
- util-linux-2.12-bfields/mount/Makefile | 4
- util-linux-2.12-bfields/mount/nfsmount.c | 1235 +++++++++++++++++++------------
- util-linux-2.12-bfields/mount/sundries.h | 1
- util-linux-2.12-bfields/mount/umount.c | 4
- 4 files changed, 794 insertions(+), 450 deletions(-)
-
-diff -puN mount/Makefile~nfs mount/Makefile
---- util-linux-2.12/mount/Makefile~nfs 2004-10-13 13:51:44.000000000 -0400
-+++ util-linux-2.12-bfields/mount/Makefile 2004-10-13 14:13:30.000000000 -0400
-@@ -31,7 +31,7 @@
-
- LO_OBJS = lomount.o $(LIB)/xstrncpy.o
- CRYPT_OBJS = cryptsetup.o -lcryptsetup
--NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o
-+NFS_OBJS = nfsmount.o nfsmount_xdr.o
- GEN_FILES = nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
-
- all: $(PROGS)
-@@ -55,7 +55,7 @@
-
- umount: umount.o fstab.o sundries.o xmalloc.o realpath.o mntent.o \
- getusername.o get_label_uuid.o mount_by_label.o mount_blkid.o \
-- version.o $(LIB)/env.o $(LO_OBJS) $(CRYPT_OBJS)
-+ version.o $(LIB)/env.o $(NFS_OBJS) $(LO_OBJS) $(CRYPT_OBJS)
- $(LINK) $^ -o $@ $(BLKID_LIB)
-
- swapon: swapon.o version.o xmalloc.o \
-diff -puN mount/nfsmount.c~nfs mount/nfsmount.c
---- util-linux-2.12/mount/nfsmount.c~nfs 2004-10-13 13:51:44.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfsmount.c 2004-10-13 14:13:30.000000000 -0400
-@@ -34,6 +34,7 @@
-
- #include "../defines.h" /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
-
-+#include <ctype.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <string.h>
-@@ -72,11 +73,100 @@
- #define NFS_FHSIZE 32
- #endif
-
-+#define MNT_SENDBUFSIZE ((u_int)2048)
-+#define MNT_RECVBUFSIZE ((u_int)1024)
-+
- static char *nfs_strerror(int stat);
-
- #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
-
- #define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
-+#define MAX_MNTPROT ((nfs_mount_version >= 4) ? 3 : 2)
-+#define HAVE_RELIABLE_TCP (nfs_mount_version >= 4)
-+
-+#ifndef HAVE_inet_aton
-+#define inet_aton(a,b) (0)
-+#endif
-+
-+typedef dirpath mnt2arg_t;
-+typedef dirpath mnt3arg_t;
-+typedef dirpath mntarg_t;
-+
-+typedef struct fhstatus mnt2res_t;
-+typedef struct mountres3 mnt3res_t;
-+typedef union {
-+ mnt2res_t nfsv2;
-+ mnt3res_t nfsv3;
-+} mntres_t;
-+
-+typedef struct {
-+ char **hostname;
-+ struct sockaddr_in saddr;
-+ struct pmap pmap;
-+} clnt_addr_t;
-+
-+/* RPC call timeout values */
-+static const struct timeval TIMEOUT = { 20, 0 };
-+static const struct timeval RETRY_TIMEOUT = { 3, 0 };
-+
-+/* Define the order in which to probe for UDP/TCP services */
-+static const u_int *
-+proto_probelist(const int use_tcp)
-+{
-+ static const u_int probe_both[] = { IPPROTO_TCP, IPPROTO_UDP, 0 };
-+ static const u_int probe_udponly[] = { IPPROTO_UDP, 0 };
-+ if (use_tcp)
-+ return probe_both;
-+ return probe_udponly;
-+}
-+
-+/* Define the order in which NFS versions are probed on portmapper */
-+static const u_long *
-+nfs_probelist(const int vers)
-+{
-+ static const u_long nfs2_probe[] = { 2, 0};
-+ static const u_long nfs3_probe[] = { 3, 2, 0};
-+ switch (vers) {
-+ case 3:
-+ return nfs3_probe;
-+ default:
-+ return nfs2_probe;
-+ }
-+}
-+
-+/* Define the order in which Mountd versions are probed on portmapper */
-+static const u_long *
-+mnt_probelist(const int vers)
-+{
-+ static const u_long mnt1_probe[] = { 1, 2, 0 };
-+ static const u_long mnt3_probe[] = { 3, 1, 2, 0 };
-+ switch (vers) {
-+ case 3:
-+ return mnt3_probe;
-+ default:
-+ return mnt1_probe;
-+ }
-+}
-+
-+/* Map an NFS version into the corresponding Mountd version */
-+static u_long
-+nfsvers_to_mnt(const u_long vers)
-+{
-+ static const u_long nfs_to_mnt[] = { 0, 0, 1, 3 };
-+ if (vers <= 3)
-+ return nfs_to_mnt[vers];
-+ return 0;
-+}
-+
-+/* Map a Mountd version into the corresponding NFS version */
-+static u_long
-+mntvers_to_nfs(const u_long vers)
-+{
-+ static const u_long mnt_to_nfs[] = { 0, 2, 2, 3 };
-+ if (vers <= 3)
-+ return mnt_to_nfs[vers];
-+ return 0;
-+}
-
- static int
- linux_version_code(void) {
-@@ -102,123 +192,558 @@ linux_version_code(void) {
- * NFS_MOUNT_VERSION: these nfsmount sources at compile time
- * nfs_mount_version: version this source and running kernel can handle
- */
-+static int nfs_mount_version = NFS_MOUNT_VERSION;
-+
- static int
- find_kernel_nfs_mount_version(void) {
- static int kernel_version = -1;
-- int nfs_mount_version = NFS_MOUNT_VERSION;
-+ int mnt_version = NFS_MOUNT_VERSION;
-
- if (kernel_version == -1)
- kernel_version = linux_version_code();
-
- if (kernel_version) {
- if (kernel_version < MAKE_VERSION(2,1,32))
-- nfs_mount_version = 1;
-+ mnt_version = 1;
- else if (kernel_version < MAKE_VERSION(2,2,18))
-- nfs_mount_version = 3;
-+ mnt_version = 3;
- else if (kernel_version < MAKE_VERSION(2,3,0))
-- nfs_mount_version = 4; /* since 2.2.18pre9 */
-+ mnt_version = 4; /* since 2.2.18pre9 */
- else if (kernel_version < MAKE_VERSION(2,3,99))
-- nfs_mount_version = 3;
-+ mnt_version = 3;
- else
-- nfs_mount_version = 4; /* since 2.3.99pre4 */
-+ mnt_version = 4; /* since 2.3.99pre4 */
- }
-- if (nfs_mount_version > NFS_MOUNT_VERSION)
-- nfs_mount_version = NFS_MOUNT_VERSION;
-- return nfs_mount_version;
--}
--
--static struct pmap *
--get_mountport(struct sockaddr_in *server_addr,
-- long unsigned prog,
-- long unsigned version,
-- long unsigned proto,
-- long unsigned port,
-- int nfs_mount_version)
--{
-- struct pmaplist *pmap;
-- static struct pmap p = {0, 0, 0, 0};
--
-- if (version > MAX_NFSPROT)
-- version = MAX_NFSPROT;
-- if (!prog)
-- prog = MOUNTPROG;
-- p.pm_prog = prog;
-- p.pm_vers = version;
-- p.pm_prot = proto;
-- p.pm_port = port;
--
-- server_addr->sin_port = PMAPPORT;
-- pmap = pmap_getmaps(server_addr);
--
-- while (pmap) {
-- if (pmap->pml_map.pm_prog != prog)
-- goto next;
-- if (!version && p.pm_vers > pmap->pml_map.pm_vers)
-- goto next;
-- if (version > 2 && pmap->pml_map.pm_vers != version)
-- goto next;
-- if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
-- goto next;
-- if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
-- (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
-- (port && pmap->pml_map.pm_port != port))
-- goto next;
-- memcpy(&p, &pmap->pml_map, sizeof(p));
-- next:
-- pmap = pmap->pml_next;
-- }
-- if (!p.pm_vers)
-- p.pm_vers = MOUNTVERS;
-- if (!p.pm_prot)
-- p.pm_prot = IPPROTO_TCP;
--#if 0
-- if (!p.pm_port) {
-- p.pm_port = pmap_getport(server_addr, p.pm_prog, p.pm_vers,
-- p.pm_prot);
-+ if (mnt_version > NFS_MOUNT_VERSION)
-+ mnt_version = NFS_MOUNT_VERSION;
-+ return mnt_version;
-+}
-+
-+static int
-+nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
-+{
-+ struct hostent *hp;
-+
-+ saddr->sin_family = AF_INET;
-+ if (!inet_aton(hostname, &saddr->sin_addr)) {
-+ if ((hp = gethostbyname(hostname)) == NULL) {
-+ fprintf(stderr, _("mount: can't get address for %s\n"),
-+ hostname);
-+ return 0;
-+ } else {
-+ if (hp->h_length > sizeof(*saddr)) {
-+ fprintf(stderr,
-+ _("mount: got bad hp->h_length\n"));
-+ hp->h_length = sizeof(*saddr);
-+ }
-+ memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
-+ }
-+ }
-+ return 1;
-+}
-+
-+/*
-+ * Sigh... pmap_getport() doesn't actually check the version number.
-+ * In order to make sure that the server actually supports the service
-+ * we're requesting, we open and RPC client, and fire off a NULL
-+ * RPC call.
-+ */
-+static int
-+clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
-+ const u_int prot)
-+{
-+ CLIENT *clnt;
-+ int sock, stat;
-+ static char clnt_res;
-+
-+ sock = RPC_ANYSOCK;
-+ switch(prot) {
-+ case IPPROTO_UDP:
-+ clnt = clntudp_bufcreate(saddr, prog, vers,
-+ RETRY_TIMEOUT, &sock,
-+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
-+ break;
-+ case IPPROTO_TCP:
-+ clnt = clnttcp_create(saddr, prog, vers, &sock,
-+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
-+ break;
-+ default:
-+ goto out_bad;
-+ }
-+ if (!clnt)
-+ goto out_bad;
-+ memset(&clnt_res, 0, sizeof(clnt_res));
-+ stat = clnt_call(clnt, NULLPROC,
-+ (xdrproc_t)xdr_void, (caddr_t)NULL,
-+ (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
-+ TIMEOUT);
-+ clnt_destroy(clnt);
-+ close(sock);
-+ if (stat != RPC_PROGVERSMISMATCH)
-+ return 1;
-+ out_bad:
-+ return 0;
-+}
-+
-+/*
-+ * Use the portmapper to discover whether or not the service we want is
-+ * available. The lists 'versions' and 'protos' define ordered sequences
-+ * of service versions and udp/tcp protocols to probe for.
-+ */
-+static int
-+probe_port(clnt_addr_t *server,
-+ const u_long *versions,
-+ const u_int *protos)
-+{
-+ struct sockaddr_in *saddr = &server->saddr;
-+ struct pmap *pmap = &server->pmap;
-+ const u_long prog = pmap->pm_prog,
-+ vers = pmap->pm_vers,
-+ *p_vers;
-+ const u_int prot = (u_int)pmap->pm_prot,
-+ *p_prot;
-+ const u_short port = (u_short) pmap->pm_port;
-+ u_short p_port;
-+
-+ p_prot = prot ? &prot : protos;
-+ p_vers = vers ? &vers : versions;
-+ for (;;) {
-+ saddr->sin_port = htons(PMAPPORT);
-+ p_port = pmap_getport(saddr, prog, *p_vers, *p_prot);
-+ if (p_port) {
-+ if (!port || port == p_port) {
-+ saddr->sin_port = htons(port);
-+ if (clnt_ping(saddr, prog, *p_vers, *p_prot))
-+ goto out_ok;
-+ }
-+ } else if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
-+ break;
-+ if (!prot) {
-+ if (*++p_prot)
-+ continue;
-+ p_prot = protos;
-+ }
-+ if (vers || !*++p_vers)
-+ break;
-+ }
-+ return 0;
-+ out_ok:
-+ if (!vers)
-+ pmap->pm_vers = *p_vers;
-+ if (!prot)
-+ pmap->pm_prot = *p_prot;
-+ if (!port)
-+ pmap->pm_port = p_port;
-+ return 1;
-+}
-+
-+static int
-+probe_nfsport(clnt_addr_t *nfs_server)
-+{
-+ const struct pmap *pmap = &nfs_server->pmap;
-+ const u_long *probe_vers;
-+ const u_int *probe_prot;
-+
-+ if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
-+ return 1;
-+ probe_vers = nfs_probelist(MAX_NFSPROT);
-+ probe_prot = proto_probelist(HAVE_RELIABLE_TCP);
-+ return probe_port(nfs_server, probe_vers, probe_prot);
-+}
-+
-+static int
-+probe_mntport(clnt_addr_t *mnt_server)
-+{
-+ const struct pmap *pmap = &mnt_server->pmap;
-+ const u_long *probe_vers;
-+ const u_int *probe_prot;
-+
-+ if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
-+ return 1;
-+ probe_vers = mnt_probelist(MAX_MNTPROT);
-+ probe_prot = proto_probelist(HAVE_RELIABLE_TCP);
-+ return probe_port(mnt_server, probe_vers, probe_prot);
-+}
-+
-+static int
-+probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
-+{
-+ struct pmap *nfs_pmap = &nfs_server->pmap;
-+ struct pmap *mnt_pmap = &mnt_server->pmap;
-+ struct pmap save_nfs, save_mnt;
-+ int res;
-+ const u_long *probe_vers;
-+
-+ if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
-+ nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
-+ else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
-+ mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
-+ if (nfs_pmap->pm_vers)
-+ goto version_fixed;
-+ memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
-+ memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
-+ for (probe_vers = mnt_probelist(MAX_MNTPROT); *probe_vers; probe_vers++) {
-+ nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
-+ if ((res = probe_nfsport(nfs_server) != 0)) {
-+ mnt_pmap->pm_vers = *probe_vers;
-+ if ((res = probe_mntport(mnt_server)) != 0)
-+ return 1;
-+ memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
-+ }
-+ memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
- }
-+ out_bad:
-+ return 0;
-+ version_fixed:
-+ if (!probe_nfsport(nfs_server))
-+ goto out_bad;
-+ return probe_mntport(mnt_server);
-+}
-+
-+static CLIENT *
-+mnt_openclnt(clnt_addr_t *mnt_server, int *msock, const int report_errs)
-+{
-+ struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
-+ struct pmap *mnt_pmap = &mnt_server->pmap;
-+ CLIENT *clnt;
-+
-+ /* contact the mount daemon via TCP */
-+ mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
-+ *msock = RPC_ANYSOCK;
-+
-+ switch (mnt_pmap->pm_prot) {
-+ case IPPROTO_UDP:
-+ clnt = clntudp_bufcreate(mnt_saddr,
-+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
-+ RETRY_TIMEOUT, msock,
-+ MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
-+ break;
-+ case IPPROTO_TCP:
-+ clnt = clnttcp_create(mnt_saddr,
-+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
-+ msock,
-+ MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
-+ break;
-+ default:
-+ goto out_bad;
-+ }
-+ if (!clnt)
-+ goto report_err;
-+ /* try to mount hostname:dirname */
-+ clnt->cl_auth = authunix_create_default();
-+ return clnt;
-+ report_err:
-+ if (report_errs)
-+ clnt_pcreateerror("mount");
-+ out_bad:
-+ return NULL;
-+}
-+
-+static inline void
-+mnt_closeclnt(CLIENT *clnt, int msock)
-+{
-+ auth_destroy(clnt->cl_auth);
-+ clnt_destroy(clnt);
-+ close(msock);
-+}
-+
-+static inline enum clnt_stat
-+nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res)
-+{
-+ return clnt_call(clnt, MOUNTPROC3_MNT,
-+ (xdrproc_t) xdr_dirpath, (caddr_t) mnt3arg,
-+ (xdrproc_t) xdr_mountres3, (caddr_t) mnt3res,
-+ TIMEOUT);
-+}
-+
-+static inline enum clnt_stat
-+nfs2_mount(CLIENT *clnt, mnt2arg_t *mnt2arg, mnt2res_t *mnt2res)
-+{
-+ return clnt_call(clnt, MOUNTPROC_MNT,
-+ (xdrproc_t) xdr_dirpath, (caddr_t) mnt2arg,
-+ (xdrproc_t) xdr_fhstatus, (caddr_t) mnt2res,
-+ TIMEOUT);
-+}
-+
-+static int
-+nfs_call_mount(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server,
-+ mntarg_t *mntarg, mntres_t *mntres, const int report_errs)
-+{
-+ CLIENT *clnt;
-+ enum clnt_stat stat;
-+ int msock;
-+
-+
-+ if (!probe_bothports(mnt_server, nfs_server)) {
-+ if (report_errs)
-+ fprintf(stderr,_("mount: failed to probe ports on NFS server %s\n"),
-+ *nfs_server->hostname);
-+ goto out_bad;
-+ }
-+
-+ clnt = mnt_openclnt(mnt_server, &msock, report_errs);
-+ if (!clnt)
-+ goto out_bad;
-+ /* make pointers in xdr_mountres3 NULL so
-+ * that xdr_array allocates memory for us
-+ */
-+ memset(mntres, 0, sizeof(*mntres));
-+ switch (mnt_server->pmap.pm_vers) {
-+ case 3:
-+ stat = nfs3_mount(clnt, mntarg, &mntres->nfsv3);
-+ break;
-+ case 2:
-+ case 1:
-+ stat = nfs2_mount(clnt, mntarg, &mntres->nfsv2);
-+ break;
-+ default:
-+ goto out_bad;
-+ }
-+ if (stat != RPC_SUCCESS && report_errs)
-+ clnt_perror(clnt, "mount");
-+ mnt_closeclnt(clnt, msock);
-+ if (stat == RPC_SUCCESS)
-+ return 1;
-+ out_bad:
-+ return 0;
-+}
-+
-+static int
-+parse_options(char *old_opts, struct nfs_mount_data *data,
-+ int *bg, int *retry, clnt_addr_t *mnt_server,
-+ clnt_addr_t *nfs_server, char *new_opts, const int opt_size)
-+{
-+ struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
-+ struct pmap *mnt_pmap = &mnt_server->pmap;
-+ struct pmap *nfs_pmap = &nfs_server->pmap;
-+ int len;
-+ char *opt, *opteq;
-+ char *mounthost = NULL;
-+ char cbuf[128];
-+
-+ data->flags = 0;
-+ *bg = 0;
-+
-+ len = strlen(new_opts);
-+ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
-+ if (strlen(opt) >= sizeof(cbuf))
-+ goto bad_parameter;
-+ if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
-+ int val = atoi(opteq + 1);
-+ *opteq = '\0';
-+ if (!strcmp(opt, "rsize"))
-+ data->rsize = val;
-+ else if (!strcmp(opt, "wsize"))
-+ data->wsize = val;
-+ else if (!strcmp(opt, "timeo"))
-+ data->timeo = val;
-+ else if (!strcmp(opt, "retrans"))
-+ data->retrans = val;
-+ else if (!strcmp(opt, "acregmin"))
-+ data->acregmin = val;
-+ else if (!strcmp(opt, "acregmax"))
-+ data->acregmax = val;
-+ else if (!strcmp(opt, "acdirmin"))
-+ data->acdirmin = val;
-+ else if (!strcmp(opt, "acdirmax"))
-+ data->acdirmax = val;
-+ else if (!strcmp(opt, "actimeo")) {
-+ data->acregmin = val;
-+ data->acregmax = val;
-+ data->acdirmin = val;
-+ data->acdirmax = val;
-+ }
-+ else if (!strcmp(opt, "retry"))
-+ *retry = val;
-+ else if (!strcmp(opt, "port"))
-+ nfs_pmap->pm_port = val;
-+ else if (!strcmp(opt, "mountport"))
-+ mnt_pmap->pm_port = val;
-+ else if (!strcmp(opt, "mountprog"))
-+ mnt_pmap->pm_prog = val;
-+ else if (!strcmp(opt, "mountvers"))
-+ mnt_pmap->pm_vers = val;
-+ else if (!strcmp(opt, "nfsprog"))
-+ nfs_pmap->pm_prog = val;
-+ else if (!strcmp(opt, "nfsvers") ||
-+ !strcmp(opt, "vers")) {
-+ nfs_pmap->pm_vers = val;
-+ opt = "nfsvers";
-+#if NFS_MOUNT_VERSION >= 2
-+ } else if (!strcmp(opt, "namlen")) {
-+ if (nfs_mount_version >= 2)
-+ data->namlen = val;
-+ else if (!sloppy)
-+ goto bad_parameter;
- #endif
--#if 0
--#define MOUNTPORT 635
-- /* HJLu wants to remove all traces of the old default port.
-- Are there still people running a mount RPC service on this
-- port without having a portmapper? */
-- if (!p.pm_port)
-- p.pm_port = MOUNTPORT;
--#endif
-- return &p;
-+ } else if (!strcmp(opt, "addr")) {
-+ /* ignore */;
-+ continue;
-+ } else if (!sloppy)
-+ goto bad_parameter;
-+ sprintf(cbuf, "%s=%s,", opt, opteq+1);
-+ } else if (opteq) {
-+ *opteq = '\0';
-+ if (!strcmp(opt, "proto")) {
-+ if (!strcmp(opteq+1, "udp")) {
-+ nfs_pmap->pm_prot = IPPROTO_UDP;
-+#if NFS_MOUNT_VERSION >= 2
-+ data->flags &= ~NFS_MOUNT_TCP;
-+ } else if (!strcmp(opteq+1, "tcp") &&
-+ nfs_mount_version >= 2) {
-+ nfs_pmap->pm_prot = IPPROTO_TCP;
-+ data->flags |= NFS_MOUNT_TCP;
-+#endif
-+ } else if (!sloppy)
-+ goto bad_parameter;
-+ } else if (!strcmp(opt, "mounthost"))
-+ mounthost=xstrndup(opteq+1,
-+ strcspn(opteq+1," \t\n\r,"));
-+ else
-+ goto bad_parameter;
-+ sprintf(cbuf, "%s=%s,", opt, opteq+1);
-+ } else {
-+ int val = 1;
-+ if (!strncmp(opt, "no", 2)) {
-+ val = 0;
-+ opt += 2;
-+ }
-+ if (!strcmp(opt, "bg"))
-+ *bg = val;
-+ else if (!strcmp(opt, "fg"))
-+ *bg = !val;
-+ else if (!strcmp(opt, "soft")) {
-+ data->flags &= ~NFS_MOUNT_SOFT;
-+ if (val)
-+ data->flags |= NFS_MOUNT_SOFT;
-+ } else if (!strcmp(opt, "hard")) {
-+ data->flags &= ~NFS_MOUNT_SOFT;
-+ if (!val)
-+ data->flags |= NFS_MOUNT_SOFT;
-+ } else if (!strcmp(opt, "intr")) {
-+ data->flags &= ~NFS_MOUNT_INTR;
-+ if (val)
-+ data->flags |= NFS_MOUNT_INTR;
-+ } else if (!strcmp(opt, "posix")) {
-+ data->flags &= ~NFS_MOUNT_POSIX;
-+ if (val)
-+ data->flags |= NFS_MOUNT_POSIX;
-+ } else if (!strcmp(opt, "cto")) {
-+ data->flags &= ~NFS_MOUNT_NOCTO;
-+ if (!val)
-+ data->flags |= NFS_MOUNT_NOCTO;
-+ } else if (!strcmp(opt, "ac")) {
-+ data->flags &= ~NFS_MOUNT_NOAC;
-+ if (!val)
-+ data->flags |= NFS_MOUNT_NOAC;
-+#if NFS_MOUNT_VERSION >= 2
-+ } else if (!strcmp(opt, "tcp")) {
-+ data->flags &= ~NFS_MOUNT_TCP;
-+ if (val) {
-+ if (nfs_mount_version < 2)
-+ goto bad_option;
-+ nfs_pmap->pm_prot = IPPROTO_TCP;
-+ data->flags |= NFS_MOUNT_TCP;
-+ } else
-+ nfs_pmap->pm_prot = IPPROTO_UDP;
-+ } else if (!strcmp(opt, "udp")) {
-+ data->flags &= ~NFS_MOUNT_TCP;
-+ if (!val) {
-+ if (nfs_mount_version < 2)
-+ goto bad_option;
-+ nfs_pmap->pm_prot = IPPROTO_TCP;
-+ data->flags |= NFS_MOUNT_TCP;
-+ } else
-+ nfs_pmap->pm_prot = IPPROTO_UDP;
-+#endif
-+#if NFS_MOUNT_VERSION >= 3
-+ } else if (!strcmp(opt, "lock")) {
-+ data->flags &= ~NFS_MOUNT_NONLM;
-+ if (!val) {
-+ if (nfs_mount_version < 3)
-+ goto bad_option;
-+ data->flags |= NFS_MOUNT_NONLM;
-+ }
-+#endif
-+#if NFS_MOUNT_VERSION >= 4
-+ } else if (!strcmp(opt, "broken_suid")) {
-+ data->flags &= ~NFS_MOUNT_BROKEN_SUID;
-+ if (val) {
-+ if (nfs_mount_version < 4)
-+ goto bad_option;
-+ data->flags |= NFS_MOUNT_BROKEN_SUID;
-+ }
-+#endif
-+ } else {
-+ bad_option:
-+ printf(_("Unsupported nfs mount option: "
-+ "%s%s\n"), val ? "" : "no", opt);
-+ goto out_bad;
-+ }
-+ sprintf(cbuf, val ? "%s,":"no%s,", opt);
-+ }
-+ len += strlen(cbuf);
-+ if (len >= opt_size) {
-+ printf(_("mount: excessively long option argument\n"));
-+ goto out_bad;
-+ }
-+ strcat(new_opts, cbuf);
-+ }
-+ /* See if the nfs host = mount host. */
-+ if (mounthost) {
-+ if (!nfs_gethostbyname(mounthost, mnt_saddr))
-+ goto out_bad;
-+ *mnt_server->hostname = mounthost;
-+ }
-+ return 1;
-+ bad_parameter:
-+ printf(_("Bad nfs mount parameter: %s\n"), opt);
-+ out_bad:
-+ return 0;
-+}
-+
-+static inline int
-+nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
-+{
-+ if (nfs_pmap->pm_vers > MAX_NFSPROT) {
-+ fprintf(stderr, _("NFSv%ld not supported!\n"), nfs_pmap->pm_vers);
-+ goto out_bad;
-+ }
-+ if (mnt_pmap->pm_vers > MAX_MNTPROT) {
-+ fprintf(stderr, _("NFS mount v%ld not supported!\n"), mnt_pmap->pm_vers);
-+ goto out_bad;
-+ }
-+ return 1;
-+ out_bad:
-+ return 0;
- }
-
--int nfsmount(const char *spec, const char *node, int *flags,
-- char **extra_opts, char **mount_opts, int *nfs_mount_vers,
-- int running_bg)
-+int
-+nfsmount(const char *spec, const char *node, int *flags,
-+ char **extra_opts, char **mount_opts, int *nfs_mount_vers,
-+ int running_bg)
- {
- static char *prev_bg_host;
- char hostdir[1024];
-- CLIENT *mclient;
- char *hostname, *dirname, *old_opts, *mounthost = NULL;
-- char new_opts[1024];
-- struct timeval total_timeout;
-- enum clnt_stat clnt_stat;
-+ char new_opts[1024], cbuf[20];
- static struct nfs_mount_data data;
-- char *opt, *opteq;
-- int nfs_mount_version;
- int val;
-- struct hostent *hp;
-- struct sockaddr_in server_addr;
-- struct sockaddr_in mount_server_addr;
-- struct pmap *pm_mnt;
-- int msock, fsock;
-- struct timeval retry_timeout;
-- union {
-- struct fhstatus nfsv2;
-- struct mountres3 nfsv3;
-- } status;
-+
-+ clnt_addr_t mnt_server = { &mounthost, };
-+ clnt_addr_t nfs_server = { &hostname, };
-+ struct sockaddr_in *nfs_saddr = &nfs_server.saddr;
-+ struct pmap *mnt_pmap = &mnt_server.pmap,
-+ *nfs_pmap = &nfs_server.pmap;
-+ struct pmap save_mnt, save_nfs;
-+
-+ int fsock;
-+
-+ mntres_t mntres;
-+
- struct stat statbuf;
-- char *s;
-- int port, mountport, proto, bg, soft, intr;
-- int posix, nocto, noac, nolock, broken_suid;
-- int retry, tcp;
-- int mountprog, mountvers, nfsprog, nfsvers;
-+ char *s, *p;
-+ int bg, retry;
- int retval;
- time_t t;
- time_t prevt;
-@@ -231,8 +756,7 @@ int nfsmount(const char *spec, const cha
- nfs_mount_version = *nfs_mount_vers;
-
- retval = EX_FAIL;
-- msock = fsock = -1;
-- mclient = NULL;
-+ fsock = -1;
- if (strlen(spec) >= sizeof(hostdir)) {
- fprintf(stderr, _("mount: "
- "excessively long host:dir argument\n"));
-@@ -258,49 +782,23 @@ int nfsmount(const char *spec, const cha
- goto fail;
- }
-
-- server_addr.sin_family = AF_INET;
--#ifdef HAVE_inet_aton
-- if (!inet_aton(hostname, &server_addr.sin_addr))
--#endif
-- {
-- if ((hp = gethostbyname(hostname)) == NULL) {
-- fprintf(stderr, _("mount: can't get address for %s\n"),
-- hostname);
-- goto fail;
-- } else {
-- if (hp->h_length > sizeof(struct in_addr)) {
-- fprintf(stderr,
-- _("mount: got bad hp->h_length\n"));
-- hp->h_length = sizeof(struct in_addr);
-- }
-- memcpy(&server_addr.sin_addr,
-- hp->h_addr, hp->h_length);
-- }
-- }
--
-- memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
-+ if (!nfs_gethostbyname(hostname, nfs_saddr))
-+ goto fail;
-+ mounthost = hostname;
-+ memcpy (&mnt_server.saddr, nfs_saddr, sizeof (mnt_server.saddr));
-
- /* add IP address to mtab options for use when unmounting */
-
-- s = inet_ntoa(server_addr.sin_addr);
-+ s = inet_ntoa(nfs_saddr->sin_addr);
- old_opts = *extra_opts;
- if (!old_opts)
- old_opts = "";
-- if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
-- fprintf(stderr, _("mount: "
-- "excessively long option argument\n"));
-- goto fail;
-- }
-- sprintf(new_opts, "%s%saddr=%s",
-- old_opts, *old_opts ? "," : "", s);
-- *extra_opts = xstrdup(new_opts);
-
- /* Set default options.
- * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
- * let the kernel decide.
- * timeo is filled in after we know whether it'll be TCP or UDP. */
- memset(&data, 0, sizeof(data));
-- data.retrans = 3;
- data.acregmin = 3;
- data.acregmax = 60;
- data.acdirmin = 30;
-@@ -310,167 +808,21 @@ int nfsmount(const char *spec, const cha
- #endif
-
- bg = 0;
-- soft = 0;
-- intr = 0;
-- posix = 0;
-- nocto = 0;
-- nolock = 0;
-- broken_suid = 0;
-- noac = 0;
- retry = 10000; /* 10000 minutes ~ 1 week */
-- tcp = 0;
-
-- mountprog = MOUNTPROG;
-- mountvers = 0;
-- port = 0;
-- mountport = 0;
-- nfsprog = NFS_PROGRAM;
-- nfsvers = 0;
-+ memset(mnt_pmap, 0, sizeof(*mnt_pmap));
-+ mnt_pmap->pm_prog = MOUNTPROG;
-+ memset(nfs_pmap, 0, sizeof(*nfs_pmap));
-+ nfs_pmap->pm_prog = NFS_PROGRAM;
-
- /* parse options */
-+ new_opts[0] = 0;
-+ if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
-+ new_opts, sizeof(new_opts)))
-+ goto fail;
-+ if (!nfsmnt_check_compat(nfs_pmap, mnt_pmap))
-+ goto fail;
-
-- for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
-- if ((opteq = strchr(opt, '='))) {
-- val = atoi(opteq + 1);
-- *opteq = '\0';
-- if (!strcmp(opt, "rsize"))
-- data.rsize = val;
-- else if (!strcmp(opt, "wsize"))
-- data.wsize = val;
-- else if (!strcmp(opt, "timeo"))
-- data.timeo = val;
-- else if (!strcmp(opt, "retrans"))
-- data.retrans = val;
-- else if (!strcmp(opt, "acregmin"))
-- data.acregmin = val;
-- else if (!strcmp(opt, "acregmax"))
-- data.acregmax = val;
-- else if (!strcmp(opt, "acdirmin"))
-- data.acdirmin = val;
-- else if (!strcmp(opt, "acdirmax"))
-- data.acdirmax = val;
-- else if (!strcmp(opt, "actimeo")) {
-- data.acregmin = val;
-- data.acregmax = val;
-- data.acdirmin = val;
-- data.acdirmax = val;
-- }
-- else if (!strcmp(opt, "retry"))
-- retry = val;
-- else if (!strcmp(opt, "port"))
-- port = val;
-- else if (!strcmp(opt, "mountport"))
-- mountport = val;
-- else if (!strcmp(opt, "mounthost"))
-- mounthost=xstrndup(opteq+1,
-- strcspn(opteq+1," \t\n\r,"));
-- else if (!strcmp(opt, "mountprog"))
-- mountprog = val;
-- else if (!strcmp(opt, "mountvers"))
-- mountvers = val;
-- else if (!strcmp(opt, "nfsprog"))
-- nfsprog = val;
-- else if (!strcmp(opt, "nfsvers") ||
-- !strcmp(opt, "vers"))
-- nfsvers = val;
-- else if (!strcmp(opt, "proto")) {
-- if (!strncmp(opteq+1, "tcp", 3))
-- tcp = 1;
-- else if (!strncmp(opteq+1, "udp", 3))
-- tcp = 0;
-- else
-- printf(_("Warning: Unrecognized proto= option.\n"));
-- } else if (!strcmp(opt, "namlen")) {
--#if NFS_MOUNT_VERSION >= 2
-- if (nfs_mount_version >= 2)
-- data.namlen = val;
-- else
--#endif
-- printf(_("Warning: Option namlen is not supported.\n"));
-- } else if (!strcmp(opt, "addr")) {
-- /* ignore */;
-- } else {
-- printf(_("unknown nfs mount parameter: "
-- "%s=%d\n"), opt, val);
-- goto fail;
-- }
-- } else {
-- val = 1;
-- if (!strncmp(opt, "no", 2)) {
-- val = 0;
-- opt += 2;
-- }
-- if (!strcmp(opt, "bg"))
-- bg = val;
-- else if (!strcmp(opt, "fg"))
-- bg = !val;
-- else if (!strcmp(opt, "soft"))
-- soft = val;
-- else if (!strcmp(opt, "hard"))
-- soft = !val;
-- else if (!strcmp(opt, "intr"))
-- intr = val;
-- else if (!strcmp(opt, "posix"))
-- posix = val;
-- else if (!strcmp(opt, "cto"))
-- nocto = !val;
-- else if (!strcmp(opt, "ac"))
-- noac = !val;
-- else if (!strcmp(opt, "tcp"))
-- tcp = val;
-- else if (!strcmp(opt, "udp"))
-- tcp = !val;
-- else if (!strcmp(opt, "lock")) {
-- if (nfs_mount_version >= 3)
-- nolock = !val;
-- else
-- printf(_("Warning: option nolock is not supported.\n"));
-- } else if (!strcmp(opt, "broken_suid")) {
-- broken_suid = val;
-- } else {
-- if (!sloppy) {
-- printf(_("unknown nfs mount option: "
-- "%s%s\n"), val ? "" : "no", opt);
-- goto fail;
-- }
-- }
-- }
-- }
-- proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
--
-- data.flags = (soft ? NFS_MOUNT_SOFT : 0)
-- | (intr ? NFS_MOUNT_INTR : 0)
-- | (posix ? NFS_MOUNT_POSIX : 0)
-- | (nocto ? NFS_MOUNT_NOCTO : 0)
-- | (noac ? NFS_MOUNT_NOAC : 0);
--#if NFS_MOUNT_VERSION >= 2
-- if (nfs_mount_version >= 2)
-- data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
--#endif
--#if NFS_MOUNT_VERSION >= 3
-- if (nfs_mount_version >= 3)
-- data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
--#endif
--#if NFS_MOUNT_VERSION >= 4
-- if (nfs_mount_version >= 4)
-- data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
--#endif
-- if (nfsvers > MAX_NFSPROT) {
-- fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
-- return 0;
-- }
-- if (mountvers > MAX_NFSPROT) {
-- fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
-- return 0;
-- }
-- if (nfsvers && !mountvers)
-- mountvers = (nfsvers < 3) ? 1 : nfsvers;
-- if (nfsvers && nfsvers < mountvers)
-- mountvers = nfsvers;
--
-- /* Adjust options if none specified */
-- if (!data.timeo)
-- data.timeo = tcp ? 70 : 7;
-
- #ifdef NFS_MOUNT_DEBUG
- printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-@@ -478,9 +830,10 @@ int nfsmount(const char *spec, const cha
- printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
- data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
- printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
-- port, bg, retry, data.flags);
-+ nfs_pmap->pm_port, bg, retry, data.flags);
- printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
-- mountprog, mountvers, nfsprog, nfsvers);
-+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
-+ nfs_pmap->pm_prog, nfs_pmap->pm_vers);
- printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
- (data.flags & NFS_MOUNT_SOFT) != 0,
- (data.flags & NFS_MOUNT_INTR) != 0,
-@@ -497,7 +850,7 @@ int nfsmount(const char *spec, const cha
- *mount_opts = (char *) &data;
-
- if (*flags & MS_REMOUNT)
-- return 0;
-+ goto out_ok;
-
- /*
- * If the previous mount operation on the same host was
-@@ -512,28 +865,6 @@ int nfsmount(const char *spec, const cha
- }
-
- /* create mount deamon client */
-- /* See if the nfs host = mount host. */
-- if (mounthost) {
-- if (mounthost[0] >= '0' && mounthost[0] <= '9') {
-- mount_server_addr.sin_family = AF_INET;
-- mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
-- } else {
-- if ((hp = gethostbyname(mounthost)) == NULL) {
-- fprintf(stderr, _("mount: can't get address for %s\n"),
-- mounthost);
-- goto fail;
-- } else {
-- if (hp->h_length > sizeof(struct in_addr)) {
-- fprintf(stderr,
-- _("mount: got bad hp->h_length?\n"));
-- hp->h_length = sizeof(struct in_addr);
-- }
-- mount_server_addr.sin_family = AF_INET;
-- memcpy(&mount_server_addr.sin_addr,
-- hp->h_addr, hp->h_length);
-- }
-- }
-- }
-
- /*
- * The following loop implements the mount retries. On the first
-@@ -551,15 +882,13 @@ int nfsmount(const char *spec, const cha
- *
- * Only the first error message will be displayed.
- */
-- retry_timeout.tv_sec = 3;
-- retry_timeout.tv_usec = 0;
-- total_timeout.tv_sec = 20;
-- total_timeout.tv_usec = 0;
- timeout = time(NULL) + 60 * retry;
- prevt = 0;
- t = 30;
- val = 1;
-
-+ memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
-+ memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
- for (;;) {
- if (bg && stat(node, &statbuf) == -1) {
- /* no mount point yet - sleep */
-@@ -570,89 +899,18 @@ int nfsmount(const char *spec, const cha
- val = 30;
- }
- } else {
-+ int stat;
- /* be careful not to use too many CPU cycles */
- if (t - prevt < 30)
- sleep(30);
-
-- pm_mnt = get_mountport(&mount_server_addr,
-- mountprog,
-- mountvers,
-- proto,
-- mountport,
-- nfs_mount_version);
--
-- /* contact the mount daemon via TCP */
-- mount_server_addr.sin_port = htons(pm_mnt->pm_port);
-- msock = RPC_ANYSOCK;
--
-- switch (pm_mnt->pm_prot) {
-- case IPPROTO_UDP:
-- mclient = clntudp_create(&mount_server_addr,
-- pm_mnt->pm_prog,
-- pm_mnt->pm_vers,
-- retry_timeout,
-- &msock);
-- if (mclient)
-- break;
-- mount_server_addr.sin_port =
-- htons(pm_mnt->pm_port);
-- msock = RPC_ANYSOCK;
-- case IPPROTO_TCP:
-- mclient = clnttcp_create(&mount_server_addr,
-- pm_mnt->pm_prog,
-- pm_mnt->pm_vers,
-- &msock, 0, 0);
-+ stat = nfs_call_mount(&mnt_server, &nfs_server,
-+ &dirname, &mntres,
-+ !running_bg && prevt == 0);
-+ if (stat)
- break;
-- default:
-- mclient = 0;
-- }
--
-- if (mclient) {
-- /* try to mount hostname:dirname */
-- mclient->cl_auth = authunix_create_default();
--
-- /* make pointers in xdr_mountres3 NULL so
-- * that xdr_array allocates memory for us
-- */
-- memset(&status, 0, sizeof(status));
--
-- if (pm_mnt->pm_vers == 3)
-- clnt_stat = clnt_call(mclient,
-- MOUNTPROC3_MNT,
-- (xdrproc_t) xdr_dirpath,
-- (caddr_t) &dirname,
-- (xdrproc_t) xdr_mountres3,
-- (caddr_t) &status,
-- total_timeout);
-- else
-- clnt_stat = clnt_call(mclient,
-- MOUNTPROC_MNT,
-- (xdrproc_t) xdr_dirpath,
-- (caddr_t) &dirname,
-- (xdrproc_t) xdr_fhstatus,
-- (caddr_t) &status,
-- total_timeout);
--
-- if (clnt_stat == RPC_SUCCESS)
-- break; /* we're done */
--#if 0
-- /* errno? who sets errno? */
-- /* this fragment breaks bg mounting */
-- if (errno != ECONNREFUSED) {
-- clnt_perror(mclient, "mount");
-- goto fail; /* don't retry */
-- }
--#endif
-- if (!running_bg && prevt == 0)
-- clnt_perror(mclient, "mount");
-- auth_destroy(mclient->cl_auth);
-- clnt_destroy(mclient);
-- mclient = 0;
-- close(msock);
-- } else {
-- if (!running_bg && prevt == 0)
-- clnt_pcreateerror("mount");
-- }
-+ memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
-+ memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
- prevt = t;
- }
-
-@@ -668,36 +926,35 @@ int nfsmount(const char *spec, const cha
- if (t >= timeout)
- goto fail;
- }
-- nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
-
-- if (nfsvers == 2) {
-- if (status.nfsv2.fhs_status != 0) {
-+ if (nfs_pmap->pm_vers == 2) {
-+ if (mntres.nfsv2.fhs_status != 0) {
- fprintf(stderr,
-- "mount: %s:%s failed, reason given by server: %s\n",
-+ _("mount: %s:%s failed, reason given by server: %s\n"),
- hostname, dirname,
-- nfs_strerror(status.nfsv2.fhs_status));
-+ nfs_strerror(mntres.nfsv2.fhs_status));
- goto fail;
- }
- memcpy(data.root.data,
-- (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
-+ (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
- NFS_FHSIZE);
- #if NFS_MOUNT_VERSION >= 4
- data.root.size = NFS_FHSIZE;
- memcpy(data.old_root.data,
-- (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
-+ (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
- NFS_FHSIZE);
- #endif
- } else {
- #if NFS_MOUNT_VERSION >= 4
- fhandle3 *fhandle;
-- if (status.nfsv3.fhs_status != 0) {
-+ if (mntres.nfsv3.fhs_status != 0) {
- fprintf(stderr,
-- "mount: %s:%s failed, reason given by server: %s\n",
-+ _("mount: %s:%s failed, reason given by server: %s\n"),
- hostname, dirname,
-- nfs_strerror(status.nfsv3.fhs_status));
-+ nfs_strerror(mntres.nfsv3.fhs_status));
- goto fail;
- }
-- fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
-+ fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle;
- memset(data.old_root.data, 0, NFS_FHSIZE);
- memset(&data.root, 0, sizeof(data.root));
- data.root.size = fhandle->fhandle3_len;
-@@ -711,13 +968,9 @@ int nfsmount(const char *spec, const cha
-
- /* create nfs socket for kernel */
-
-- if (tcp) {
-- if (nfs_mount_version < 3) {
-- printf(_("NFS over TCP is not supported.\n"));
-- goto fail;
-- }
-+ if (nfs_pmap->pm_prot == IPPROTO_TCP)
- fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-- } else
-+ else
- fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (fsock < 0) {
- perror(_("nfs socket"));
-@@ -727,72 +980,162 @@ int nfsmount(const char *spec, const cha
- perror(_("nfs bindresvport"));
- goto fail;
- }
-- if (port == 0) {
-- server_addr.sin_port = PMAPPORT;
-- port = pmap_getport(&server_addr, nfsprog, nfsvers,
-- tcp ? IPPROTO_TCP : IPPROTO_UDP);
--#if 1
-- /* Here we check to see if user is mounting with the
-- * tcp option. If so, and if the portmap returns a
-- * '0' for port (service unavailable), we then exit,
-- * notifying the user, rather than hanging up mount.
-- */
-- if (port == 0 && tcp == 1) {
-- perror(_("nfs server reported service unavailable"));
-- goto fail;
-- }
--#endif
--
-- if (port == 0)
-- port = NFS_PORT;
- #ifdef NFS_MOUNT_DEBUG
-- else
-- printf(_("used portmapper to find NFS port\n"));
-+ printf(_("using port %d for nfs deamon\n"), nfs_pmap->pm_port);
- #endif
-- }
--#ifdef NFS_MOUNT_DEBUG
-- printf(_("using port %d for nfs deamon\n"), port);
--#endif
-- server_addr.sin_port = htons(port);
-+ nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
- /*
- * connect() the socket for kernels 1.3.10 and below only,
- * to avoid problems with multihomed hosts.
- * --Swen
- */
- if (linux_version_code() <= 66314
-- && connect(fsock, (struct sockaddr *) &server_addr,
-- sizeof (server_addr)) < 0) {
-+ && connect(fsock, (struct sockaddr *) nfs_saddr,
-+ sizeof (*nfs_saddr)) < 0) {
- perror(_("nfs connect"));
- goto fail;
- }
-
-+#if NFS_MOUNT_VERSION >= 2
-+ if (nfs_pmap->pm_prot == IPPROTO_TCP)
-+ data.flags |= NFS_MOUNT_TCP;
-+ else
-+ data.flags &= ~NFS_MOUNT_TCP;
-+#endif
-+
- /* prepare data structure for kernel */
-
- data.fd = fsock;
-- memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
-+ memcpy((char *) &data.addr, (char *) nfs_saddr, sizeof(data.addr));
- strncpy(data.hostname, hostname, sizeof(data.hostname));
-
-- /* clean up */
-+ out_ok:
-+ /* Ensure we have enough padding for the following strcat()s */
-+ if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) {
-+ fprintf(stderr, _("mount: "
-+ "excessively long option argument\n"));
-+ goto fail;
-+ }
-
-- auth_destroy(mclient->cl_auth);
-- clnt_destroy(mclient);
-- close(msock);
-+ sprintf(cbuf, "addr=%s", s);
-+ strcat(new_opts, cbuf);
-+
-+ *extra_opts = xstrdup(new_opts);
- return 0;
-
- /* abort */
--
- fail:
-- if (msock != -1) {
-- if (mclient) {
-- auth_destroy(mclient->cl_auth);
-- clnt_destroy(mclient);
-- }
-- close(msock);
-- }
- if (fsock != -1)
- close(fsock);
- return retval;
--}
-+}
-+
-+static inline enum clnt_stat
-+nfs3_umount(dirpath *argp, CLIENT *clnt)
-+{
-+ static char clnt_res;
-+ memset (&clnt_res, 0, sizeof(clnt_res));
-+ return clnt_call(clnt, MOUNTPROC_UMNT,
-+ (xdrproc_t) xdr_dirpath, (caddr_t)argp,
-+ (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
-+ TIMEOUT);
-+}
-+
-+static inline enum clnt_stat
-+nfs2_umount(dirpath *argp, CLIENT *clnt)
-+{
-+ static char clnt_res;
-+ memset (&clnt_res, 0, sizeof(clnt_res));
-+ return clnt_call(clnt, MOUNTPROC_UMNT,
-+ (xdrproc_t) xdr_dirpath, (caddr_t)argp,
-+ (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
-+ TIMEOUT);
-+}
-+
-+static int
-+nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
-+{
-+ CLIENT *clnt;
-+ enum clnt_stat res = 0;
-+ int msock;
-+
-+ clnt = mnt_openclnt(mnt_server, &msock, 1);
-+ if (!clnt)
-+ goto out_bad;
-+ switch (mnt_server->pmap.pm_vers) {
-+ case 3:
-+ res = nfs3_umount(argp, clnt);
-+ break;
-+ case 2:
-+ case 1:
-+ res = nfs2_umount(argp, clnt);
-+ break;
-+ default:
-+ }
-+ mnt_closeclnt(clnt, msock);
-+ if (res == RPC_SUCCESS)
-+ return 1;
-+ out_bad:
-+ return 0;
-+}
-+
-+int
-+nfsumount(const char *spec, const char *opts)
-+{
-+ char *hostname;
-+ char *dirname;
-+ clnt_addr_t mnt_server = { &hostname, };
-+ struct pmap *pmap = &mnt_server.pmap;
-+ char *p;
-+
-+ nfs_mount_version = find_kernel_nfs_mount_version();
-+ if (spec == NULL || (p = strchr(spec,':')) == NULL)
-+ goto out_bad;
-+ hostname = xstrndup(spec, p-spec);
-+ dirname = xstrdup(p+1);
-+#ifdef NFS_MOUNT_DEBUG
-+ printf(_("host: %s, directory: %s\n"), hostname, dirname);
-+#endif
-+
-+ if (opts && (p = strstr(opts, "addr="))) {
-+ char *q;
-+
-+ free(hostname);
-+ p += 5;
-+ q = p;
-+ while (*q && *q != ',') q++;
-+ hostname = xstrndup(p,q-p);
-+ }
-+
-+ if (opts && (p = strstr(opts, "mounthost="))) {
-+ char *q;
-+
-+ free(hostname);
-+ p += 10;
-+ q = p;
-+ while (*q && *q != ',') q++;
-+ hostname = xstrndup(p,q-p);
-+ }
-+
-+ pmap->pm_prog = MOUNTPROG;
-+ pmap->pm_vers = MOUNTVERS;
-+ if (opts && (p = strstr(opts, "mountprog=")) && isdigit(*(p+10)))
-+ pmap->pm_prog = atoi(p+10);
-+ if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10)))
-+ pmap->pm_port = atoi(p+10);
-+ if (opts && (p = strstr(opts, "nfsvers=")) && isdigit(*(p+8)))
-+ pmap->pm_vers = nfsvers_to_mnt(atoi(p+8));
-+ if (opts && (p = strstr(opts, "mountvers=")) && isdigit(*(p+10)))
-+ pmap->pm_vers = atoi(p+10);
-+
-+ if (!nfs_gethostbyname(hostname, &mnt_server.saddr))
-+ goto out_bad;
-+ if (!probe_mntport(&mnt_server))
-+ goto out_bad;
-+ return nfs_call_umount(&mnt_server, &dirname);
-+ out_bad:
-+ return 0;
-+}
-
- /*
- * We need to translate between nfs status return values and
-diff -puN mount/sundries.h~nfs mount/sundries.h
---- util-linux-2.12/mount/sundries.h~nfs 2004-10-13 13:51:44.000000000 -0400
-+++ util-linux-2.12-bfields/mount/sundries.h 2004-10-13 14:13:30.000000000 -0400
-@@ -37,6 +37,7 @@ void die (int errcode, const char *fmt,
- #ifdef HAVE_NFS
- int nfsmount (const char *spec, const char *node, int *flags,
- char **orig_opts, char **opt_args, int *version, int running_bg);
-+int nfsumount(const char *spec, const char *opts);
- #endif
-
- /* exit status - bits below are ORed */
-diff -puN mount/umount.c~nfs mount/umount.c
---- util-linux-2.12/mount/umount.c~nfs 2004-10-13 13:51:44.000000000 -0400
-+++ util-linux-2.12-bfields/mount/umount.c 2004-10-13 14:13:30.000000000 -0400
-@@ -122,7 +122,7 @@ check_special_umountprog() {
- }
- #endif
-
--#ifdef HAVE_NFS
-+#if 0
- static int xdr_dir(XDR *xdrsp, char *dirp)
- {
- return (xdr_string(xdrsp, &dirp, MNTPATHLEN));
-@@ -265,7 +265,7 @@ umount_one (const char *spec, const char
- /* Ignore any RPC errors, so that you can umount the filesystem
- if the server is down. */
- if (strcasecmp(type, "nfs") == 0)
-- nfs_umount_rpc_call(spec, opts);
-+ nfsumount(spec, opts);
- #endif
-
- umnt_err = umnt_err2 = 0;
-_
+++ /dev/null
-
-Add basic nfsv4 support
-
----
-
- util-linux-2.12-bfields/mount/Makefile | 2
- util-linux-2.12-bfields/mount/fstab.5 | 1
- util-linux-2.12-bfields/mount/mount.8 | 75 ++++++
- util-linux-2.12-bfields/mount/mount.c | 13 +
- util-linux-2.12-bfields/mount/nfs.5 | 200 +++++++++++++++++
- util-linux-2.12-bfields/mount/nfs4_mount.h | 82 +++++++
- util-linux-2.12-bfields/mount/nfs4mount.c | 335 +++++++++++++++++++++++++++++
- util-linux-2.12-bfields/mount/nfsmount.c | 5
- util-linux-2.12-bfields/mount/sundries.h | 2
- util-linux-2.12-bfields/mount/umount.c | 3
- 10 files changed, 710 insertions(+), 8 deletions(-)
-
-diff -puN mount/fstab.5~base-nfsv4 mount/fstab.5
---- util-linux-2.12/mount/fstab.5~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/fstab.5 2004-10-13 13:51:50.000000000 -0400
-@@ -115,6 +115,7 @@ of filesystem types, such as
- .IR msdos ,
- .IR ncpfs ,
- .IR nfs ,
-+.IR nfs4 ,
- .IR ntfs ,
- .IR proc ,
- .IR qnx4 ,
-diff -puN mount/Makefile~base-nfsv4 mount/Makefile
---- util-linux-2.12/mount/Makefile~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/Makefile 2004-10-13 13:51:50.000000000 -0400
-@@ -31,7 +31,7 @@
-
- LO_OBJS = lomount.o $(LIB)/xstrncpy.o
- CRYPT_OBJS = cryptsetup.o -lcryptsetup
--NFS_OBJS = nfsmount.o nfsmount_xdr.o
-+NFS_OBJS = nfsmount.o nfsmount_xdr.o nfs4mount.o
- GEN_FILES = nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
-
- all: $(PROGS)
-diff -puN mount/mount.8~base-nfsv4 mount/mount.8
---- util-linux-2.12/mount/mount.8~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/mount.8 2004-10-13 13:51:50.000000000 -0400
-@@ -370,6 +370,7 @@ currently supported are:
- .IR msdos ,
- .IR ncpfs ,
- .IR nfs ,
-+.IR nfs4 ,
- .IR ntfs ,
- .IR proc ,
- .IR qnx4 ,
-@@ -403,7 +404,7 @@ For most types all the
- program has to do is issue a simple
- .IR mount (2)
- system call, and no detailed knowledge of the filesystem type is required.
--For a few types however (like nfs, smbfs, ncpfs) ad hoc code is
-+For a few types however (like nfs, nfs4, smbfs, ncpfs) ad hoc code is
- necessary. The nfs ad hoc code is built in, but smbfs and ncpfs
- have a separate mount program. In order to make it possible to
- treat all types in a uniform way, mount will execute the program
-@@ -451,9 +452,10 @@ or, if that does not exist,
- All of the filesystem types listed there will be tried,
- except for those that are labeled "nodev" (e.g.,
- .IR devpts ,
--.I proc
-+.IR proc ,
-+.IR nfs ,
- and
--.IR nfs ).
-+.IR nfs4 ).
- If
- .I /etc/filesystems
- ends in a line with a single * only, mount will read
-@@ -1243,6 +1245,73 @@ Usually it just causes lots of trouble.
- .B nolock
- Do not use locking. Do not start lockd.
-
-+.SH "Mount options for nfs4"
-+Instead of a textual option string, parsed by the kernel, the
-+.I nfs4
-+file system expects a binary argument of type
-+.IR "struct nfs4_mount_data" .
-+The program
-+.B mount
-+itself parses the following options of the form `tag=value',
-+and puts them in the structure mentioned:
-+.BI rsize= n,
-+.BI wsize= n,
-+.BI timeo= n,
-+.BI retrans= n,
-+.BI acregmin= n,
-+.BI acregmax= n,
-+.BI acdirmin= n,
-+.BI acdirmax= n,
-+.BI actimeo= n,
-+.BI retry= n,
-+.BI port= n,
-+.BI proto= n,
-+.BI clientaddr= n,
-+.BI sec= n.
-+The option
-+.BI addr= n
-+is accepted but ignored.
-+Also the following Boolean options, possibly preceded by
-+.B no
-+are recognized:
-+.BR bg ,
-+.BR fg ,
-+.BR soft ,
-+.BR hard ,
-+.BR intr ,
-+.BR cto ,
-+.BR ac ,
-+For details, see
-+.BR nfs (5).
-+
-+Especially useful options include
-+.TP
-+.B rsize=32768,wsize=32768
-+This will make your NFS connection faster than with the default
-+buffer size of 4096.
-+.TP
-+.B hard
-+The program accessing a file on a NFS mounted file system will hang
-+when the server crashes. The process cannot be interrupted or
-+killed unless you also specify
-+.BR intr .
-+When the NFS server is back online the program will continue undisturbed
-+from where it was. This is probably what you want.
-+.TP
-+.B soft
-+This option allows the kernel to time out if the NFS server is not
-+responding for some time. The time can be
-+specified with
-+.BR timeo=time .
-+This timeout value is expressed in tenths of a second.
-+The
-+.BR soft
-+option might be useful if your NFS server sometimes doesn't respond
-+or will be rebooted while some process tries to get a file from the server.
-+Avoid using this option with
-+.BR proto=udp
-+or with a short timeout.
-+
- .SH "Mount options for ntfs"
- .TP
- .BI iocharset= name
-diff -puN mount/mount.c~base-nfsv4 mount/mount.c
---- util-linux-2.12/mount/mount.c~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/mount.c 2004-10-13 13:51:50.000000000 -0400
-@@ -821,6 +821,19 @@ retry_nfs:
- "without support for the type `nfs'"));
- #endif
- }
-+#ifdef HAVE_NFS
-+ /*
-+ * NFSv4 support
-+ */
-+ if (!fake && types && streq (types, "nfs4")) {
-+ mnt_err = nfs4mount(spec, node, &flags, &extra_opts, &mount_opts, bg);
-+ if (mnt_err)
-+ return mnt_err;
-+#else
-+ die (EX_SOFTWARE, _("mount: this version was compiled "
-+ "without support for the type `nfs4'"));
-+#endif
-+ }
-
- block_signals (SIG_BLOCK);
-
-diff -puN /dev/null mount/nfs4mount.c
---- /dev/null 2004-08-19 17:44:20.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs4mount.c 2004-10-13 13:52:38.000000000 -0400
-@@ -0,0 +1,335 @@
-+/*
-+ * nfs4mount.c -- Linux NFS mount
-+ * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * Note: this file based on the original nfsmount.c
-+ */
-+
-+#include "../defines.h" /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
-+
-+#include <linux/posix_types.h>
-+#include <asm/posix_types.h>
-+#undef __FD_CLR
-+#undef __FD_SET
-+#undef __FD_ISSET
-+#undef __FD_ZERO
-+
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <netdb.h>
-+#include <time.h>
-+#include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/utsname.h>
-+#include <sys/stat.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+
-+#include "sundries.h"
-+
-+#include "mount_constants.h"
-+#include "nfs4_mount.h"
-+
-+#include "nls.h"
-+
-+#ifndef NFS_PORT
-+#define NFS_PORT 2049
-+#endif
-+
-+static int parse_devname(char *hostdir, char **hostname, char **dirname)
-+{
-+ char *s;
-+
-+ if (!(s = strchr(hostdir, ':'))) {
-+ fprintf(stderr,
-+ _("mount: "
-+ "directory to mount not in host:dir format\n"));
-+ return -1;
-+ }
-+ *hostname = hostdir;
-+ *dirname = s + 1;
-+ *s = '\0';
-+ /* Ignore all but first hostname in replicated mounts
-+ until they can be fully supported. (mack@sgi.com) */
-+ if ((s = strchr(hostdir, ','))) {
-+ *s = '\0';
-+ fprintf(stderr,
-+ _("mount: warning: "
-+ "multiple hostnames not supported\n"));
-+ }
-+ return 0;
-+}
-+
-+static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
-+{
-+ struct hostent *hp;
-+ addr->sin_family = AF_INET;
-+
-+ if (inet_aton(hostname, &addr->sin_addr))
-+ return 0;
-+ if ((hp = gethostbyname(hostname)) == NULL) {
-+ fprintf(stderr, _("mount: can't get address for %s\n"),
-+ hostname);
-+ return -1;
-+ }
-+ if (hp->h_length > sizeof(struct in_addr)) {
-+ fprintf(stderr,
-+ _("mount: got bad hp->h_length\n"));
-+ hp->h_length = sizeof(struct in_addr);
-+ }
-+ memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
-+ return 0;
-+}
-+
-+static int get_my_ipv4addr(char *ip_addr, int len)
-+{
-+ char myname[1024];
-+ struct sockaddr_in myaddr;
-+
-+ if (gethostname(myname, sizeof(myname))) {
-+ fprintf(stderr, _("mount: can't determine client address\n"));
-+ return -1;
-+ }
-+ if (fill_ipv4_sockaddr(myname, &myaddr))
-+ return -1;
-+ snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr));
-+ ip_addr[len-1] = '\0';
-+ return 0;
-+}
-+
-+int nfs4mount(const char *spec, const char *node, int *flags,
-+ char **extra_opts, char **mount_opts,
-+ int running_bg)
-+{
-+ static struct nfs4_mount_data data;
-+ static char hostdir[1024];
-+ static char ip_addr[16] = "127.0.0.1";
-+ static struct sockaddr_in server_addr;
-+ static int pseudoflavour = 0;
-+
-+ char *hostname, *dirname, *old_opts;
-+ char new_opts[1024];
-+ char *opt, *opteq;
-+ char *s;
-+ int val;
-+ int bg, soft, intr;
-+ int nocto, noac;
-+ int retry;
-+ int retval;
-+
-+ retval = EX_FAIL;
-+ if (strlen(spec) >= sizeof(hostdir)) {
-+ fprintf(stderr, _("mount: "
-+ "excessively long host:dir argument\n"));
-+ goto fail;
-+ }
-+ strcpy(hostdir, spec);
-+ if (parse_devname(hostdir, &hostname, &dirname))
-+ goto fail;
-+
-+ if (fill_ipv4_sockaddr(hostname, &server_addr))
-+ goto fail;
-+ if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
-+ goto fail;
-+
-+ /* add IP address to mtab options for use when unmounting */
-+ s = inet_ntoa(server_addr.sin_addr);
-+ old_opts = *extra_opts;
-+ if (!old_opts)
-+ old_opts = "";
-+ if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
-+ fprintf(stderr, _("mount: "
-+ "excessively long option argument\n"));
-+ goto fail;
-+ }
-+ snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
-+ old_opts, *old_opts ? "," : "", s);
-+ *extra_opts = xstrdup(new_opts);
-+
-+ /* Set default options.
-+ * rsize/wsize and timeo are left 0 in order to
-+ * let the kernel decide.
-+ */
-+ memset(&data, 0, sizeof(data));
-+ data.retrans = 3;
-+ data.acregmin = 3;
-+ data.acregmax = 60;
-+ data.acdirmin = 30;
-+ data.acdirmax = 60;
-+ data.proto = IPPROTO_TCP;
-+
-+ bg = 0;
-+ soft = 0;
-+ intr = 0;
-+ nocto = 0;
-+ noac = 0;
-+ retry = 10000; /* 10000 minutes ~ 1 week */
-+
-+ /*
-+ * NFSv4 specifies that the default port should be 2049
-+ */
-+ server_addr.sin_port = htons(NFS_PORT);
-+
-+ /* parse options */
-+
-+ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
-+ if ((opteq = strchr(opt, '='))) {
-+ val = atoi(opteq + 1);
-+ *opteq = '\0';
-+ if (!strcmp(opt, "rsize"))
-+ data.rsize = val;
-+ else if (!strcmp(opt, "wsize"))
-+ data.wsize = val;
-+ else if (!strcmp(opt, "timeo"))
-+ data.timeo = val;
-+ else if (!strcmp(opt, "retrans"))
-+ data.retrans = val;
-+ else if (!strcmp(opt, "acregmin"))
-+ data.acregmin = val;
-+ else if (!strcmp(opt, "acregmax"))
-+ data.acregmax = val;
-+ else if (!strcmp(opt, "acdirmin"))
-+ data.acdirmin = val;
-+ else if (!strcmp(opt, "acdirmax"))
-+ data.acdirmax = val;
-+ else if (!strcmp(opt, "actimeo")) {
-+ data.acregmin = val;
-+ data.acregmax = val;
-+ data.acdirmin = val;
-+ data.acdirmax = val;
-+ }
-+ else if (!strcmp(opt, "retry"))
-+ retry = val;
-+ else if (!strcmp(opt, "port"))
-+ server_addr.sin_port = htons(val);
-+ else if (!strcmp(opt, "proto")) {
-+ if (!strncmp(opteq+1, "tcp", 3))
-+ data.proto = IPPROTO_TCP;
-+ else if (!strncmp(opteq+1, "udp", 3))
-+ data.proto = IPPROTO_UDP;
-+ else
-+ printf(_("Warning: Unrecognized proto= option.\n"));
-+ } else if (!strcmp(opt, "clientaddr")) {
-+ if (strlen(opteq+1) >= sizeof(ip_addr))
-+ printf(_("Invalid client address %s"),
-+ opteq+1);
-+ strncpy(ip_addr,opteq+1, sizeof(ip_addr));
-+ ip_addr[sizeof(ip_addr)-1] = '\0';
-+ } else if (!strcmp(opt, "sec")) {
-+ if (!strcmp(opteq+1, "krb5"))
-+ pseudoflavour = 390003;
-+ else if (!strcmp(opteq+1, "krb5i"))
-+ pseudoflavour = 390004;
-+ else if (!strcmp(opteq+1, "krb5p"))
-+ pseudoflavour = 390005;
-+ else if (!strcmp(opteq+1, "lipkey"))
-+ pseudoflavour = 390006;
-+ else if (!strcmp(opteq+1, "lipkey-i"))
-+ pseudoflavour = 390007;
-+ else if (!strcmp(opteq+1, "lipkey-p"))
-+ pseudoflavour = 390008;
-+ else if (!strcmp(opteq+1, "spkm3"))
-+ pseudoflavour = 390009;
-+ else if (!strcmp(opteq+1, "spkm3i"))
-+ pseudoflavour = 390010;
-+ else if (!strcmp(opteq+1, "spkm3p"))
-+ pseudoflavour = 390011;
-+ else {
-+ printf(_("unknown security type %s\n"),
-+ opteq+1);
-+ goto fail;
-+ }
-+ } else if (!strcmp(opt, "addr")) {
-+ /* ignore */;
-+ } else {
-+ printf(_("unknown nfs mount parameter: "
-+ "%s=%d\n"), opt, val);
-+ goto fail;
-+ }
-+ } else {
-+ val = 1;
-+ if (!strncmp(opt, "no", 2)) {
-+ val = 0;
-+ opt += 2;
-+ }
-+ if (!strcmp(opt, "bg"))
-+ bg = val;
-+ else if (!strcmp(opt, "fg"))
-+ bg = !val;
-+ else if (!strcmp(opt, "soft"))
-+ soft = val;
-+ else if (!strcmp(opt, "hard"))
-+ soft = !val;
-+ else if (!strcmp(opt, "intr"))
-+ intr = val;
-+ else if (!strcmp(opt, "cto"))
-+ nocto = !val;
-+ else if (!strcmp(opt, "ac"))
-+ noac = !val;
-+ else {
-+ if (!sloppy) {
-+ printf(_("unknown nfs mount option: "
-+ "%s%s\n"), val ? "" : "no", opt);
-+ goto fail;
-+ }
-+ }
-+ }
-+ }
-+
-+ data.flags = (soft ? NFS4_MOUNT_SOFT : 0)
-+ | (intr ? NFS4_MOUNT_INTR : 0)
-+ | (nocto ? NFS4_MOUNT_NOCTO : 0)
-+ | (noac ? NFS4_MOUNT_NOAC : 0);
-+
-+ if (pseudoflavour != 0) {
-+ data.auth_flavourlen = 1;
-+ data.auth_flavours = &pseudoflavour;
-+ }
-+
-+ data.client_addr.data = ip_addr;
-+ data.client_addr.len = strlen(ip_addr);
-+
-+ data.mnt_path.data = dirname;
-+ data.mnt_path.len = strlen(dirname);
-+
-+ data.hostname.data = hostname;
-+ data.hostname.len = strlen(hostname);
-+ data.host_addr = (struct sockaddr *)&server_addr;
-+ data.host_addrlen = sizeof(server_addr);
-+
-+#ifdef NFS_MOUNT_DEBUG
-+ printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-+ data.rsize, data.wsize, data.timeo, data.retrans);
-+ printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
-+ data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
-+ printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
-+ ntohs(server_addr.sin_port), bg, retry, data.flags);
-+ printf("soft = %d, intr = %d, nocto = %d, noac = %d\n",
-+ (data.flags & NFS4_MOUNT_SOFT) != 0,
-+ (data.flags & NFS4_MOUNT_INTR) != 0,
-+ (data.flags & NFS4_MOUNT_NOCTO) != 0,
-+ (data.flags & NFS4_MOUNT_NOAC) != 0);
-+ printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp");
-+#endif
-+
-+ data.version = NFS4_MOUNT_VERSION;
-+
-+ *mount_opts = (char *) &data;
-+ /* clean up */
-+ return 0;
-+
-+fail:
-+ return retval;
-+}
-diff -puN /dev/null mount/nfs4_mount.h
---- /dev/null 2004-08-19 17:44:20.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs4_mount.h 2004-10-13 13:51:50.000000000 -0400
-@@ -0,0 +1,82 @@
-+#ifndef _LINUX_NFS4_MOUNT_H
-+#define _LINUX_NFS4_MOUNT_H
-+
-+/*
-+ * linux/include/linux/nfs4_mount.h
-+ *
-+ * Copyright (C) 2002 Trond Myklebust
-+ *
-+ * structure passed from user-space to kernel-space during an nfsv4 mount
-+ */
-+
-+/*
-+ * WARNING! Do not delete or change the order of these fields. If
-+ * a new field is required then add it to the end. The version field
-+ * tracks which fields are present. This will ensure some measure of
-+ * mount-to-kernel version compatibility. Some of these aren't used yet
-+ * but here they are anyway.
-+ */
-+#define NFS4_MOUNT_VERSION 1
-+
-+struct nfs_string {
-+ unsigned int len;
-+ const char* data;
-+};
-+
-+struct nfs4_mount_data {
-+ int version; /* 1 */
-+ int flags; /* 1 */
-+ int rsize; /* 1 */
-+ int wsize; /* 1 */
-+ int timeo; /* 1 */
-+ int retrans; /* 1 */
-+ int acregmin; /* 1 */
-+ int acregmax; /* 1 */
-+ int acdirmin; /* 1 */
-+ int acdirmax; /* 1 */
-+
-+ /* see the definition of 'struct clientaddr4' in RFC3010 */
-+ struct nfs_string client_addr; /* 1 */
-+
-+ /* Mount path */
-+ struct nfs_string mnt_path; /* 1 */
-+
-+ /* Server details */
-+ struct nfs_string hostname; /* 1 */
-+ /* Server IP address */
-+ unsigned int host_addrlen; /* 1 */
-+ struct sockaddr* host_addr; /* 1 */
-+
-+ /* Transport protocol to use */
-+ int proto; /* 1 */
-+
-+ /* Pseudo-flavours to use for authentication. See RFC2623 */
-+ int auth_flavourlen; /* 1 */
-+ int *auth_flavours; /* 1 */
-+};
-+
-+/* bits in the flags field */
-+/* Note: the fields that correspond to existing NFSv2/v3 mount options
-+ * should mirror the values from include/linux/nfs_mount.h
-+ */
-+
-+#define NFS4_MOUNT_SOFT 0x0001 /* 1 */
-+#define NFS4_MOUNT_INTR 0x0002 /* 1 */
-+#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */
-+#define NFS4_MOUNT_NOAC 0x0020 /* 1 */
-+#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */
-+#define NFS4_MOUNT_FLAGMASK 0xFFFF
-+
-+/* pseudoflavors: */
-+
-+#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
-+
-+#endif
-diff -puN mount/nfs.5~base-nfsv4 mount/nfs.5
---- util-linux-2.12/mount/nfs.5~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs.5 2004-10-13 13:51:50.000000000 -0400
-@@ -3,7 +3,7 @@
- .\" patches. "
- .TH NFS 5 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
- .SH NAME
--nfs \- nfs fstab format and options
-+nfs \- nfs and nfs4 fstab format and options
- .SH SYNOPSIS
- .B /etc/fstab
- .SH DESCRIPTION
-@@ -17,14 +17,51 @@ the local directory that is the mount po
- and the NFS specific options that control
- the way the filesystem is mounted.
- .P
--Here is an example from an \fI/etc/fstab\fP file from an NFS mount.
-+Three different versions of the NFS protocol are
-+supported by the Linux NFS client:
-+NFS version 2, NFS version 3, and NFS version 4.
-+To mount via NFS version 2, use the
-+.BR nfs
-+file system type and specify
-+.BR nfsvers=2 .
-+Version 2 is the default protocol version for the
-+.BR nfs
-+file system type when
-+.BR nfsvers=
-+is not specified on the mount command.
-+To mount via NFS version 3, use the
-+.BR nfs
-+file system type and specify
-+.BR nfsvers=3 .
-+To mount via NFS version 4, use the
-+.BR nfs4
-+file system type.
-+The
-+.BR nfsvers=
-+keyword is not supported for the
-+.BR nfs4
-+file system type.
-+.P
-+These file system types share similar mount options;
-+the differences are listed below.
-+.P
-+Here is an example from an \fI/etc/fstab\fP file for an NFSv2 mount
-+over UDP.
- .sp
- .nf
- .ta 2.5i +0.75i +0.75i +1.0i
- server:/usr/local/pub /pub nfs rsize=8192,wsize=8192,timeo=14,intr
- .fi
-+.P
-+Here is an example for an NFSv4 mount over TCP using Kerberos
-+5 mutual authentication.
-+.sp
-+.nf
-+.ta 2.5i +0.75i +0.75i +1.0i
-+server:/usr/local/pub /pub nfs4 proto=tcp,sec=krb5,hard,intr
-+.fi
- .DT
--.SS Options
-+.SS Options for the nfs file system type
- .TP 1.5i
- .I rsize=n
- The number of bytes NFS uses when reading files from an NFS server.
-@@ -208,6 +245,163 @@ is the default.
- All of the non-value options have corresponding nooption forms.
- For example, nointr means don't allow file operations to be
- interrupted.
-+.SS Options for the nfs4 file system type
-+.TP 1.5i
-+.I rsize=n
-+The number of bytes NFS uses when reading files from an NFS server.
-+The default value is dependent on the kernel, currently 4096 bytes.
-+(However, throughput is improved greatly by asking for
-+.IR rsize=32768 .)
-+This value is negotiated with the server.
-+.TP 1.5i
-+.I wsize=n
-+The number of bytes NFS uses when writing files to an NFS server.
-+The default value is dependent on the kernel, currently 4096 bytes.
-+(However, throughput is improved greatly by asking for
-+.IR wsize=32768 .)
-+This value is negotiated with the server.
-+.TP 1.5i
-+.I timeo=n
-+The value in tenths of a second before sending the
-+first retransmission after an RPC timeout.
-+The default value depends on whether
-+.IR proto=udp
-+or
-+.IR proto=tcp
-+is in effect (see below).
-+The default value for UDP is 7 tenths of a second.
-+The default value for TCP is 60 seconds.
-+After the first timeout,
-+the timeout is doubled after each successive timeout until a maximum
-+timeout of 60 seconds is reached or the enough retransmissions
-+have occured to cause a major timeout. Then, if the filesystem
-+is hard mounted, each new timeout cascade restarts at twice the
-+initial value of the previous cascade, again doubling at each
-+retransmission. The maximum timeout is always 60 seconds.
-+.TP 1.5i
-+.I retrans=n
-+The number of minor timeouts and retransmissions that must occur before
-+a major timeout occurs. The default is 5 timeouts for
-+.IR proto=udp
-+and 2 timeouts for
-+.IR proto=tcp .
-+When a major timeout
-+occurs, the file operation is either aborted or a "server not responding"
-+message is printed on the console.
-+.TP 1.5i
-+.I acregmin=n
-+The minimum time in seconds that attributes of a regular file should
-+be cached before requesting fresh information from a server.
-+The default is 3 seconds.
-+.TP 1.5i
-+.I acregmax=n
-+The maximum time in seconds that attributes of a regular file can
-+be cached before requesting fresh information from a server.
-+The default is 60 seconds.
-+.TP 1.5i
-+.I acdirmin=n
-+The minimum time in seconds that attributes of a directory should
-+be cached before requesting fresh information from a server.
-+The default is 30 seconds.
-+.TP 1.5i
-+.I acdirmax=n
-+The maximum time in seconds that attributes of a directory can
-+be cached before requesting fresh information from a server.
-+The default is 60 seconds.
-+.TP 1.5i
-+.I actimeo=n
-+Using actimeo sets all of
-+.I acregmin,
-+.I acregmax,
-+.I acdirmin,
-+and
-+.I acdirmax
-+to the same value.
-+There is no default value.
-+.TP 1.5i
-+.I retry=n
-+The number of minutes to retry an NFS mount operation
-+in the foreground or background before giving up.
-+The default value is 10000 minutes, which is roughly one week.
-+.TP 1.5i
-+.I port=n
-+The numeric value of the port to connect to the NFS server on.
-+If the port number is 0 (the default) then query the
-+remote host's portmapper for the port number to use.
-+If the remote host's NFS daemon is not registered with
-+its portmapper, the standard NFS port number 2049 is
-+used instead.
-+.TP 1.5i
-+.I proto=n
-+Mount the NFS filesystem using a specific network protocol
-+instead of the default UDP protocol.
-+Many NFS version 4 servers only support TCP.
-+Valid protocol types are
-+.IR udp
-+and
-+.IR tcp .
-+.TP 1.5i
-+.I clientaddr=n
-+On a multi-homed client, this
-+causes the client to use a specific callback address when
-+communicating with an NFS version 4 server.
-+This option is currently ignored.
-+.TP 1.5i
-+.I sec=n
-+Specify an advanced security mechanism for this file system.
-+To use Kerberos 5 mutual authentication, specify
-+.IR krb5 .
-+Kerberos 5 integrity checking is specified with
-+.IR krb5i ,
-+and Kerberos 5 privacy is specified with
-+.IR krb5p .
-+Other security mechanisms may become available in the future.
-+.TP 1.5i
-+.I bg
-+If an NFS mount attempt times out, retry the mount
-+in the background.
-+After a mount operation is backgrounded, all subsequent mounts
-+on the same NFS server will be backgrounded immediately, without
-+first attempting the mount.
-+A missing mount point is treated as a timeout,
-+to allow for nested NFS mounts.
-+.TP 1.5i
-+.I fg
-+If the first NFS mount attempt times out, retry the mount
-+in the foreground.
-+This is the complement of the
-+.I bg
-+option, and also the default behavior.
-+.TP 1.5i
-+.I soft
-+If an NFS file operation has a major timeout then report an I/O error to
-+the calling program.
-+The default is to continue retrying NFS file operations indefinitely.
-+.TP 1.5i
-+.I hard
-+If an NFS file operation has a major timeout then report
-+"server not responding" on the console and continue retrying indefinitely.
-+This is the default.
-+.TP 1.5i
-+.I intr
-+If an NFS file operation has a major timeout and it is hard mounted,
-+then allow signals to interupt the file operation and cause it to
-+return EINTR to the calling program. The default is to not
-+allow file operations to be interrupted.
-+.TP 1.5i
-+.I nocto
-+Suppress the retrieval of new attributes when creating a file.
-+.TP 1.5i
-+.I noac
-+Disable attribute caching, and force synchronous writes.
-+This extracts a
-+server performance penalty but it allows two different NFS clients
-+to get reasonable good results when both clients are actively
-+writing to common filesystem on the server.
-+.P
-+All of the non-value options have corresponding nooption forms.
-+For example, nointr means don't allow file operations to be
-+interrupted.
- .SH FILES
- .I /etc/fstab
- .SH "SEE ALSO"
-diff -puN mount/nfsmount.c~base-nfsv4 mount/nfsmount.c
---- util-linux-2.12/mount/nfsmount.c~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfsmount.c 2004-10-13 13:51:50.000000000 -0400
-@@ -706,7 +706,10 @@ static inline int
- nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
- {
- if (nfs_pmap->pm_vers > MAX_NFSPROT) {
-- fprintf(stderr, _("NFSv%ld not supported!\n"), nfs_pmap->pm_vers);
-+ if (nfs_pmap->pm_vers == 4)
-+ fprintf(stderr, _("'vers=4' is not supported. Use '-t nfs4' instead.\n"));
-+ else
-+ fprintf(stderr, _("NFSv%ld not supported!\n"), nfs_pmap->pm_vers);
- goto out_bad;
- }
- if (mnt_pmap->pm_vers > MAX_MNTPROT) {
-diff -puN mount/sundries.h~base-nfsv4 mount/sundries.h
---- util-linux-2.12/mount/sundries.h~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/sundries.h 2004-10-13 13:51:50.000000000 -0400
-@@ -37,6 +37,8 @@ void die (int errcode, const char *fmt,
- #ifdef HAVE_NFS
- int nfsmount (const char *spec, const char *node, int *flags,
- char **orig_opts, char **opt_args, int *version, int running_bg);
-+int nfs4mount (const char *spec, const char *node, int *flags,
-+ char **orig_opts, char **opt_args, int running_bg);
- int nfsumount(const char *spec, const char *opts);
- #endif
-
-diff -puN mount/umount.c~base-nfsv4 mount/umount.c
---- util-linux-2.12/mount/umount.c~base-nfsv4 2004-10-13 13:51:50.000000000 -0400
-+++ util-linux-2.12-bfields/mount/umount.c 2004-10-13 13:51:50.000000000 -0400
-@@ -89,6 +89,9 @@
- /* True if ruid != euid. */
- int suid = 0;
-
-+/* Needed by nfs4mount.c */
-+int sloppy = 0;
-+
- /*
- * check_special_umountprog()
- * If there is a special umount program for this type, exec it.
-
+++ /dev/null
-
-Allow nfs versions 2 and 3 to mount with -osec=krb5.
-
-
----
-
- util-linux-2.12-bfields/mount/nfs.5 | 37 +++++++++-----
- util-linux-2.12-bfields/mount/nfs_mount4.h | 18 ++++++-
- util-linux-2.12-bfields/mount/nfsmount.c | 74 ++++++++++++++++++++++++++++-
- 3 files changed, 112 insertions(+), 17 deletions(-)
-
-diff -puN mount/nfs.5~krb5 mount/nfs.5
---- util-linux-2.12/mount/nfs.5~krb5 2004-10-13 14:15:03.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs.5 2004-10-13 14:15:03.000000000 -0400
-@@ -165,7 +165,7 @@ mount daemon program number.
- Use an alternate RPC version number to contact the
- mount daemon on the remote host. This option is useful
- for hosts that can run multiple NFS servers.
--The default value is version 1.
-+The default value depends on which kernel you are using.
- .TP 1.5i
- .I nfsprog=n
- Use an alternate RPC program number to contact the
-@@ -178,7 +178,7 @@ NFS daemon program number.
- Use an alternate RPC version number to contact the
- NFS daemon on the remote host. This option is useful
- for hosts that can run multiple NFS servers.
--The default value is version 2.
-+The default value depends on which kernel you are using.
- .TP 1.5i
- .I nolock
- Disable NFS locking. Do not start lockd.
-@@ -230,9 +230,25 @@ Suppress the retrieval of new attributes
- .TP 1.5i
- .I noac
- Disable all forms of attribute caching entirely. This extracts a
--server performance penalty but it allows two different NFS clients
--to get reasonable good results when both clients are actively
--writing to common filesystem on the server.
-+significant performance penalty but it allows two different NFS clients
-+to get reasonable results when both clients are actively
-+writing to a common export on the server.
-+.TP 1.5i
-+.I sec=mode
-+Set the security flavor for this mount to "mode".
-+The default setting is \f3sec=sys\f1, which uses local
-+unix uids and gids to authenticate NFS operations (AUTH_SYS).
-+Other currently supported settings are:
-+\f3sec=krb5\f1, which uses Kerberos V5 instead of local unix uids
-+and gids to authenticate users;
-+\f3sec=krb5i\f1, which uses Kerberos V5 for user authentication
-+and performs integrity checking of NFS operations using secure
-+checksums to prevent data tampering; and
-+\f3sec=krb5p\f1, which uses Kerberos V5 for user authentication
-+and integrity checking, and encrypts NFS traffic to prevent
-+traffic sniffing (this is the most secure setting).
-+Note that there is a performance penalty when using integrity
-+or privacy.
- .TP 1.5i
- .I tcp
- Mount the NFS filesystem using the TCP protocol instead of the
-@@ -347,15 +363,8 @@ causes the client to use a specific call
- communicating with an NFS version 4 server.
- This option is currently ignored.
- .TP 1.5i
--.I sec=n
--Specify an advanced security mechanism for this file system.
--To use Kerberos 5 mutual authentication, specify
--.IR krb5 .
--Kerberos 5 integrity checking is specified with
--.IR krb5i ,
--and Kerberos 5 privacy is specified with
--.IR krb5p .
--Other security mechanisms may become available in the future.
-+.I sec=mode
-+Same as \f3sec=mode\f1 for the nfs filesystem type (see above).
- .TP 1.5i
- .I bg
- If an NFS mount attempt times out, retry the mount
-diff -puN mount/nfs_mount4.h~krb5 mount/nfs_mount4.h
---- util-linux-2.12/mount/nfs_mount4.h~krb5 2004-10-13 14:15:03.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs_mount4.h 2004-10-13 14:16:45.000000000 -0400
-@@ -8,7 +8,7 @@
- * so it is easiest to ignore the kernel altogether (at compile time).
- */
-
--#define NFS_MOUNT_VERSION 4
-+#define NFS_MOUNT_VERSION 5
-
- struct nfs2_fh {
- char data[32];
-@@ -36,6 +36,7 @@ struct nfs_mount_data {
- int namlen; /* 2 */
- unsigned int bsize; /* 3 */
- struct nfs3_fh root; /* 4 */
-+ int pseudoflavor; /* 5 */
- };
-
- /* bits in the flags field */
-@@ -51,4 +52,19 @@ struct nfs_mount_data {
- #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
- #define NFS_MOUNT_NONLM 0x0200 /* 3 */
- #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */
-+#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
-+
-+/* security pseudoflavors */
-+
-+#ifndef AUTH_GSS_KRB5
-+#define AUTH_GSS_KRB5 390003
-+#define AUTH_GSS_KRB5I 390004
-+#define AUTH_GSS_KRB5P 390005
-+#define AUTH_GSS_LKEY 390006
-+#define AUTH_GSS_LKEYI 390007
-+#define AUTH_GSS_LKEYP 390008
-+#define AUTH_GSS_SPKM 390009
-+#define AUTH_GSS_SPKMI 390010
-+#define AUTH_GSS_SPKMP 390011
-+#endif
-
-diff -puN mount/nfsmount.c~krb5 mount/nfsmount.c
---- util-linux-2.12/mount/nfsmount.c~krb5 2004-10-13 14:15:03.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfsmount.c 2004-10-13 14:16:46.000000000 -0400
-@@ -109,6 +109,8 @@ typedef struct {
- static const struct timeval TIMEOUT = { 20, 0 };
- static const struct timeval RETRY_TIMEOUT = { 3, 0 };
-
-+static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp);
-+
- /* Define the order in which to probe for UDP/TCP services */
- static const u_int *
- proto_probelist(const int use_tcp)
-@@ -211,8 +213,10 @@ find_kernel_nfs_mount_version(void) {
- mnt_version = 4; /* since 2.2.18pre9 */
- else if (kernel_version < MAKE_VERSION(2,3,99))
- mnt_version = 3;
-+ else if (kernel_version < MAKE_VERSION(2,6,0))
-+ mnt_version = 4;
- else
-- mnt_version = 4; /* since 2.3.99pre4 */
-+ mnt_version = 5;
- }
- if (mnt_version > NFS_MOUNT_VERSION)
- mnt_version = NFS_MOUNT_VERSION;
-@@ -596,6 +600,40 @@ parse_options(char *old_opts, struct nfs
- #endif
- } else if (!sloppy)
- goto bad_parameter;
-+#if NFS_MOUNT_VERSION >= 5
-+ } else if (!strcmp(opt, "sec")) {
-+ char *secflavor = opteq+1;
-+ /* see RFC 2623 */
-+ if (nfs_mount_version < 5) {
-+ printf(_("Warning: ignoring sec=%s option\n"), secflavor);
-+ continue;
-+ } else if (!strcmp(secflavor, "sys"))
-+ data->pseudoflavor = AUTH_SYS;
-+ else if (!strcmp(secflavor, "krb5"))
-+ data->pseudoflavor = AUTH_GSS_KRB5;
-+ else if (!strcmp(secflavor, "krb5i"))
-+ data->pseudoflavor = AUTH_GSS_KRB5I;
-+ else if (!strcmp(secflavor, "krb5p"))
-+ data->pseudoflavor = AUTH_GSS_KRB5P;
-+ else if (!strcmp(secflavor, "lipkey"))
-+ data->pseudoflavor = AUTH_GSS_LKEY;
-+ else if (!strcmp(secflavor, "lipkey-i"))
-+ data->pseudoflavor = AUTH_GSS_LKEYI;
-+ else if (!strcmp(secflavor, "lipkey-p"))
-+ data->pseudoflavor = AUTH_GSS_LKEYP;
-+ else if (!strcmp(secflavor, "spkm3"))
-+ data->pseudoflavor = AUTH_GSS_SPKM;
-+ else if (!strcmp(secflavor, "spkm3i"))
-+ data->pseudoflavor = AUTH_GSS_SPKMI;
-+ else if (!strcmp(secflavor, "spkm3p"))
-+ data->pseudoflavor = AUTH_GSS_SPKMP;
-+ else if (!sloppy) {
-+ printf(_("Warning: Unrecognized security flavor %s.\n"),
-+ secflavor);
-+ goto bad_parameter;
-+ }
-+ data->flags |= NFS_MOUNT_SECFLAVOUR;
-+#endif
- } else if (!strcmp(opt, "mounthost"))
- mounthost=xstrndup(opteq+1,
- strcspn(opteq+1," \t\n\r,"));
-@@ -745,7 +783,7 @@ nfsmount(const char *spec, const char *n
- mntres_t mntres;
-
- struct stat statbuf;
-- char *s, *p;
-+ char *s;
- int bg, retry;
- int retval;
- time_t t;
-@@ -809,6 +847,7 @@ nfsmount(const char *spec, const char *n
- #if NFS_MOUNT_VERSION >= 2
- data.namlen = NAME_MAX;
- #endif
-+ data.pseudoflavor = AUTH_SYS;
-
- bg = 0;
- retry = 10000; /* 10000 minutes ~ 1 week */
-@@ -847,6 +886,9 @@ nfsmount(const char *spec, const char *n
- printf("tcp = %d\n",
- (data.flags & NFS_MOUNT_TCP) != 0);
- #endif
-+#if NFS_MOUNT_VERSION >= 5
-+ printf("sec = %u\n", data.pseudoflavor);
-+#endif
- #endif
-
- data.version = nfs_mount_version;
-@@ -949,7 +991,9 @@ nfsmount(const char *spec, const char *n
- #endif
- } else {
- #if NFS_MOUNT_VERSION >= 4
-+ mountres3_ok *mountres;
- fhandle3 *fhandle;
-+ int i, *flavor, yum = 0;
- if (mntres.nfsv3.fhs_status != 0) {
- fprintf(stderr,
- _("mount: %s:%s failed, reason given by server: %s\n"),
-@@ -957,6 +1001,32 @@ nfsmount(const char *spec, const char *n
- nfs_strerror(mntres.nfsv3.fhs_status));
- goto fail;
- }
-+#if NFS_MOUNT_VERSION >= 5
-+ mountres = &mntres.nfsv3.mountres3_u.mountinfo;
-+ i = mountres->auth_flavours.auth_flavours_len;
-+ if (i <= 0)
-+ goto noauth_flavours;
-+
-+ flavor = mountres->auth_flavours.auth_flavours_val;
-+ while (--i >= 0) {
-+ if (flavor[i] == data.pseudoflavor)
-+ yum = 1;
-+#ifdef NFS_MOUNT_DEBUG
-+ printf("auth flavor %d: %d\n",
-+ i, flavor[i]);
-+#endif
-+ }
-+ if (!yum) {
-+ fprintf(stderr,
-+ "mount: %s:%s failed, "
-+ "security flavor not supported\n",
-+ hostname, dirname);
-+ /* server has registered us in mtab, send umount */
-+ nfs_call_umount(&mnt_server, &dirname);
-+ goto fail;
-+ }
-+noauth_flavours:
-+#endif
- fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle;
- memset(data.old_root.data, 0, NFS_FHSIZE);
- memset(&data.root, 0, sizeof(data.root));
-_
+++ /dev/null
-
-This patch modifies the NFSv4 'mount' command to accept multiple
-authentication flavors. This list of flavors will be used during security
-negotiation to determine which flavors the user is willing to use (most
-preferred flavor is listed first).
-
-This patch applies on top of CITI's version 2.11z-3 of util-linux.
-
-The format for passing one flavor is unchanged:
- mount -tnfs4 -osec=krb5 server:/ /mnt/nfs4
-
-The format for passing multiple flavors is:
- mount -tnfs4 -osec=krb5:spkm3p:unix server:/ /mnt/nfs4
-
-If no sec= option is given, we assume AUTH_UNIX.
-
-From Nick Wilson <njw@us.ibm.com>
-
----
-
- util-linux-2.12-bfields/mount/nfs4mount.c | 102 ++++++++++++++++++++++--------
- 1 files changed, 75 insertions(+), 27 deletions(-)
-
-diff -puN mount/nfs4mount.c~modify_mount_to_support_multiple_security_flavors mount/nfs4mount.c
---- util-linux-2.12/mount/nfs4mount.c~modify_mount_to_support_multiple_security_flavors 2004-10-13 14:18:23.000000000 -0400
-+++ util-linux-2.12-bfields/mount/nfs4mount.c 2004-10-13 14:21:18.000000000 -0400
-@@ -36,6 +36,7 @@
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-+#include <rpc/auth.h>
-
- #include "sundries.h"
-
-@@ -48,6 +49,57 @@
- #define NFS_PORT 2049
- #endif
-
-+struct {
-+ char *flavour;
-+ int fnum;
-+} flav_map[] = {
-+ { "krb5", RPC_AUTH_GSS_KRB5 },
-+ { "krb5i", RPC_AUTH_GSS_KRB5I },
-+ { "krb5p", RPC_AUTH_GSS_KRB5P },
-+ { "lipkey", RPC_AUTH_GSS_LKEY },
-+ { "lipkey-i", RPC_AUTH_GSS_LKEYI },
-+ { "lipkey-p", RPC_AUTH_GSS_LKEYP },
-+ { "spkm3", RPC_AUTH_GSS_SPKM },
-+ { "spkm3i", RPC_AUTH_GSS_SPKMI },
-+ { "spkm3p", RPC_AUTH_GSS_SPKMP },
-+ { "unix", AUTH_UNIX },
-+ { "sys", AUTH_SYS },
-+ { "null", AUTH_NULL },
-+ { "none", AUTH_NONE },
-+};
-+
-+#define FMAPSIZE (sizeof(flav_map)/sizeof(flav_map[0]))
-+#define MAX_USER_FLAVOUR 16
-+
-+static int parse_sec(char *sec, int *pseudoflavour)
-+{
-+ int i, num_flavour = 0;
-+
-+ for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) {
-+ if (num_flavour >= MAX_USER_FLAVOUR) {
-+ fprintf(stderr,
-+ _("mount: maximum number of security flavors "
-+ "exceeded\n"));
-+ return 0;
-+ }
-+ for (i = 0; i < FMAPSIZE; i++) {
-+ if (strcmp(sec, flav_map[i].flavour) == 0) {
-+ pseudoflavour[num_flavour++] = flav_map[i].fnum;
-+ break;
-+ }
-+ }
-+ if (i == FMAPSIZE) {
-+ fprintf(stderr,
-+ _("mount: unknown security type %s\n"), sec);
-+ return 0;
-+ }
-+ }
-+ if (!num_flavour)
-+ fprintf(stderr,
-+ _("mount: no security flavors passed to sec= option\n"));
-+ return num_flavour;
-+}
-+
- static int parse_devname(char *hostdir, char **hostname, char **dirname)
- {
- char *s;
-@@ -117,7 +169,8 @@ int nfs4mount(const char *spec, const ch
- static char hostdir[1024];
- static char ip_addr[16] = "127.0.0.1";
- static struct sockaddr_in server_addr;
-- static int pseudoflavour = 0;
-+ static int pseudoflavour[MAX_USER_FLAVOUR];
-+ int num_flavour = 0;
-
- char *hostname, *dirname, *old_opts;
- char new_opts[1024];
-@@ -228,29 +281,9 @@ int nfs4mount(const char *spec, const ch
- strncpy(ip_addr,opteq+1, sizeof(ip_addr));
- ip_addr[sizeof(ip_addr)-1] = '\0';
- } else if (!strcmp(opt, "sec")) {
-- if (!strcmp(opteq+1, "krb5"))
-- pseudoflavour = 390003;
-- else if (!strcmp(opteq+1, "krb5i"))
-- pseudoflavour = 390004;
-- else if (!strcmp(opteq+1, "krb5p"))
-- pseudoflavour = 390005;
-- else if (!strcmp(opteq+1, "lipkey"))
-- pseudoflavour = 390006;
-- else if (!strcmp(opteq+1, "lipkey-i"))
-- pseudoflavour = 390007;
-- else if (!strcmp(opteq+1, "lipkey-p"))
-- pseudoflavour = 390008;
-- else if (!strcmp(opteq+1, "spkm3"))
-- pseudoflavour = 390009;
-- else if (!strcmp(opteq+1, "spkm3i"))
-- pseudoflavour = 390010;
-- else if (!strcmp(opteq+1, "spkm3p"))
-- pseudoflavour = 390011;
-- else {
-- printf(_("unknown security type %s\n"),
-- opteq+1);
-+ num_flavour = parse_sec(opteq+1, pseudoflavour);
-+ if (!num_flavour)
- goto fail;
-- }
- } else if (!strcmp(opt, "addr")) {
- /* ignore */;
- } else {
-@@ -293,10 +326,10 @@ int nfs4mount(const char *spec, const ch
- | (nocto ? NFS4_MOUNT_NOCTO : 0)
- | (noac ? NFS4_MOUNT_NOAC : 0);
-
-- if (pseudoflavour != 0) {
-- data.auth_flavourlen = 1;
-- data.auth_flavours = &pseudoflavour;
-- }
-+ if (num_flavour == 0)
-+ pseudoflavour[num_flavour++] = AUTH_UNIX;
-+ data.auth_flavourlen = num_flavour;
-+ data.auth_flavours = pseudoflavour;
-
- data.client_addr.data = ip_addr;
- data.client_addr.len = strlen(ip_addr);
-@@ -321,6 +354,21 @@ int nfs4mount(const char *spec, const ch
- (data.flags & NFS4_MOUNT_INTR) != 0,
- (data.flags & NFS4_MOUNT_NOCTO) != 0,
- (data.flags & NFS4_MOUNT_NOAC) != 0);
-+
-+ if (num_flavour > 0) {
-+ int pf_cnt, i;
-+
-+ printf("sec = ");
-+ for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
-+ for (i = 0; i < FMAPSIZE; i++) {
-+ if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
-+ printf("%s", flav_map[i].flavour);
-+ break;
-+ }
-+ }
-+ printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n");
-+ }
-+ }
- printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp");
- #endif
-
-_
+++ /dev/null
-
-
----
-
- util-linux-2.12-bfields/mount/nfsmount.c | 2 +-
- 1 files changed, 1 insertion(+), 1 deletion(-)
-
-diff -puN mount/nfsmount.c~mount_sloppy_fix mount/nfsmount.c
---- util-linux-2.12/mount/nfsmount.c~mount_sloppy_fix 2004-12-13 12:21:52.000000000 -0500
-+++ util-linux-2.12-bfields/mount/nfsmount.c 2004-12-13 12:21:52.000000000 -0500
-@@ -712,7 +712,7 @@ parse_options(char *old_opts, struct nfs
- data->flags |= NFS_MOUNT_BROKEN_SUID;
- }
- #endif
-- } else {
-+ } else if (!sloppy) {
- bad_option:
- printf(_("Unsupported nfs mount option: "
- "%s%s\n"), val ? "" : "no", opt);
-_
+++ /dev/null
-
-
-Changes from redhat srpm.
-
----
-
- util-linux-2.12-bfields/mount/mount.c | 2
- util-linux-2.12-bfields/mount/nfs4mount.c | 20 +++++++++
- util-linux-2.12-bfields/mount/nfsmount.c | 61 +++++++++++++++++++++++++-----
- 3 files changed, 72 insertions(+), 11 deletions(-)
-
-diff -puN mount/mount.c~redhat-nfs-mount mount/mount.c
---- util-linux-2.12/mount/mount.c~redhat-nfs-mount 2004-12-13 12:34:18.000000000 -0500
-+++ util-linux-2.12-bfields/mount/mount.c 2004-12-13 12:34:18.000000000 -0500
-@@ -829,6 +829,7 @@ retry_nfs:
- mnt_err = nfs4mount(spec, node, &flags, &extra_opts, &mount_opts, bg);
- if (mnt_err)
- return mnt_err;
-+ goto nosigblock;
- #else
- die (EX_SOFTWARE, _("mount: this version was compiled "
- "without support for the type `nfs4'"));
-@@ -836,6 +837,7 @@ retry_nfs:
- }
-
- block_signals (SIG_BLOCK);
-+nosigblock:
-
- if (!fake)
- mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,
-diff -puN mount/nfs4mount.c~redhat-nfs-mount mount/nfs4mount.c
---- util-linux-2.12/mount/nfs4mount.c~redhat-nfs-mount 2004-12-13 12:34:18.000000000 -0500
-+++ util-linux-2.12-bfields/mount/nfs4mount.c 2004-12-13 12:34:18.000000000 -0500
-@@ -37,6 +37,12 @@
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <rpc/auth.h>
-+#ifdef HAVE_rpcsvc_nfs_prot_h
-+#include <rpcsvc/nfs_prot.h>
-+#else
-+#include <linux/nfs.h>
-+#define nfsstat nfs_stat
-+#endif
-
- #include "sundries.h"
-
-@@ -49,6 +55,9 @@
- #define NFS_PORT 2049
- #endif
-
-+extern int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
-+extern void rpc_strerror(void);
-+
- struct {
- char *flavour;
- int fnum;
-@@ -225,7 +234,7 @@ int nfs4mount(const char *spec, const ch
-
- bg = 0;
- soft = 0;
-- intr = 0;
-+ intr = NFS4_MOUNT_INTR;
- nocto = 0;
- noac = 0;
- retry = 10000; /* 10000 minutes ~ 1 week */
-@@ -374,10 +383,19 @@ int nfs4mount(const char *spec, const ch
-
- data.version = NFS4_MOUNT_VERSION;
-
-+ clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto);
-+ if (rpc_createerr.cf_stat) {
-+ fprintf(stderr, "mount to NFS server '%s' failed.\n", data.hostname.data);
-+ goto fail;
-+ }
-+
- *mount_opts = (char *) &data;
- /* clean up */
- return 0;
-
- fail:
-+ if (verbose) {
-+ rpc_strerror();
-+ }
- return retval;
- }
-diff -puN mount/nfsmount.c~redhat-nfs-mount mount/nfsmount.c
---- util-linux-2.12/mount/nfsmount.c~redhat-nfs-mount 2004-12-13 12:34:18.000000000 -0500
-+++ util-linux-2.12-bfields/mount/nfsmount.c 2004-12-13 12:34:18.000000000 -0500
-@@ -111,6 +111,25 @@ static const struct timeval RETRY_TIMEOU
-
- static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp);
-
-+int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
-+
-+/* Convert RPC errors into strings */
-+void rpc_strerror(void)
-+{
-+ int cf_stat = rpc_createerr.cf_stat;
-+ int cf_errno = rpc_createerr.cf_error.re_errno;
-+ char *ptr, *estr = clnt_sperrno(cf_stat);
-+
-+ if (estr) {
-+ if ((ptr = index(estr, ':')))
-+ estr = ++ptr;
-+
-+ fprintf(stderr, "RPC Error: %d (%s )\n", cf_stat, estr);
-+ if (cf_stat == RPC_SYSTEMERROR)
-+ fprintf(stderr, "System Error: %d (%s)\n", cf_errno, strerror(cf_errno));
-+ }
-+}
-+
- /* Define the order in which to probe for UDP/TCP services */
- static const u_int *
- proto_probelist(const int use_tcp)
-@@ -252,14 +271,15 @@ nfs_gethostbyname(const char *hostname,
- * we're requesting, we open and RPC client, and fire off a NULL
- * RPC call.
- */
--static int
-+int
- clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
- const u_int prot)
- {
-- CLIENT *clnt;
-+ CLIENT *clnt=NULL;
- int sock, stat;
- static char clnt_res;
-
-+ rpc_createerr.cf_stat = stat = 0;
- sock = RPC_ANYSOCK;
- switch(prot) {
- case IPPROTO_UDP:
-@@ -285,6 +305,7 @@ clnt_ping(struct sockaddr_in *saddr, con
- close(sock);
- if (stat != RPC_PROGVERSMISMATCH)
- return 1;
-+
- out_bad:
- return 0;
- }
-@@ -308,9 +329,9 @@ probe_port(clnt_addr_t *server,
- *p_prot;
- const u_short port = (u_short) pmap->pm_port;
- u_short p_port;
--
- p_prot = prot ? &prot : protos;
- p_vers = vers ? &vers : versions;
-+ rpc_createerr.cf_stat = 0;
- for (;;) {
- saddr->sin_port = htons(PMAPPORT);
- p_port = pmap_getport(saddr, prog, *p_vers, *p_prot);
-@@ -338,6 +359,7 @@ probe_port(clnt_addr_t *server,
- pmap->pm_prot = *p_prot;
- if (!port)
- pmap->pm_port = p_port;
-+ rpc_createerr.cf_stat = 0;
- return 1;
- }
-
-@@ -394,6 +416,8 @@ probe_bothports(clnt_addr_t *mnt_server,
- return 1;
- memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
- }
-+ if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
-+ break;
- memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
- }
- out_bad:
-@@ -477,11 +501,23 @@ nfs_call_mount(clnt_addr_t *mnt_server,
- enum clnt_stat stat;
- int msock;
-
--
- if (!probe_bothports(mnt_server, nfs_server)) {
-- if (report_errs)
-- fprintf(stderr,_("mount: failed to probe ports on NFS server %s\n"),
-+ if (report_errs) {
-+ fprintf(stderr, "mount to NFS server '%s' failed",
- *nfs_server->hostname);
-+ if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) {
-+ fprintf(stderr, ": server is down.\n");
-+ } else if (nfs_server->pmap.pm_prot) {
-+ fprintf(stderr, ": possible invalid protocol.\n");
-+ } else if (nfs_server->pmap.pm_port) {
-+ fprintf(stderr, ": possible invalid port.\n");
-+ } else {
-+ fprintf(stderr, ".\n");
-+ }
-+ if (verbose) {
-+ rpc_strerror();
-+ }
-+ }
- goto out_bad;
- }
-
-@@ -743,15 +779,19 @@ parse_options(char *old_opts, struct nfs
- static inline int
- nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
- {
-- if (nfs_pmap->pm_vers > MAX_NFSPROT) {
-+ if (nfs_pmap->pm_vers &&
-+ (nfs_pmap->pm_vers > MAX_NFSPROT || nfs_pmap->pm_vers < 2)) {
- if (nfs_pmap->pm_vers == 4)
-- fprintf(stderr, _("'vers=4' is not supported. Use '-t nfs4' instead.\n"));
-+ fprintf(stderr, _("'vers=4' is not supported. "
-+ "Use '-t nfs4' instead.\n"));
- else
-- fprintf(stderr, _("NFSv%ld not supported!\n"), nfs_pmap->pm_vers);
-+ fprintf(stderr, _("NFS version %ld is not supported.\n"),
-+ nfs_pmap->pm_vers);
- goto out_bad;
- }
- if (mnt_pmap->pm_vers > MAX_MNTPROT) {
-- fprintf(stderr, _("NFS mount v%ld not supported!\n"), mnt_pmap->pm_vers);
-+ fprintf(stderr, _("NFS mount version %ld s not supported.\n"),
-+ mnt_pmap->pm_vers);
- goto out_bad;
- }
- return 1;
-@@ -1144,6 +1184,7 @@ nfs_call_umount(clnt_addr_t *mnt_server,
- res = nfs2_umount(argp, clnt);
- break;
- default:
-+ break;
- }
- mnt_closeclnt(clnt, msock);
- if (res == RPC_SUCCESS)
-_