Blame SOURCES/autofs-5.0.7-fix-portmap-lookup.patch

ab3a3d
autofs-5.0.7 - fix portmap lookup
ab3a3d
ab3a3d
From: Ian Kent <ikent@redhat.com>
ab3a3d
ab3a3d
The autofs RPC library has fallen behind some.
ab3a3d
ab3a3d
When using IPv6 (rpbbind) version 3 or 4 is available whereas with IPv4
ab3a3d
(portmap) verions 2 and 3 are available.
ab3a3d
ab3a3d
autofs uses the version defined by PMAPVERS in the portmap include files
ab3a3d
whereas it should be using the RPCBVERS defines when using libtirpc.
ab3a3d
ab3a3d
In addition /etc/rpc should be used for program number lookup and
ab3a3d
/etc/services should be used to lookup rpcbind/protmap port number.
ab3a3d
ab3a3d
This incompatibility only shows up when using IPv6 only.
ab3a3d
---
ab3a3d
 CHANGELOG           |    1 
ab3a3d
 aclocal.m4          |    2 +
ab3a3d
 configure           |   13 +++++++
ab3a3d
 include/config.h.in |    6 +++
ab3a3d
 lib/rpc_subs.c      |   92 ++++++++++++++++++++++++++++++++++++++++++++++++----
ab3a3d
 5 files changed, 108 insertions(+), 6 deletions(-)
ab3a3d
ab3a3d
--- autofs-5.0.7.orig/CHANGELOG
ab3a3d
+++ autofs-5.0.7/CHANGELOG
ab3a3d
@@ -62,6 +62,7 @@
ab3a3d
 - try and cleanup after dumpmaps.
ab3a3d
 - teach dumpmaps to output simple key value pairs.
ab3a3d
 - fix get_nfs_info() probe.
ab3a3d
+- fix portmap lookup.
ab3a3d
 
ab3a3d
 25/07/2012 autofs-5.0.7
ab3a3d
 =======================
ab3a3d
--- autofs-5.0.7.orig/aclocal.m4
ab3a3d
+++ autofs-5.0.7/aclocal.m4
ab3a3d
@@ -421,6 +421,8 @@ if test "$af_have_libtirpc" = "yes"; the
ab3a3d
     TIRPCLIB="-ltirpc"
ab3a3d
 fi
ab3a3d
 
ab3a3d
+AC_CHECK_FUNCS([getrpcbyname getservbyname])
ab3a3d
+
ab3a3d
 # restore flags
ab3a3d
 CFLAGS="$af_check_libtirpc_save_cflags"
ab3a3d
 LDFLAGS="$af_check_libtirpc_save_ldflags"
ab3a3d
--- autofs-5.0.7.orig/configure
ab3a3d
+++ autofs-5.0.7/configure
ab3a3d
@@ -3161,6 +3161,19 @@ $as_echo "#define TIRPC_WORKAROUND 1" >>
ab3a3d
     TIRPCLIB="-ltirpc"
ab3a3d
 fi
ab3a3d
 
ab3a3d
+for ac_func in getrpcbyname getservbyname
ab3a3d
+do :
ab3a3d
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ab3a3d
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
ab3a3d
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
ab3a3d
+  cat >>confdefs.h <<_ACEOF
ab3a3d
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
ab3a3d
+_ACEOF
ab3a3d
+
ab3a3d
+fi
ab3a3d
+done
ab3a3d
+
ab3a3d
+
ab3a3d
 # restore flags
ab3a3d
 CFLAGS="$af_check_libtirpc_save_cflags"
ab3a3d
 LDFLAGS="$af_check_libtirpc_save_ldflags"
ab3a3d
--- autofs-5.0.7.orig/include/config.h.in
ab3a3d
+++ autofs-5.0.7/include/config.h.in
ab3a3d
@@ -21,6 +21,12 @@
ab3a3d
 /* define if you have E4FSCK */
ab3a3d
 #undef HAVE_E4FSCK
ab3a3d
 
