[autofs/f20] add fixes for RHEL-7 bug related to use of UDP during NFSv4 mount and internal hosts map not working

Ian Kent iankent at fedoraproject.org
Tue Nov 19 03:43:19 UTC 2013


commit 96bffb67907f94679781a9a0843386784a5b9423
Author: Ian Kent <ikent at redhat.com>
Date:   Tue Nov 19 11:42:03 2013 +0800

    add fixes for RHEL-7 bug related to use of UDP during NFSv4 mount and internal hosts map not working.

 autofs-5.0.7-fix-get_nfs_info-probe.patch          |   94 ++++++
 autofs-5.0.7-fix-portmap-lookup.patch              |  211 ++++++++++++
 ...probe-specific-nfs-version-when-requested.patch |   40 +++
 autofs-5.0.8-fix-ipv6-libtirpc-getport.patch       |  341 ++++++++++++++++++++
 autofs.spec                                        |   18 +-
 5 files changed, 703 insertions(+), 1 deletions(-)
---
diff --git a/autofs-5.0.7-fix-get_nfs_info-probe.patch b/autofs-5.0.7-fix-get_nfs_info-probe.patch
new file mode 100644
index 0000000..90d7a1e
--- /dev/null
+++ b/autofs-5.0.7-fix-get_nfs_info-probe.patch
@@ -0,0 +1,94 @@
+autofs-5.0.7 - fix get_nfs_info() probe
+
+From: Ian Kent <ikent at redhat.com>
+
+A recent contributed patch series changed the behaviour of server
+probing to use port specification in the same way as mount.nfs(8).
+
+Unfortunately, if NFSv2 only is to be probed and the NFS port
+needs to be obtained, the probe fails unconditionally because
+no rpc client has yet been created.
+---
+ CHANGELOG            |    1 +
+ modules/replicated.c |   32 ++++++++++++++++++++------------
+ 2 files changed, 21 insertions(+), 12 deletions(-)
+
+--- autofs-5.0.7.orig/CHANGELOG
++++ autofs-5.0.7/CHANGELOG
+@@ -58,6 +58,7 @@
+ - add after sssd dependency to unit file.
+ - improve timeout option description.
+ - only probe specific nfs version if requested.
++- fix get_nfs_info() probe.
+ 
+ 25/07/2012 autofs-5.0.7
+ =======================
+--- autofs-5.0.7.orig/modules/replicated.c
++++ autofs-5.0.7/modules/replicated.c
+@@ -444,6 +444,11 @@ static unsigned int get_nfs_info(unsigne
+ 		      host->name, proto, version);
+ 
+ 	rpc_info->proto = proto;
++	if (port < 0)
++		rpc_info->port = NFS_PORT;
++	else if (port > 0)
++		rpc_info->port = port;
++
+ 	memset(&parms, 0, sizeof(struct pmap));
+ 	parms.pm_prog = NFS_PROGRAM;
+ 	parms.pm_prot = proto;
+@@ -451,11 +456,7 @@ static unsigned int get_nfs_info(unsigne
+ 	if (!(version & NFS4_REQUESTED))
+ 		goto v3_ver;
+ 
+-	if (port < 0)
+-		rpc_info->port = NFS_PORT;
+-	else if (port > 0)
+-		rpc_info->port = port;
+-	else {
++	if (!port) {
+ 		status = rpc_portmap_getclient(pm_info,
+ 				host->name, host->addr, host->addr_len,
+ 				proto, RPC_CLOSE_DEFAULT);
+@@ -515,7 +516,7 @@ v3_ver:
+ 	if (!(version & NFS3_REQUESTED))
+ 		goto v2_ver;
+ 
+-	if (port <= 0 && !(version & NFS4_REQUESTED && port == 0)) {
++	if (!port && !pm_info->client) {
+ 		status = rpc_portmap_getclient(pm_info,
+ 				host->name, host->addr, host->addr_len,
+ 				proto, RPC_CLOSE_DEFAULT);
+@@ -526,9 +527,7 @@ v3_ver:
+ 			goto done_ver;
+ 	}
+ 
+-	if (port > 0)
+-		rpc_info->port = port;
+-	else {
++	if (!port) {
+ 		parms.pm_vers = NFS3_VERSION;
+ 		status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
+ 		if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
+@@ -573,9 +572,18 @@ v2_ver:
+ 	if (!(version & NFS2_REQUESTED))
+ 		goto done_ver;
+ 
+-	if (port > 0)
+-		rpc_info->port = port;
+-	else {
++	if (!port && !pm_info->client) {
++		status = rpc_portmap_getclient(pm_info,
++				host->name, host->addr, host->addr_len,
++				proto, RPC_CLOSE_DEFAULT);
++		if (status == -EHOSTUNREACH) {
++			supported = status;
++			goto done_ver;
++		} else if (status)
++			goto done_ver;
++	}
++
++	if (!port) {
+ 		parms.pm_vers = NFS2_VERSION;
+ 		status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
+ 		if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
diff --git a/autofs-5.0.7-fix-portmap-lookup.patch b/autofs-5.0.7-fix-portmap-lookup.patch
new file mode 100644
index 0000000..1156218
--- /dev/null
+++ b/autofs-5.0.7-fix-portmap-lookup.patch
@@ -0,0 +1,211 @@
+autofs-5.0.7 - fix portmap lookup
+
+From: Ian Kent <ikent at redhat.com>
+
+The autofs RPC library has fallen behind some.
+
+When using IPv6 (rpbbind) version 3 or 4 is available whereas with IPv4
+(portmap) verions 2 and 3 are available.
+
+autofs uses the version defined by PMAPVERS in the portmap include files
+whereas it should be using the RPCBVERS defines when using libtirpc.
+
+In addition /etc/rpc should be used for program number lookup and
+/etc/services should be used to lookup rpcbind/protmap port number.
+
+This incompatibility only shows up when using IPv6 only.
+---
+ CHANGELOG           |    1 
+ aclocal.m4          |    2 +
+ configure           |   13 +++++++
+ include/config.h.in |    6 +++
+ lib/rpc_subs.c      |   92 ++++++++++++++++++++++++++++++++++++++++++++++++----
+ 5 files changed, 108 insertions(+), 6 deletions(-)
+
+--- autofs-5.0.7.orig/CHANGELOG
++++ autofs-5.0.7/CHANGELOG
+@@ -59,6 +59,7 @@
+ - improve timeout option description.
+ - only probe specific nfs version if requested.
+ - fix get_nfs_info() probe.
++- fix portmap lookup.
+ 
+ 25/07/2012 autofs-5.0.7
+ =======================
+--- autofs-5.0.7.orig/aclocal.m4
++++ autofs-5.0.7/aclocal.m4
+@@ -421,6 +421,8 @@ if test "$af_have_libtirpc" = "yes"; the
+     TIRPCLIB="-ltirpc"
+ fi
+ 
++AC_CHECK_FUNCS([getrpcbyname getservbyname])
++
+ # restore flags
+ CFLAGS="$af_check_libtirpc_save_cflags"
+ LDFLAGS="$af_check_libtirpc_save_ldflags"
+--- autofs-5.0.7.orig/configure
++++ autofs-5.0.7/configure
+@@ -3161,6 +3161,19 @@ $as_echo "#define TIRPC_WORKAROUND 1" >>
+     TIRPCLIB="-ltirpc"
+ fi
+ 
++for ac_func in getrpcbyname getservbyname
++do :
++  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
++if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
++  cat >>confdefs.h <<_ACEOF
++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
++_ACEOF
++
++fi
++done
++
++
+ # restore flags
+ CFLAGS="$af_check_libtirpc_save_cflags"
+ LDFLAGS="$af_check_libtirpc_save_ldflags"
+--- autofs-5.0.7.orig/include/config.h.in
++++ autofs-5.0.7/include/config.h.in
+@@ -21,6 +21,12 @@
+ /* define if you have E4FSCK */
+ #undef HAVE_E4FSCK
+ 
++/* Define to 1 if you have the `getrpcbyname' function. */
++#undef HAVE_GETRPCBYNAME
++
++/* Define to 1 if you have the `getservbyname' function. */
++#undef HAVE_GETSERVBYNAME
++
+ /* Define to 1 if you have the <inttypes.h> header file. */
+ #undef HAVE_INTTYPES_H
+ 
+--- autofs-5.0.7.orig/lib/rpc_subs.c
++++ autofs-5.0.7/lib/rpc_subs.c
+@@ -43,6 +43,14 @@
+                 } while (0)
+ #endif
+ 
++#ifdef WITH_LIBTIRPC
++const rpcprog_t rpcb_prog = RPCBPROG;
++const rpcvers_t rpcb_version = RPCBVERS;
++#else
++const rpcprog_t rpcb_prog = PMAPPROG;
++const rpcvers_t rpcb_version = PMAPVERS;
++#endif
++
+ #include "mount.h"
+ #include "rpc_subs.h"
+ #include "automount.h"
+@@ -259,6 +267,9 @@ static int rpc_do_create_client(struct s
+ 		laddr = (struct sockaddr *) &in4_laddr;
+ 		in4_raddr->sin_port = htons(info->port);
+ 		slen = sizeof(struct sockaddr_in);
++		/* Use rpcbind v2 for AF_INET */
++		if (info->program == rpcb_prog)
++			info->version = PMAPVERS;
+ 	} else if (addr->sa_family == AF_INET6) {
+ 		struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr;
+ 		in6_laddr.sin6_family = AF_INET6;
+@@ -315,6 +326,63 @@ static int rpc_do_create_client(struct s
+ }
+ #endif
+ 
++#if defined(HAVE_GETRPCBYNAME) || defined(HAVE_GETSERVBYNAME)
++static pthread_mutex_t rpcb_mutex = PTHREAD_MUTEX_INITIALIZER;
++#endif
++
++static rpcprog_t rpc_getrpcbyname(const rpcprog_t program)
++{
++#ifdef HAVE_GETRPCBYNAME
++	static const char *rpcb_pgmtbl[] = {
++		"rpcbind", "portmap", "portmapper", "sunrpc", NULL,
++	};
++	struct rpcent *entry;
++	rpcprog_t prog_number;
++	unsigned int i;
++
++	pthread_mutex_lock(&rpcb_mutex);
++	for (i = 0; rpcb_pgmtbl[i] != NULL; i++) {
++		entry = getrpcbyname(rpcb_pgmtbl[i]);
++		if (entry) {
++			prog_number = entry->r_number;
++			pthread_mutex_unlock(&rpcb_mutex);
++			return prog_number;
++		}
++	}
++	pthread_mutex_unlock(&rpcb_mutex);
++#endif
++	return program;
++}
++
++static unsigned short rpc_getrpcbport(const int proto)
++{
++#ifdef HAVE_GETSERVBYNAME
++	static const char *rpcb_netnametbl[] = {
++		"rpcbind", "portmapper", "sunrpc", NULL,
++	};
++	struct servent *entry;
++	struct protoent *p_ent;
++	unsigned short port;
++	unsigned int i;
++
++	pthread_mutex_lock(&rpcb_mutex);
++	p_ent = getprotobynumber(proto);
++	if (!p_ent)
++		goto done;
++	for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
++		entry = getservbyname(rpcb_netnametbl[i], p_ent->p_name);
++		if (entry) {
++			port = entry->s_port;
++			pthread_mutex_unlock(&rpcb_mutex);
++			return port;
++		}
++	}
++done:
++	pthread_mutex_unlock(&rpcb_mutex);
++#endif
++	return (unsigned short) PMAPPORT;
++}
++
+ /*
+  * Create an RPC client
+  */
+@@ -510,9 +578,15 @@ int rpc_portmap_getclient(struct conn_in
+ 	info->host = host;
+ 	info->addr = addr;
+ 	info->addr_len = addr_len;
+-	info->program = PMAPPROG;
+-	info->port = PMAPPORT;
+-	info->version = PMAPVERS;
++	info->program = rpc_getrpcbyname(rpcb_prog);
++	info->port = ntohs(rpc_getrpcbport(proto));
++	/*
++	 * When using libtirpc we might need to change the rpcbind version
++	 * to qurey AF_INET addresses. Since we might not have an address
++	 * yet set AF_INET rpcbind version in rpc_do_create_client() when
++	 * we always have an address.
++	 */
++	info->version = rpcb_version;
+ 	info->proto = proto;
+ 	info->send_sz = RPCSMALLMSGSIZE;
+ 	info->recv_sz = RPCSMALLMSGSIZE;
+@@ -555,9 +629,15 @@ int rpc_portmap_getport(struct conn_info
+ 		pmap_info.host = info->host;
+ 		pmap_info.addr = info->addr;
+ 		pmap_info.addr_len = info->addr_len;
+-		pmap_info.port = PMAPPORT;
+-		pmap_info.program = PMAPPROG;
+-		pmap_info.version = PMAPVERS;
++		pmap_info.port = ntohs(rpc_getrpcbport(info->proto));
++		pmap_info.program = rpc_getrpcbyname(rpcb_prog);
++		/*
++		 * When using libtirpc we might need to change the rpcbind
++		 * version to qurey AF_INET addresses. Since we might not
++		 * have an address yet set AF_INET rpcbind version in
++		 * rpc_do_create_client() when we always have an address.
++		 */
++		pmap_info.version = rpcb_version;
+ 		pmap_info.proto = info->proto;
+ 		pmap_info.send_sz = RPCSMALLMSGSIZE;
+ 		pmap_info.recv_sz = RPCSMALLMSGSIZE;
diff --git a/autofs-5.0.7-only-probe-specific-nfs-version-when-requested.patch b/autofs-5.0.7-only-probe-specific-nfs-version-when-requested.patch
new file mode 100644
index 0000000..bbd4f84
--- /dev/null
+++ b/autofs-5.0.7-only-probe-specific-nfs-version-when-requested.patch
@@ -0,0 +1,40 @@
+autofs-5.0.7 - only probe specific nfs version when requested
+
+From: Ian Kent <raven at themaw.net>
+
+If a specific NFS version is given as an option the set the probe flags
+to probe only that version.
+---
+ CHANGELOG           |    1 +
+ modules/mount_nfs.c |   10 +++++++++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+--- autofs-5.0.7.orig/CHANGELOG
++++ autofs-5.0.7/CHANGELOG
+@@ -57,6 +57,7 @@
+ - fix a couple of compiler warnings.
+ - add after sssd dependency to unit file.
+ - improve timeout option description.
++- only probe specific nfs version if requested.
+ 
+ 25/07/2012 autofs-5.0.7
+ =======================
+--- autofs-5.0.7.orig/modules/mount_nfs.c
++++ autofs-5.0.7/modules/mount_nfs.c
+@@ -146,7 +146,15 @@ int mount_mount(struct autofs_point *ap,
+ 				if (strncmp("vers=4", cp, o_len) == 0 ||
+ 				    strncmp("nfsvers=4", cp, o_len) == 0)
+ 					vers = NFS4_VERS_MASK | TCP_SUPPORTED;
+-				else if (strstr(cp, "port=") == cp &&
++				else if (strncmp("vers=3", cp, o_len) == 0 ||
++					 strncmp("nfsvers=3", cp, o_len) == 0) {
++					vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK);
++					vers |= NFS3_REQUESTED;
++				} else if (strncmp("vers=2", cp, o_len) == 0 ||
++					 strncmp("nfsvers=2", cp, o_len) == 0) {
++					vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK);
++					vers |= NFS2_REQUESTED;
++				} else if (strstr(cp, "port=") == cp &&
+ 					 o_len - 5 < 25) {
+ 					char optport[25];
+ 
diff --git a/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch b/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch
new file mode 100644
index 0000000..bf34446
--- /dev/null
+++ b/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch
@@ -0,0 +1,341 @@
+autofs-5.0.8 - fix ipv6 libtirpc getport
+
+From: Ian Kent <ikent at redhat.com>
+
+The method that was being used to obtain a service port number
+when using libtirpc was wrong.
+---
+ CHANGELOG      |    1 
+ lib/rpc_subs.c |  283 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 267 insertions(+), 17 deletions(-)
+
+--- autofs-5.0.7.orig/CHANGELOG
++++ autofs-5.0.7/CHANGELOG
+@@ -60,6 +60,7 @@
+ - only probe specific nfs version if requested.
+ - fix get_nfs_info() probe.
+ - fix portmap lookup.
++- fix ipv6 libtirpc getport.
+ 
+ 25/07/2012 autofs-5.0.7
+ =======================
+--- autofs-5.0.7.orig/lib/rpc_subs.c
++++ autofs-5.0.7/lib/rpc_subs.c
+@@ -234,6 +234,28 @@ static int rpc_do_create_client(struct s
+ 
+ 	return 0;
+ }
++static int rpc_getport(struct conn_info *info,
++		       struct pmap *parms, CLIENT *client)
++{
++	enum clnt_stat status;
++
++	/*
++	 * Check to see if server is up otherwise a getport will take
++	 * forever to timeout.
++	 */
++	status = clnt_call(client, PMAPPROC_NULL,
++			 (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0,
++			 info->timeout);
++
++	if (status == RPC_SUCCESS) {
++		status = clnt_call(client, PMAPPROC_GETPORT,
++				 (xdrproc_t) xdr_pmap, (caddr_t) parms,
++				 (xdrproc_t) xdr_u_short, (caddr_t) port,
++				 info->timeout);
++	}
++
++	return status;
++}
+ #else
+ static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, int *fd, CLIENT **client)
+ {
+@@ -267,9 +289,6 @@ static int rpc_do_create_client(struct s
+ 		laddr = (struct sockaddr *) &in4_laddr;
+ 		in4_raddr->sin_port = htons(info->port);
+ 		slen = sizeof(struct sockaddr_in);
+-		/* Use rpcbind v2 for AF_INET */
+-		if (info->program == rpcb_prog)
+-			info->version = PMAPVERS;
+ 	} else if (addr->sa_family == AF_INET6) {
+ 		struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr;
+ 		in6_laddr.sin6_family = AF_INET6;
+@@ -324,6 +343,244 @@ static int rpc_do_create_client(struct s
+ 
+ 	return 0;
+ }
++
++/*
++ * Thankfully nfs-utils had already dealt with this.
++ * Thanks to Chuck Lever for his nfs-utils patch series, much of
++ * which is used here.
++ */
++static pthread_mutex_t proto_mutex = PTHREAD_MUTEX_INITIALIZER;
++
++static enum clnt_stat rpc_get_netid(const sa_family_t family,
++				    const int protocol, char **netid)
++{
++	char *nc_protofmly, *nc_proto, *nc_netid;
++	struct netconfig *nconf;
++	struct protoent *proto;
++	void *handle;
++
++	switch (family) {
++	case AF_LOCAL:
++	case AF_INET:
++		nc_protofmly = NC_INET;
++		break;
++	case AF_INET6:
++		nc_protofmly = NC_INET6;
++		break;
++	default:
++		return RPC_UNKNOWNPROTO;
++        }
++
++	pthread_mutex_lock(&proto_mutex);
++	proto = getprotobynumber(protocol);
++	if (!proto) {
++		pthread_mutex_unlock(&proto_mutex);
++		return RPC_UNKNOWNPROTO;
++	}
++	nc_proto = strdup(proto->p_name);
++	pthread_mutex_unlock(&proto_mutex);
++	if (!nc_proto)
++		return RPC_SYSTEMERROR;
++
++	handle = setnetconfig();
++	while ((nconf = getnetconfig(handle)) != NULL) {
++		if (nconf->nc_protofmly != NULL &&
++		    strcmp(nconf->nc_protofmly, nc_protofmly) != 0)
++			continue;
++		if (nconf->nc_proto != NULL &&
++		    strcmp(nconf->nc_proto, nc_proto) != 0)
++			continue;
++
++		nc_netid = strdup(nconf->nc_netid);
++		if (!nc_netid) {
++			free(nc_proto);
++			return RPC_SYSTEMERROR;
++		}
++
++		*netid = nc_netid;
++	}
++	endnetconfig(handle);
++	free(nc_proto);
++
++	return RPC_SUCCESS;
++}
++
++static char *rpc_sockaddr2universal(const struct sockaddr *addr)
++{
++	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *) addr;
++	const struct sockaddr_un *sun = (const struct sockaddr_un *) addr;
++	const struct sockaddr_in *sin = (const struct sockaddr_in *) addr;
++	char buf[INET6_ADDRSTRLEN + 8 /* for port information */];
++	uint16_t port;
++	size_t count;
++	char *result;
++	int len;
++
++	switch (addr->sa_family) {
++	case AF_LOCAL:
++		return strndup(sun->sun_path, sizeof(sun->sun_path));
++	case AF_INET:
++		if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr,
++					buf, (socklen_t)sizeof(buf)) == NULL)
++			goto out_err;
++		port = ntohs(sin->sin_port);
++		break;
++	case AF_INET6:
++		if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
++					buf, (socklen_t)sizeof(buf)) == NULL)
++			goto out_err;
++		port = ntohs(sin6->sin6_port);
++		break;
++	default:
++		goto out_err;
++	}
++
++	count = sizeof(buf) - strlen(buf);
++	len = snprintf(buf + strlen(buf), count, ".%u.%u",
++			(unsigned)(port >> 8), (unsigned)(port & 0xff));
++	/* before glibc 2.0.6, snprintf(3) could return -1 */
++	if (len < 0 || (size_t)len > count)
++		goto out_err;
++
++	result = strdup(buf);
++	return result;
++
++out_err:
++        return NULL;
++}
++
++static int rpc_universal2port(const char *uaddr)
++{
++	char *addrstr;
++	char *p, *endptr;
++	unsigned long portlo, porthi;
++	int port = -1;
++
++	addrstr = strdup(uaddr);
++	if (!addrstr)
++		return -1;
++
++	p = strrchr(addrstr, '.');
++	if (!p)
++		goto out;
++
++	portlo = strtoul(p + 1, &endptr, 10);
++	if (*endptr != '\0' || portlo > 255)
++		goto out;
++	*p = '\0';
++
++        p = strrchr(addrstr, '.');
++        if (!p)
++                goto out;
++
++        porthi = strtoul(p + 1, &endptr, 10);
++        if (*endptr != '\0' || porthi > 255)
++                goto out;
++        *p = '\0';
++
++        port = (porthi << 8) | portlo;
++
++out:
++	free(addrstr);
++	return port;
++}
++
++static enum clnt_stat rpc_rpcb_getport(CLIENT *client,
++				       struct rpcb *parms,
++				       struct timeval timeout,
++				       unsigned short *port)
++{
++	rpcvers_t rpcb_version;
++	struct rpc_err rpcerr;
++	int s_port = 0;
++
++	for (rpcb_version = RPCBVERS_4;
++	     rpcb_version >= RPCBVERS_3;
++	     rpcb_version--) {
++		enum clnt_stat status;
++		char *uaddr = NULL;
++
++		CLNT_CONTROL(client, CLSET_VERS, (void *) &rpcb_version);
++		status = CLNT_CALL(client, (rpcproc_t) RPCBPROC_GETADDR,
++				  (xdrproc_t) xdr_rpcb, (void *) parms,
++				  (xdrproc_t) xdr_wrapstring, (void *) &uaddr,
++				  timeout);
++
++		switch (status) {
++		case RPC_SUCCESS:
++			if ((uaddr == NULL) || (uaddr[0] == '\0'))
++				return RPC_PROGNOTREGISTERED;
++
++			s_port = rpc_universal2port(uaddr);
++			xdr_free((xdrproc_t) xdr_wrapstring, (char *) &uaddr);
++			if (s_port == -1) {
++				return RPC_N2AXLATEFAILURE;
++			}
++			*port = s_port;
++			return RPC_SUCCESS;
++
++		case RPC_PROGVERSMISMATCH:
++			clnt_geterr(client, &rpcerr);
++			if (rpcerr.re_vers.low > RPCBVERS4)
++				return status;
++			continue;
++		case RPC_PROCUNAVAIL:
++		case RPC_PROGUNAVAIL:
++			continue;
++		default:
++                        /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */
++			return status;
++		}
++	}
++
++        if (s_port == 0)
++		return RPC_PROGNOTREGISTERED;
++
++        return RPC_PROCUNAVAIL;
++}
++
++static enum clnt_stat rpc_getport(struct conn_info *info,
++				  struct pmap *parms, CLIENT *client,
++				  unsigned short *port)
++{
++	enum clnt_stat status;
++	struct sockaddr *paddr, addr;
++	struct rpcb rpcb_parms;
++	char *netid, *raddr;
++
++	if (info->addr)
++		paddr = info->addr;
++	else {
++		if (!clnt_control(client, CLGET_SERVER_ADDR, (char *) &addr))
++			return RPC_UNKNOWNADDR;
++		paddr = &addr;
++	}
++
++	netid = NULL;
++	status = rpc_get_netid(paddr->sa_family, info->proto, &netid);
++	if (status != RPC_SUCCESS)
++		return status;
++
++	raddr = rpc_sockaddr2universal(paddr);
++	if (!raddr) {
++		free(netid);
++		return RPC_UNKNOWNADDR;
++	}
++
++	memset(&rpcb_parms, 0, sizeof(rpcb_parms));
++	rpcb_parms.r_prog   = parms->pm_prog;
++	rpcb_parms.r_vers   = parms->pm_vers;
++	rpcb_parms.r_netid  = netid;
++	rpcb_parms.r_addr   = raddr;
++	rpcb_parms.r_owner  = "";
++
++	status = rpc_rpcb_getport(client, &rpcb_parms, info->timeout, port);
++
++	free(netid);
++	free(raddr);
++
++	return status;
++}
+ #endif
+ 
+ #if defined(HAVE_GETRPCBYNAME) || defined(HAVE_GETSERVBYNAME)
+@@ -647,20 +904,7 @@ int rpc_portmap_getport(struct conn_info
+ 			return ret;
+ 	}
+ 
+-	/*
+-	 * Check to see if server is up otherwise a getport will take
+-	 * forever to timeout.
+-	 */
+-	status = clnt_call(client, PMAPPROC_NULL,
+-			 (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0,
+-			 pmap_info.timeout);
+-
+-	if (status == RPC_SUCCESS) {
+-		status = clnt_call(client, PMAPPROC_GETPORT,
+-				 (xdrproc_t) xdr_pmap, (caddr_t) parms,
+-				 (xdrproc_t) xdr_u_short, (caddr_t) port,
+-				 pmap_info.timeout);
+-	}
++	status = rpc_getport(&pmap_info, parms, client, port);
+ 
+ 	if (!info->client) {
+ 		/*
+@@ -867,6 +1111,11 @@ static int rpc_get_exports_proto(struct
+ 	clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) &info->timeout);
+ 
+ 	client->cl_auth = authunix_create_default();
++	if (client->cl_auth == NULL) {
++		error(LOGOPT_ANY, "auth create failed");
++		clnt_destroy(client);
++		return 0;
++	}
+ 
+ 	vers_entry = 0;
+ 	while (1) {
diff --git a/autofs.spec b/autofs.spec
index ab81854..e3568b8 100644
--- a/autofs.spec
+++ b/autofs.spec
@@ -8,7 +8,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems
 Name: autofs
 Version: 5.0.7
-Release: 30%{?dist}
+Release: 35%{?dist}
 Epoch: 1
 License: GPLv2+
 Group: System Environment/Daemons
@@ -100,6 +100,10 @@ Patch84: autofs-5.0.7-dont-override-LDFLAGS-in-make-rules.patch
 Patch85: autofs-5.0.7-fix-a-couple-of-compiler-warnings.patch
 Patch86: autofs-5.0.7-add-after-sssd-dependency-to-unit-file.patch
 Patch87: autofs-5.0.7-improve-timeout-option-description.patch
+Patch88: autofs-5.0.7-only-probe-specific-nfs-version-when-requested.patch
+Patch89: autofs-5.0.7-fix-get_nfs_info-probe.patch
+Patch90: autofs-5.0.7-fix-portmap-lookup.patch
+Patch91: autofs-5.0.8-fix-ipv6-libtirpc-getport.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 %if %{with_systemd}
 BuildRequires: systemd-units
@@ -244,6 +248,10 @@ echo %{version}-%{release} > .version
 %patch85 -p1
 %patch86 -p1
 %patch87 -p1
+%patch88 -p1
+%patch89 -p1
+%patch90 -p1
+%patch91 -p1
 
 %build
 LDFLAGS=-Wl,-z,now
@@ -335,6 +343,14 @@ fi
 %dir /etc/auto.master.d
 
 %changelog
+* Tue Nov 19 2013 Ian Kent <ikent at redhat.com> - 1:5.0.7-35
+- add fixes for RHEL-7 bug related to use of UDP during NFSv4 mount
+  and internal hosts map not working.
+  - only probe specific nfs version when requested
+  - fix get_nfs_info() probe.
+  - fix portmap lookup.
+  - fix ipv6 libtirpc getport.
+
 * Fri Nov 15 2013 Ian Kent <ikent at redhat.com> - 1:5.0.7-30
 - improve timeout option description (bz1029461).
 


More information about the scm-commits mailing list