walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
67a1db4
diff --git a/support/include/conffile.h b/support/include/conffile.h
67a1db4
index ce7aa21..05ea5d2 100644
67a1db4
--- a/support/include/conffile.h
67a1db4
+++ b/support/include/conffile.h
67a1db4
@@ -54,7 +54,7 @@ extern int      conf_end(int, int);
67a1db4
 extern void     conf_free_list(struct conf_list *);
67a1db4
 extern struct sockaddr *conf_get_address(char *, char *);
67a1db4
 extern struct conf_list *conf_get_list(char *, char *);
67a1db4
-extern struct conf_list *conf_get_tag_list(char *);
67a1db4
+extern struct conf_list *conf_get_tag_list(char *, char *);
67a1db4
 extern int      conf_get_num(char *, char *, int);
67a1db4
 extern char    *conf_get_str(char *, char *);
67a1db4
 extern char    *conf_get_section(char *, char *, char *);
67a1db4
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
67a1db4
index 174c2dd..38db5b5 100644
67a1db4
--- a/support/include/nfs/nfs.h
67a1db4
+++ b/support/include/nfs/nfs.h
67a1db4
@@ -15,6 +15,10 @@
67a1db4
 #define NFSD_MINVERS 2
67a1db4
 #define NFSD_MAXVERS 4
67a1db4
 