ab3a3d
+/* Define to 1 if you have the `getrpcbyname' function. */
ab3a3d
+#undef HAVE_GETRPCBYNAME
ab3a3d
+
ab3a3d
+/* Define to 1 if you have the `getservbyname' function. */
ab3a3d
+#undef HAVE_GETSERVBYNAME
ab3a3d
+
ab3a3d
 /* Define to 1 if you have the <inttypes.h> header file. */
ab3a3d
 #undef HAVE_INTTYPES_H
ab3a3d
 
ab3a3d
--- autofs-5.0.7.orig/lib/rpc_subs.c
ab3a3d
+++ autofs-5.0.7/lib/rpc_subs.c
ab3a3d
@@ -43,6 +43,14 @@
ab3a3d
                 } while (0)
ab3a3d
 #endif
ab3a3d
 
ab3a3d
+#ifdef WITH_LIBTIRPC
ab3a3d
+const rpcprog_t rpcb_prog = RPCBPROG;
ab3a3d
+const rpcvers_t rpcb_version = RPCBVERS;
ab3a3d
+#else
ab3a3d
+const rpcprog_t rpcb_prog = PMAPPROG;
ab3a3d
+const rpcvers_t rpcb_version = PMAPVERS;
ab3a3d
+#endif
ab3a3d
+
ab3a3d
 #include "mount.h"
ab3a3d
 #include "rpc_subs.h"
ab3a3d
 #include "automount.h"
ab3a3d
@@ -259,6 +267,9 @@ static int rpc_do_create_client(struct s
ab3a3d
 		laddr = (struct sockaddr *) &in4_laddr;
ab3a3d
 		in4_raddr->sin_port = htons(info->port);
ab3a3d
 		slen = sizeof(struct sockaddr_in);
ab3a3d
+		/* Use rpcbind v2 for AF_INET */
ab3a3d
+		if (info->program == rpcb_prog)
ab3a3d
+			info->version = PMAPVERS;
ab3a3d
 	} else if (addr->sa_family == AF_INET6) {
ab3a3d
 		struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr;
ab3a3d
 		in6_laddr.sin6_family = AF_INET6;
ab3a3d
@@ -315,6 +326,63 @@ static int rpc_do_create_client(struct s
ab3a3d
 }
ab3a3d
 #endif
ab3a3d
 
ab3a3d
+#if defined(HAVE_GETRPCBYNAME) || defined(HAVE_GETSERVBYNAME)
ab3a3d
+static pthread_mutex_t rpcb_mutex = PTHREAD_MUTEX_INITIALIZER;
ab3a3d
+#endif
ab3a3d
+
ab3a3d
+static rpcprog_t rpc_getrpcbyname(const rpcprog_t program)
ab3a3d
+{
ab3a3d
+#ifdef HAVE_GETRPCBYNAME
ab3a3d
+	static const char *rpcb_pgmtbl[] = {
ab3a3d
+		"rpcbind", "portmap", "portmapper", "sunrpc", NULL,
ab3a3d
+	};
ab3a3d
+	struct rpcent *entry;
ab3a3d
+	rpcprog_t prog_number;
ab3a3d
+	unsigned int i;
ab3a3d
+
ab3a3d
+	pthread_mutex_lock(&rpcb_mutex);
ab3a3d
+	for (i = 0; rpcb_pgmtbl[i] != NULL; i++) {
ab3a3d
+		entry = getrpcbyname(rpcb_pgmtbl[i]);
ab3a3d
+		if (entry) {
ab3a3d
+			prog_number = entry->r_number;
ab3a3d
+			pthread_mutex_unlock(&rpcb_mutex);
ab3a3d
+			return prog_number;
ab3a3d
+		}
ab3a3d
+	}
ab3a3d
+	pthread_mutex_unlock(&rpcb_mutex);
ab3a3d
+#endif
ab3a3d
+	return program;
ab3a3d
+}
ab3a3d
+
ab3a3d
+static unsigned short rpc_getrpcbport(const int proto)
ab3a3d
+{
ab3a3d
+#ifdef HAVE_GETSERVBYNAME
ab3a3d
+	static const char *rpcb_netnametbl[] = {
ab3a3d
+		"rpcbind", "portmapper", "sunrpc", NULL,
ab3a3d
+	};
ab3a3d
+	struct servent *entry;
ab3a3d
+	struct protoent *p_ent;
ab3a3d
+	unsigned short port;
ab3a3d
+	unsigned int i;
ab3a3d
+
ab3a3d
+	pthread_mutex_lock(&rpcb_mutex);
ab3a3d
+	p_ent = getprotobynumber(proto);
ab3a3d
+	if (!p_ent)
ab3a3d
+		goto done;
ab3a3d
+	for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
ab3a3d
+		entry = getservbyname(rpcb_netnametbl[i], p_ent->p_name);
ab3a3d
+		if (entry) {
ab3a3d
+			port = entry->s_port;
ab3a3d
+			pthread_mutex_unlock(&rpcb_mutex);
ab3a3d
+			return port;
ab3a3d
+		}
ab3a3d
+	}
ab3a3d
+done:
ab3a3d
+	pthread_mutex_unlock(&rpcb_mutex);
ab3a3d
+#endif
ab3a3d
+	return (unsigned short) PMAPPORT;
ab3a3d
+}
ab3a3d
+
ab3a3d
 /*
ab3a3d
  * Create an RPC client
ab3a3d
  */
ab3a3d
@@ -510,9 +578,15 @@ int rpc_portmap_getclient(struct conn_in
ab3a3d
 	info->host = host;
ab3a3d
 	info->addr = addr;
ab3a3d
 	info->addr_len = addr_len;
ab3a3d
-	info->program = PMAPPROG;
ab3a3d
-	info->port = PMAPPORT;
ab3a3d
-	info->version = PMAPVERS;
ab3a3d
+	info->program = rpc_getrpcbyname(rpcb_prog);
ab3a3d
+	info->port = ntohs(rpc_getrpcbport(proto));
ab3a3d
+	/*
ab3a3d
+	 * When using libtirpc we might need to change the rpcbind version
ab3a3d
+	 * to qurey AF_INET addresses. Since we might not have an address
ab3a3d
+	 * yet set AF_INET rpcbind version in rpc_do_create_client() when
ab3a3d
+	 * we always have an address.
ab3a3d
+	 */
ab3a3d
+	info->version = rpcb_version;
ab3a3d
 	info->proto = proto;
ab3a3d
 	info->send_sz = RPCSMALLMSGSIZE;
ab3a3d
 	info->recv_sz = RPCSMALLMSGSIZE;
ab3a3d
@@ -555,9 +629,15 @@ int rpc_portmap_getport(struct conn_info
ab3a3d
 		pmap_info.host = info->host;
ab3a3d
 		pmap_info.addr = info->addr;
ab3a3d
 		pmap_info.addr_len = info->addr_len;
ab3a3d
-		pmap_info.port = PMAPPORT;
ab3a3d
-		pmap_info.program = PMAPPROG;
ab3a3d
-		pmap_info.version = PMAPVERS;
ab3a3d
+		pmap_info.port = ntohs(rpc_getrpcbport(info->proto));
ab3a3d
+		pmap_info.program = rpc_getrpcbyname(rpcb_prog);
ab3a3d
+		/*
ab3a3d
+		 * When using libtirpc we might need to change the rpcbind
ab3a3d
+		 * version to qurey AF_INET addresses. Since we might not
ab3a3d
+		 * have an address yet set AF_INET rpcbind version in
ab3a3d
+		 * rpc_do_create_client() when we always have an address.
ab3a3d
+		 */
ab3a3d
+		pmap_info.version = rpcb_version;
ab3a3d
 		pmap_info.proto = info->proto;
ab3a3d
 		pmap_info.send_sz = RPCSMALLMSGSIZE;
ab3a3d
 		pmap_info.recv_sz = RPCSMALLMSGSIZE;