67a1db4
+#define NFS4_MINMINOR 1
67a1db4
+#define NFS4_MAXMINOR 2
67a1db4
+#define NFS4_VERDEFAULT  0x1  /* minor verion 1 */
67a1db4
+
67a1db4
 struct nfs_fh_len {
67a1db4
 	int		fh_size;
67a1db4
 	u_int8_t	fh_handle[NFS3_FHSIZE];
67a1db4
@@ -52,6 +56,7 @@ struct nfs_fh_old {
67a1db4
 #define NFSCTL_UDPISSET(_cltbits)     ((_cltbits) & NFSCTL_UDPBIT) 
67a1db4
 #define NFSCTL_TCPISSET(_cltbits)     ((_cltbits) & NFSCTL_TCPBIT) 
67a1db4
 
67a1db4
+#define NFSCTL_VERDEFAULT (0xc)       /* versions 3 and 4 */
67a1db4
 #define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |= (1 << ((_v) - 1))) 
67a1db4
 #define NFSCTL_UDPSET(_cltbits)       ((_cltbits) |= NFSCTL_UDPBIT)
67a1db4
 #define NFSCTL_TCPSET(_cltbits)       ((_cltbits) |= NFSCTL_TCPBIT)
6464d61
diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h
6464d61
index a0b80e1..1bfae7a 100644
6464d61
--- a/support/include/nfsrpc.h
6464d61
+++ b/support/include/nfsrpc.h
6464d61
@@ -156,6 +156,11 @@ extern unsigned long	nfs_pmap_getport(const struct sockaddr_in *,
6464d61
 				const struct timeval *);
6464d61
 
6464d61
 /*
6464d61
+ * Use nfs_pmap_getport to see if statd is running locally
6464d61
+ */
6464d61
+extern int nfs_probe_statd(void);
6464d61
+
6464d61
+/*
6464d61
  * Contact a remote RPC service to discover whether it is responding
6464d61
  * to requests.
6464d61
  */
67a1db4
diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c
67a1db4
index 5015e94..c3434d5 100644
67a1db4
--- a/support/nfs/conffile.c
67a1db4
+++ b/support/nfs/conffile.c
67a1db4
@@ -565,7 +565,7 @@ cleanup:
67a1db4
 }
67a1db4
 
67a1db4
 struct conf_list *
67a1db4
-conf_get_tag_list(char *section)
67a1db4
+conf_get_tag_list(char *section, char *arg)
67a1db4
 {
67a1db4
 	struct conf_list *list = 0;
67a1db4
 	struct conf_list_node *node;
67a1db4
@@ -579,6 +579,8 @@ conf_get_tag_list(char *section)
67a1db4
 	cb = LIST_FIRST(&conf_bindings[conf_hash (section)]);
67a1db4
 	for (; cb; cb = LIST_NEXT(cb, link)) {
67a1db4
 		if (strcasecmp (section, cb->section) == 0) {
67a1db4
+			if (arg != NULL && strcasecmp(arg, cb->arg) != 0)
67a1db4
+				continue;
67a1db4
 			list->cnt++;
67a1db4
 			node = calloc(1, sizeof *node);
67a1db4
 			if (!node)
6464d61
diff --git a/support/nfs/getport.c b/support/nfs/getport.c
6464d61
index 3331ad4..081594c 100644
6464d61
--- a/support/nfs/getport.c
6464d61
+++ b/support/nfs/getport.c
6464d61
@@ -1102,3 +1102,25 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
6464d61
 
6464d61
 	return port;
6464d61
 }
6464d61
+
6464d61
+static const char *nfs_ns_pgmtbl[] = {
6464d61
+        "status",
6464d61
+        NULL,
6464d61
+};
6464d61
+
6464d61
+/*
6464d61
+ * nfs_probe_statd - use nfs_pmap_getport to see if statd is running locally
6464d61
+ *
6464d61
+ * Returns non-zero if statd is running locally.
6464d61
+ */
6464d61
+int nfs_probe_statd(void)
6464d61
+{
6464d61
+        struct sockaddr_in addr = {
6464d61
+                .sin_family             = AF_INET,
6464d61
+                .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
6464d61
+        };
6464d61
+        rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
6464d61
+
6464d61
+        return nfs_getport_ping((struct sockaddr *)(char *)&addr, sizeof(addr),
6464d61
+                                program, (rpcvers_t)1, IPPROTO_UDP);
6464d61
+}
67a1db4
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
67a1db4
index dfbef87..c035537 100644
67a1db4
--- a/tools/nfs-iostat/nfs-iostat.py
67a1db4
+++ b/tools/nfs-iostat/nfs-iostat.py
67a1db4
@@ -353,14 +353,14 @@ class DeviceData:
67a1db4
             exe_per_op = 0.0
67a1db4
 
67a1db4
         op += ':'
67a1db4
-        print('%s' % op.lower().ljust(15))
67a1db4
+        print('%s' % op.lower().ljust(15), end='')
67a1db4
         print('  ops/s\t\t   kB/s\t\t  kB/op\t\tretrans\t\tavg RTT (ms)\tavg exe (ms)')
67a1db4
 
67a1db4
-        print('\t\t%7.3f' % (ops / sample_time))
67a1db4
-        print('\t%7.3f' % (kilobytes / sample_time))
67a1db4
-        print('\t%7.3f' % kb_per_op)
67a1db4
-        print(' %7d (%3.1f%%)' % (retrans, retrans_percent))
67a1db4
-        print('\t%7.3f' % rtt_per_op)
67a1db4
+        print('\t\t%7.3f' % (ops / sample_time), end='')
67a1db4
+        print('\t%7.3f' % (kilobytes / sample_time), end='')
67a1db4
+        print('\t%7.3f' % kb_per_op, end='')
67a1db4
+        print(' %7d (%3.1f%%)' % (retrans, retrans_percent), end='')
67a1db4
+        print('\t%7.3f' % rtt_per_op, end='')
67a1db4
         print('\t%7.3f' % exe_per_op)
67a1db4
 
67a1db4
     def ops(self, sample_time):
67a1db4
@@ -392,7 +392,7 @@ class DeviceData:
67a1db4
         print()
67a1db4
 
67a1db4
         print('   op/s\t\trpc bklog')
67a1db4
-        print('%7.2f' % (sends / sample_time))
67a1db4
+        print('%7.2f' % (sends / sample_time), end='')
67a1db4
         print('\t%7.2f' % backlog)
67a1db4
 
67a1db4
         if which == 0:
6464d61
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
6464d61
index 1df75c5..ac13fd4 100644
6464d61
--- a/utils/gssd/gssd.man
6464d61
+++ b/utils/gssd/gssd.man
6464d61
@@ -195,11 +195,28 @@ option when starting
6464d61
 .BR rpc.gssd .
6464d61
 .SH OPTIONS
6464d61
 .TP
6464d61
-.B -D
6464d61
-DNS Reverse lookups are not used for determining the
6464d61
-server names pass to GSSAPI. This option will reverses that and forces 
6464d61
-the use of DNS Reverse resolution of the server's IP address to 
6464d61
-retrieve the server name to use in GSAPI authentication.
6464d61
+.B \-D
6464d61
+The server name passed to GSSAPI for authentication is normally the
6464d61
+name exactly as requested.  e.g. for NFS
6464d61
+it is the server name in the "servername:/path" mount request.  Only if this
6464d61
+servername appears to be an IP address (IPv4 or IPv6) or an
6464d61
+unqualified name (no dots) will a reverse DNS lookup
6464d61
+will be performed to get the canoncial server name.
6464d61
+
6464d61
+If
6464d61
+.B \-D
6464d61
+is present, a reverse DNS lookup will
6464d61
+.I always
6464d61
+be used, even if the server name looks like a canonical name.  So it
6464d61
+is needed if partially qualified, or non canonical names are regularly
6464d61
+used.
6464d61
+
6464d61
+Using
6464d61
+.B \-D
6464d61
+can introduce a security vulnerability, so it is recommended that
6464d61
+.B \-D
6464d61
+not be used, and that canonical names always be used when requesting
6464d61
+services.
6464d61
 .TP
6464d61
 .B -f
6464d61
 Runs
6464d61
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
6464d61
index af1844c..b7e2bbb 100644
6464d61
--- a/utils/gssd/gssd_proc.c
6464d61
+++ b/utils/gssd/gssd_proc.c
6464d61
@@ -67,7 +67,6 @@
6464d61
 #include <errno.h>
6464d61
 #include <gssapi/gssapi.h>
6464d61
 #include <netdb.h>
6464d61
-#include <ctype.h>
6464d61
 
6464d61
 #include "gssd.h"
6464d61
 #include "err_util.h"
6464d61
@@ -176,7 +175,6 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
6464d61
 	char			*hostname;
6464d61
 	char			hbuf[NI_MAXHOST];
6464d61
 	unsigned char		buf[sizeof(struct in6_addr)];
6464d61
-	int			servername = 0;
6464d61
 
6464d61
 	if (avoid_dns) {
6464d61
 		/*
6464d61
@@ -184,15 +182,18 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
6464d61
 		 * If it is an IP address, do the DNS lookup otherwise
6464d61
 		 * skip the DNS lookup.
6464d61
 		 */
6464d61
-		servername = 0;
6464d61
-		if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1)
6464d61
-			servername = 1; /* IPv4 */
6464d61
-		else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1)
6464d61
-			servername = 1; /* or IPv6 */
6464d61
-
6464d61
-		if (servername) {
6464d61
+		int is_fqdn = 1;
6464d61
+		if (strchr(name, '.') == NULL)
6464d61
+			is_fqdn = 0; /* local name */
6464d61
+		else if (inet_pton(AF_INET, name, buf) == 1)
6464d61
+			is_fqdn = 0; /* IPv4 address */
6464d61
+		else if (inet_pton(AF_INET6, name, buf) == 1)
6464d61
+			is_fqdn = 0; /* IPv6 addrss */
6464d61
+
6464d61
+		if (is_fqdn) {
6464d61
 			return strdup(name);
6464d61
 		}
6464d61
+		/* Sorry, cannot avoid dns after all */
6464d61
 	}
6464d61
 
6464d61
 	switch (sa->sa_family) {
67a1db4
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
67a1db4
index 6275dd8..83b9651 100644
67a1db4
--- a/utils/gssd/krb5_util.c
67a1db4
+++ b/utils/gssd/krb5_util.c
67a1db4
@@ -231,7 +231,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
67a1db4
 				continue;
67a1db4
 			}
67a1db4
 			if (uid == 0 && !root_uses_machine_creds && 
67a1db4
-				strstr(namelist[i]->d_name, "_machine_")) {
67a1db4
+				strstr(namelist[i]->d_name, "machine_")) {
67a1db4
 				printerr(3, "CC '%s' not available to root\n",
67a1db4
 					 statname);
67a1db4
 				free(namelist[i]);
67a1db4
@@ -825,8 +825,10 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
67a1db4
 	myhostad[i+1] = 0;
67a1db4
 
67a1db4
 	retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
67a1db4
-	if (retval)
67a1db4
-		goto out;
67a1db4
+	if (retval) {
67a1db4
+		/* Don't use myhostname */
67a1db4
+		myhostname[0] = 0;
67a1db4
+	}
67a1db4
 
67a1db4
 	code = krb5_get_default_realm(context, &default_realm);
67a1db4
 	if (code) {
67a1db4
@@ -852,11 +854,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
67a1db4
 	}
67a1db4
 
67a1db4
 	/*
67a1db4
-	 * Try the "appropriate" realm first, and if nothing found for that
67a1db4
-	 * realm, try the default realm (if it hasn't already been tried).
67a1db4
+	 * Make sure the preferred_realm, which may have been explicitly set
67a1db4
+	 * on the command line, is tried first. If nothing is found go on with
67a1db4
+	 * the host and local default realm (if that hasn't already been tried).
67a1db4
 	 */
67a1db4
 	i = 0;
67a1db4
 	realm = realmnames[i];
67a1db4
+
67a1db4
+	if (strcmp (realm, preferred_realm) != 0) {
67a1db4
+		realm = preferred_realm;
67a1db4
+		/* resetting the realmnames index */
67a1db4
+		i = -1;
67a1db4
+	}
67a1db4
+
67a1db4
 	while (1) {
67a1db4
 		if (realm == NULL) {
67a1db4
 			tried_all = 1;
67a1db4
@@ -883,6 +893,8 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
67a1db4
 								myhostad,
67a1db4
 								NULL);
67a1db4
 			} else {
67a1db4
+				if (!myhostname[0])
67a1db4
+					continue;
67a1db4
 				snprintf(spn, sizeof(spn), "%s/%s@%s",
67a1db4
 					 svcnames[j], myhostname, realm);
67a1db4
 				code = krb5_build_principal_ext(context, &princ,
67a1db4
@@ -1236,7 +1248,7 @@ gssd_refresh_krb5_machine_credential(char *hostname,
67a1db4
 	krb5_keytab kt = NULL;;
67a1db4
 	int retval = 0;
67a1db4
 	char *k5err = NULL;
67a1db4
-	const char *svcnames[5] = { "$", "root", "nfs", "host", NULL };
67a1db4
+	const char *svcnames[] = { "$", "root", "nfs", "host", NULL };
67a1db4
 
67a1db4
 	/*
67a1db4
 	 * If a specific service name was specified, use it.
67a1db4
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
67a1db4
index beba9c4..b6c6231 100644
67a1db4
--- a/utils/idmapd/idmapd.c
67a1db4
+++ b/utils/idmapd/idmapd.c
67a1db4
@@ -502,7 +502,7 @@ nfsdcb(int UNUSED(fd), short which, void *data)
67a1db4
 	struct idmap_client *ic = data;
67a1db4
 	struct idmap_msg im;
67a1db4
 	u_char buf[IDMAP_MAXMSGSZ + 1];
67a1db4
-	size_t len;
67a1db4
+	ssize_t len;
67a1db4
 	ssize_t bsiz;
67a1db4
 	char *bp, typebuf[IDMAP_MAXMSGSZ],
67a1db4
 		buf1[IDMAP_MAXMSGSZ], authbuf[IDMAP_MAXMSGSZ], *p;
67a1db4
@@ -511,10 +511,14 @@ nfsdcb(int UNUSED(fd), short which, void *data)
67a1db4
 	if (which != EV_READ)
67a1db4
 		goto out;
67a1db4
 
67a1db4
-	if ((len = read(ic->ic_fd, buf, sizeof(buf))) <= 0) {
67a1db4
+	len = read(ic->ic_fd, buf, sizeof(buf));
67a1db4
+	if (len == 0)
67a1db4
+		/* No upcall to read; not necessarily a problem: */
67a1db4
+		return;
67a1db4
+	if (len < 0) {
67a1db4
 		xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)",
67a1db4
-			     ic->ic_path, len?errno:0, 
67a1db4
-			     len?strerror(errno):"End of File");
67a1db4
+			     ic->ic_path, errno,
67a1db4
+			     strerror(errno));
67a1db4
 		nfsdreopen_one(ic);
67a1db4
 		return;
67a1db4
 	}
67a1db4
diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
67a1db4
index 6f2ee75..68b9f93 100644
67a1db4
--- a/utils/mount/configfile.c
67a1db4
+++ b/utils/mount/configfile.c
67a1db4
@@ -73,6 +73,8 @@ struct mnt_alias {
67a1db4
 };
67a1db4
 int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
67a1db4
 
67a1db4
+static int strict;
67a1db4
+
67a1db4
 /*
67a1db4
  * See if the option is an alias, if so return the 
67a1db4
  * real mount option along with the argument type.
67a1db4
@@ -286,7 +288,7 @@ conf_parse_mntopts(char *section, char *arg, char *opts)
67a1db4
 	char *nvalue, *ptr;
67a1db4
 	int argtype;
67a1db4
 
67a1db4
-	list = conf_get_tag_list(section);
67a1db4
+	list = conf_get_tag_list(section, arg);
67a1db4
 	TAILQ_FOREACH(node, &list->fields, link) {
67a1db4
 		/*
67a1db4
 		 * Do not overwrite options if already exists 
67a1db4
@@ -310,7 +312,15 @@ conf_parse_mntopts(char *section, char *arg, char *opts)
67a1db4
 		if (strcasecmp(value, "false") == 0) {
67a1db4
 			if (argtype != MNT_NOARG)
67a1db4
 				snprintf(buf, BUFSIZ, "no%s", field);
67a1db4
+			else if (strcasecmp(field, "bg") == 0)
67a1db4
+				snprintf(buf, BUFSIZ, "fg");
67a1db4
+			else if (strcasecmp(field, "fg") == 0)
67a1db4
+				snprintf(buf, BUFSIZ, "bg");
67a1db4
+			else if (strcasecmp(field, "sloppy") == 0)
67a1db4
+				strict = 1;
67a1db4
 		} else if (strcasecmp(value, "true") == 0) {
67a1db4
+			if ((strcasecmp(field, "sloppy") == 0) && strict)
67a1db4
+				continue;
67a1db4
 			snprintf(buf, BUFSIZ, "%s", field);
67a1db4
 		} else {
67a1db4
 			nvalue = strdup(value);
67a1db4
@@ -345,6 +355,7 @@ char *conf_get_mntopts(char *spec, char *mount_point,
67a1db4
 	char *ptr, *server, *config_opts;
67a1db4
 	int optlen = 0;
67a1db4
 
67a1db4
+	strict = 0;
67a1db4
 	SLIST_INIT(&head;;
67a1db4
 	list_size = 0;
67a1db4
 	/*
6464d61
diff --git a/utils/mount/network.c b/utils/mount/network.c
6464d61
index 4be48cd..e2cdcaf 100644
6464d61
--- a/utils/mount/network.c
6464d61
+++ b/utils/mount/network.c
6464d61
@@ -65,11 +65,6 @@ extern int nfs_mount_data_version;
6464d61
 extern char *progname;
6464d61
 extern int verbose;
6464d61
 
6464d61
-static const char *nfs_ns_pgmtbl[] = {
6464d61
-	"status",
6464d61
-	NULL,
6464d61
-};
6464d61
-
6464d61
 static const char *nfs_mnt_pgmtbl[] = {
6464d61
 	"mount",
6464d61
 	"mountd",
6464d61
@@ -761,18 +756,6 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
6464d61
 					&nfs_server->pmap);
6464d61
 }
6464d61
 
6464d61
-static int nfs_probe_statd(void)
6464d61
-{
6464d61
-	struct sockaddr_in addr = {
6464d61
-		.sin_family		= AF_INET,
6464d61
-		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
6464d61
-	};
6464d61
-	rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
6464d61
-
6464d61
-	return nfs_getport_ping(SAFE_SOCKADDR(&addr), sizeof(addr),
6464d61
-				program, (rpcvers_t)1, IPPROTO_UDP);
6464d61
-}
6464d61
-
6464d61
 /**
6464d61
  * start_statd - attempt to start rpc.statd
6464d61
  *
6464d61
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
6464d61
index a8ec46c..2a42b93 100644
6464d61
--- a/utils/mount/nfs.man
6464d61
+++ b/utils/mount/nfs.man
6464d61
@@ -84,6 +84,20 @@ in
6464d61
 .SS "Options supported by all versions"
6464d61
 These options are valid to use with any NFS version.
6464d61
 .TP 1.5i
6464d61
+.BI nfsvers= n
6464d61
+The NFS protocol version number used to contact the server's NFS service.
6464d61
+If the server does not support the requested version, the mount request 
6464d61
+fails.
6464d61
+If this option is not specified, the client negotiates a suitable version 
6464d61
+with
6464d61
+the server, trying version 4 first, version 3 second, and version 2 last.
6464d61
+.TP 1.5i
6464d61
+.BI vers= n
6464d61
+This option is an alternative to the
6464d61
+.B nfsvers
6464d61
+option.
6464d61
+It is included for compatibility with other operating systems
6464d61
+.TP 1.5i
6464d61
 .BR soft " / " hard
6464d61
 Determines the recovery behavior of the NFS client
6464d61
 after an NFS request times out.
6464d61
@@ -621,18 +635,6 @@ Using this option ensures that
6464d61
 reports the proper maximum component length to applications
6464d61
 in such cases.
6464d61
 .TP 1.5i
6464d61
-.BI nfsvers= n
6464d61
-The NFS protocol version number used to contact the server's NFS service.
6464d61
-If the server does not support the requested version, the mount request fails.
6464d61
-If this option is not specified, the client negotiates a suitable version with
6464d61
-the server, trying version 4 first, version 3 second, and version 2 last.
6464d61
-.TP 1.5i
6464d61
-.BI vers= n
6464d61
-This option is an alternative to the
6464d61
-.B nfsvers
6464d61
-option.
6464d61
-It is included for compatibility with other operating systems.
6464d61
-.TP 1.5i
6464d61
 .BR lock " / " nolock
6464d61
 Selects whether to use the NLM sideband protocol to lock files on the server.
6464d61
 If neither option is specified (or if
6464d61
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
6464d61
index 737927c..517aa62 100644
6464d61
--- a/utils/mountd/cache.c
6464d61
+++ b/utils/mountd/cache.c
6464d61
@@ -347,20 +347,26 @@ static char *next_mnt(void **v, char *p)
6464d61
 
6464d61
 static int is_subdirectory(char *child, char *parent)
6464d61
 {
6464d61
+	/* Check is child is strictly a subdirectory of
6464d61
+	 * parent or a more distant descendant.
6464d61
+	 */
6464d61
 	size_t l = strlen(parent);
6464d61
 
6464d61
-	if (strcmp(parent, "/") == 0)
6464d61
+	if (strcmp(parent, "/") == 0 && child[1] != 0)
6464d61
 		return 1;
6464d61
 
6464d61
-	return strcmp(child, parent) == 0
6464d61
-		|| (strncmp(child, parent, l) == 0 && child[l] == '/');
6464d61
+	return (strncmp(child, parent, l) == 0 && child[l] == '/');
6464d61
 }
6464d61
 
6464d61
 static int path_matches(nfs_export *exp, char *path)
6464d61
 {
6464d61
-	if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
6464d61
-		return is_subdirectory(path, exp->m_export.e_path);
6464d61
-	return strcmp(path, exp->m_export.e_path) == 0;
6464d61
+	/* Does the path match the export?  I.e. is it an
6464d61
+	 * exact match, or does the export have CROSSMOUNT, and path
6464d61
+	 * is a descendant?
6464d61
+	 */
6464d61
+	return strcmp(path, exp->m_export.e_path) == 0
6464d61
+		|| ((exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
6464d61
+		    && is_subdirectory(path, exp->m_export.e_path));
6464d61
 }
6464d61
 
6464d61
 static int
6464d61
@@ -369,15 +375,13 @@ export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
6464d61
 	return path_matches(exp, path) && client_matches(exp, dom, ai);
6464d61
 }
6464d61
 
6464d61
-/* True iff e1 is a child of e2 and e2 has crossmnt set: */
6464d61
+/* True iff e1 is a child of e2 (or descendant) and e2 has crossmnt set: */
6464d61
 static bool subexport(struct exportent *e1, struct exportent *e2)
6464d61
 {
6464d61
 	char *p1 = e1->e_path, *p2 = e2->e_path;
6464d61
-	size_t l2 = strlen(p2);
6464d61
 
6464d61
 	return e2->e_flags & NFSEXP_CROSSMOUNT
6464d61
-		&& strncmp(p1, p2, l2) == 0
6464d61
-		&& p1[l2] == '/';
6464d61
+		&& is_subdirectory(p1, p2);
6464d61
 }
6464d61
 
6464d61
 struct parsed_fsid {
67a1db4
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
67a1db4
index e87c0a9..6db92f0 100644
67a1db4
--- a/utils/nfsd/nfsd.c
67a1db4
+++ b/utils/nfsd/nfsd.c
67a1db4
@@ -99,8 +99,8 @@ main(int argc, char **argv)
67a1db4
 	char *p, *progname, *port;
67a1db4
 	char *haddr = NULL;
67a1db4
 	int	socket_up = 0;
67a1db4
-	int minorvers41 = 0;	/* nfsv4 minor version */
67a1db4
-	unsigned int versbits = NFSCTL_ALLBITS;
67a1db4
+	int minorvers = NFS4_VERDEFAULT;	/* nfsv4 minor version */
67a1db4
+	unsigned int versbits = NFSCTL_VERDEFAULT;
67a1db4
 	unsigned int protobits = NFSCTL_ALLBITS;
67a1db4
 	unsigned int proto4 = 0;
67a1db4
 	unsigned int proto6 = 0;
67a1db4
@@ -160,11 +160,11 @@ main(int argc, char **argv)
67a1db4
 			case 4:
67a1db4
 				if (*p == '.') {
67a1db4
 					int i = atoi(p+1);
67a1db4
-					if (i != 1) {
67a1db4
+					if (i > 2) {
67a1db4
 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
67a1db4
 						exit(1);
67a1db4
 					}
67a1db4
-					minorvers41 = -1;
67a1db4
+					NFSCTL_VERUNSET(minorvers, i);
67a1db4
 					break;
67a1db4
 				}
67a1db4
 			case 3:
67a1db4
@@ -181,11 +181,11 @@ main(int argc, char **argv)
67a1db4
 			case 4:
67a1db4
 				if (*p == '.') {
67a1db4
 					int i = atoi(p+1);
67a1db4
-					if (i != 1) {
67a1db4
+					if (i > 2) {
67a1db4
 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
67a1db4
 						exit(1);
67a1db4
 					}
67a1db4
-					minorvers41 = 1;
67a1db4
+					NFSCTL_VERSET(minorvers, i);
67a1db4
 					break;
67a1db4
 				}
67a1db4
 			case 3:
67a1db4
@@ -282,7 +282,7 @@ main(int argc, char **argv)
67a1db4
 	 * registered with rpcbind. Note that on older kernels w/o the right
67a1db4
 	 * interfaces, these are a no-op.
67a1db4
 	 */
67a1db4
-	nfssvc_setvers(versbits, minorvers41);
67a1db4
+	nfssvc_setvers(versbits, minorvers);
67a1db4
  
67a1db4
 	error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
67a1db4
 	if (!error)
67a1db4
diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c
67a1db4
index 683008e..8b85846 100644
67a1db4
--- a/utils/nfsd/nfssvc.c
67a1db4
+++ b/utils/nfsd/nfssvc.c
67a1db4
@@ -269,7 +269,7 @@ nfssvc_set_sockets(const int family, const unsigned int protobits,
67a1db4
 }
67a1db4
 
67a1db4
 void
67a1db4
-nfssvc_setvers(unsigned int ctlbits, int minorvers41)
67a1db4
+nfssvc_setvers(unsigned int ctlbits, int minorvers)
67a1db4
 {
67a1db4
 	int fd, n, off;
67a1db4
 	char *ptr;
67a1db4
@@ -280,9 +280,12 @@ nfssvc_setvers(unsigned int ctlbits, int minorvers41)
67a1db4
 	if (fd < 0)
67a1db4
 		return;
67a1db4
 
67a1db4
-	if (minorvers41)
67a1db4
-		off += snprintf(ptr+off, sizeof(buf) - off, "%c4.1",
67a1db4
-				minorvers41 > 0 ? '+' : '-');
67a1db4
+	for (n = NFS4_MINMINOR; n <= NFS4_MAXMINOR; n++) {
67a1db4
+		if (NFSCTL_VERISSET(minorvers, n)) 
67a1db4
+			off += snprintf(ptr+off, sizeof(buf) - off, "+4.%d ", n);
67a1db4
+		else			
67a1db4
+			off += snprintf(ptr+off, sizeof(buf) - off, "-4.%d ", n);
67a1db4
+	}
67a1db4
 	for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
67a1db4
 		if (NFSCTL_VERISSET(ctlbits, n))
67a1db4
 		    off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n);
6464d61
diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man
6464d61
index 47007df..6940788 100644
6464d61
--- a/utils/nfsdcltrack/nfsdcltrack.man
6464d61
+++ b/utils/nfsdcltrack/nfsdcltrack.man
6464d61
@@ -1,53 +1,3 @@
6464d61
-.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)
6464d61
-.\"
6464d61
-.\" Standard preamble:
6464d61
-.\" ========================================================================
6464d61
-.de Sp \" Vertical space (when we can't use .PP)
6464d61
-.if t .sp .5v
6464d61
-.if n .sp
6464d61
-..
6464d61
-.de Vb \" Begin verbatim text
6464d61
-.ft CW
6464d61
-.nf
6464d61
-.ne \\$1
6464d61
-..
6464d61
-.de Ve \" End verbatim text
6464d61
-.ft R
6464d61
-.fi
6464d61
-..
6464d61
-.\" Set up some character translations and predefined strings.  \*(-- will
6464d61
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
6464d61
-.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
6464d61
-.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
6464d61
-.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
6464d61
-.\" nothing in troff, for use with C<>.
6464d61
-.tr \(*W-
6464d61
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
6464d61
-.ie n \{\
6464d61
-.    ds -- \(*W-
6464d61
-.    ds PI pi
6464d61
-.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
6464d61
-.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
6464d61
-.    ds L" ""
6464d61
-.    ds R" ""
6464d61
-.    ds C` ""
6464d61
-.    ds C' ""
6464d61
-'br\}
6464d61
-.el\{\
6464d61
-.    ds -- \|\(em\|
6464d61
-.    ds PI \(*p
6464d61
-.    ds L" ``
6464d61
-.    ds R" ''
6464d61
-'br\}
6464d61
-.\"
6464d61
-.\" Escape single quotes in literal strings from groff's Unicode transform.
6464d61
-.ie \n(.g .ds Aq \(aq
6464d61
-.el       .ds Aq '
6464d61
-.\"
6464d61
-.\" If the F register is turned on, we'll generate index entries on stderr for
6464d61
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
6464d61
-.\" entries marked with X<> in POD.  Of course, you'll have to process the
6464d61
-.\" output yourself in some meaningful fashion.
6464d61
 .ie \nF \{\
6464d61
 .    de IX
6464d61
 .    tm Index:\\$1\t\\n%\t"\\$2"
6464d61
@@ -59,70 +9,6 @@
6464d61
 .    de IX
6464d61
 ..
6464d61
 .\}
6464d61
-.\"
6464d61
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
6464d61
-.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
6464d61
-.    \" fudge factors for nroff and troff
6464d61
-.if n \{\
6464d61
-.    ds #H 0
6464d61
-.    ds #V .8m
6464d61
-.    ds #F .3m
6464d61
-.    ds #[ \f1
6464d61
-.    ds #] \fP
6464d61
-.\}
6464d61
-.if t \{\
6464d61
-.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
6464d61
-.    ds #V .6m
6464d61
-.    ds #F 0
6464d61
-.    ds #[ \&
6464d61
-.    ds #] \&
6464d61
-.\}
6464d61
-.    \" simple accents for nroff and troff
6464d61
-.if n \{\
6464d61
-.    ds ' \&
6464d61
-.    ds ` \&
6464d61
-.    ds ^ \&
6464d61
-.    ds , \&
6464d61
-.    ds ~ ~
6464d61
-.    ds /
6464d61
-.\}
6464d61
-.if t \{\
6464d61
-.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
6464d61
-.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
6464d61
-.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
6464d61
-.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
6464d61
-.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
6464d61
-.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
6464d61
-.\}
6464d61
-.    \" troff and (daisy-wheel) nroff accents
6464d61
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
6464d61
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
6464d61
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
6464d61
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
6464d61
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
6464d61
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
6464d61
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
6464d61
-.ds ae a\h'-(\w'a'u*4/10)'e
6464d61
-.ds Ae A\h'-(\w'A'u*4/10)'E
6464d61
-.    \" corrections for vroff
6464d61
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
6464d61
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
6464d61
-.    \" for low resolution devices (crt and lpr)
6464d61
-.if \n(.H>23 .if \n(.V>19 \
6464d61
-\{\
6464d61
-.    ds : e
6464d61
-.    ds 8 ss
6464d61
-.    ds o a
6464d61
-.    ds d- d\h'-1'\(ga
6464d61
-.    ds D- D\h'-1'\(hy
6464d61
-.    ds th \o'bp'
6464d61
-.    ds Th \o'LP'
6464d61
-.    ds ae ae
6464d61
-.    ds Ae AE
6464d61
-.\}
6464d61
-.rm #[ #] #H #V #F C
6464d61
-.\" ========================================================================
6464d61
-.\"
6464d61
 .IX Title "NFSDCLTRACK 8"
6464d61
 .TH NFSDCLTRACK 8 "2012-10-24" "" ""
6464d61
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
6464d61
diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
6464d61
index c0675c4..737a219 100644
6464d61
--- a/utils/nfsidmap/Makefile.am
6464d61
+++ b/utils/nfsidmap/Makefile.am
6464d61
@@ -1,9 +1,10 @@
6464d61
 ## Process this file with automake to produce Makefile.in
6464d61
 
6464d61
 man8_MANS = nfsidmap.man
6464d61
-
6464d61
 sbin_PROGRAMS	= nfsidmap
6464d61
+
6464d61
 nfsidmap_SOURCES = nfsidmap.c
6464d61
 nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
6464d61
 
6464d61
 MAINTAINERCLEANFILES = Makefile.in
6464d61
+EXTRA_DIST = id_resolver.conf
6464d61
diff --git a/utils/nfsidmap/id_resolver.conf b/utils/nfsidmap/id_resolver.conf
6464d61
new file mode 100644
6464d61
index 0000000..2c156c6
6464d61
--- /dev/null
6464d61
+++ b/utils/nfsidmap/id_resolver.conf
6464d61
@@ -0,0 +1 @@
6464d61
+create	id_resolver	*	*	/usr/sbin/nfsidmap -t 600 %k %d
6464d61
diff --git a/utils/statd/statd.c b/utils/statd/statd.c
6464d61
index 652546c..8c51bcc 100644
6464d61
--- a/utils/statd/statd.c
6464d61
+++ b/utils/statd/statd.c
6464d61
@@ -28,6 +28,7 @@
6464d61
 
6464d61
 #include "statd.h"
6464d61
 #include "nfslib.h"
6464d61
+#include "nfsrpc.h"
6464d61
 #include "nsm.h"
6464d61
 
6464d61
 /* Socket operations */
6464d61
@@ -237,6 +238,12 @@ int main (int argc, char **argv)
6464d61
 	/* Set hostname */
6464d61
 	MY_NAME = NULL;
6464d61
 
6464d61
+	/* Refuse to start if another statd is running */
6464d61
+	if (nfs_probe_statd()) {
6464d61
+		fprintf(stderr, "Statd service already running!\n");
6464d61
+		exit(1);
6464d61
+	}
6464d61
+
6464d61
 	/* Process command line switches */
6464d61
 	while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:L", longopts, NULL)) != EOF) {
6464d61
 		switch (arg) {