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

4d476f
autofs-5.0.7 - fix portmap lookup
4d476f
4d476f
From: Ian Kent <ikent@redhat.com>
4d476f
4d476f
The autofs RPC library has fallen behind some.
4d476f
4d476f
When using IPv6 (rpbbind) version 3 or 4 is available whereas with IPv4
4d476f
(portmap) verions 2 and 3 are available.
4d476f
4d476f
autofs uses the version defined by PMAPVERS in the portmap include files
4d476f
whereas it should be using the RPCBVERS defines when using libtirpc.
4d476f
4d476f
In addition /etc/rpc should be used for program number lookup and
4d476f
/etc/services should be used to lookup rpcbind/protmap port number.
4d476f
4d476f
This incompatibility only shows up when using IPv6 only.
4d476f
---
4d476f
 CHANGELOG           |    1 
4d476f
 aclocal.m4          |    2 +
4d476f
 configure           |   80 +++++++++++++++++++++++++++++++++++++++++++++
4d476f
 include/config.h.in |    6 +++
4d476f
 lib/rpc_subs.c      |   92 ++++++++++++++++++++++++++++++++++++++++++++++++----
4d476f
 5 files changed, 175 insertions(+), 6 deletions(-)
4d476f
4d476f
--- autofs-5.0.7.orig/CHANGELOG
4d476f
+++ autofs-5.0.7/CHANGELOG
4d476f
@@ -62,6 +62,7 @@
4d476f
 - try and cleanup after dumpmaps.
4d476f
 - teach dumpmaps to output simple key value pairs.
4d476f
 - fix get_nfs_info() probe.
4d476f
+- fix portmap lookup.
4d476f
 
4d476f
 25/07/2012 autofs-5.0.7
4d476f
 =======================
4d476f
--- autofs-5.0.7.orig/aclocal.m4
4d476f
+++ autofs-5.0.7/aclocal.m4
4d476f
@@ -421,6 +421,8 @@ if test "$af_have_libtirpc" = "yes"; the
4d476f
     TIRPCLIB="-ltirpc"
4d476f
 fi
4d476f
 
4d476f
+AC_CHECK_FUNCS([getrpcbyname getservbyname])
4d476f
+
4d476f
 # restore flags
4d476f
 CFLAGS="$af_check_libtirpc_save_cflags"
4d476f
 LDFLAGS="$af_check_libtirpc_save_ldflags"
4d476f
--- autofs-5.0.7.orig/configure
4d476f
+++ autofs-5.0.7/configure
4d476f
@@ -1559,6 +1559,73 @@ fi
4d476f
 
4d476f
 } # ac_fn_c_try_link
4d476f
 
4d476f
+# ac_fn_c_check_func LINENO FUNC VAR
4d476f
+# ----------------------------------
4d476f
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
4d476f
+ac_fn_c_check_func ()
4d476f
+{
4d476f
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
4d476f
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
4d476f
+$as_echo_n "checking for $2... " >&6; }
4d476f
+if eval \${$3+:} false; then :
4d476f
+  $as_echo_n "(cached) " >&6
4d476f
+else
4d476f
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
4d476f
+/* end confdefs.h.  */
4d476f
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
4d476f
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
4d476f
+#define $2 innocuous_$2
4d476f
+
4d476f
+/* System header to define __stub macros and hopefully few prototypes,
4d476f
+    which can conflict with char $2 (); below.
4d476f
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
4d476f
+    <limits.h> exists even on freestanding compilers.  */
4d476f
+
4d476f
+#ifdef __STDC__
4d476f
+# include <limits.h>
4d476f
+#else
4d476f
+# include <assert.h>
4d476f
+#endif
4d476f
+
4d476f
+#undef $2
4d476f
+
4d476f
+/* Override any GCC internal prototype to avoid an error.
4d476f
+   Use char because int might match the return type of a GCC
4d476f
+   builtin and then its argument prototype would still apply.  */
4d476f
+#ifdef __cplusplus
4d476f
+extern "C"
4d476f
+#endif
4d476f
+char $2 ();
4d476f
+/* The GNU C library defines this for functions which it implements
4d476f
+    to always fail with ENOSYS.  Some functions are actually named
4d476f
+    something starting with __ and the normal name is an alias.  */
4d476f
+#if defined __stub_$2 || defined __stub___$2
4d476f
+choke me
4d476f
+#endif
4d476f
+
4d476f
+int
4d476f
+main ()
4d476f
+{
4d476f
+return $2 ();
4d476f
+  ;
4d476f
+  return 0;
4d476f
+}
4d476f
+_ACEOF
4d476f
+if ac_fn_c_try_link "$LINENO"; then :
4d476f
+  eval "$3=yes"
4d476f
+else
4d476f
+  eval "$3=no"
4d476f
+fi
4d476f
+rm -f core conftest.err conftest.$ac_objext \
4d476f
+    conftest$ac_exeext conftest.$ac_ext
4d476f
+fi
4d476f
+eval ac_res=\$$3
4d476f
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
4d476f
+$as_echo "$ac_res" >&6; }
4d476f
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
4d476f
+
4d476f
+} # ac_fn_c_check_func
4d476f
+
4d476f
 # ac_fn_c_try_cpp LINENO
4d476f
 # ----------------------
4d476f
 # Try to preprocess conftest.$ac_ext, and return whether this succeeded.
4d476f
@@ -3161,6 +3228,19 @@ $as_echo "#define TIRPC_WORKAROUND 1" >>
4d476f
     TIRPCLIB="-ltirpc"
4d476f
 fi
4d476f
 
4d476f
+for ac_func in getrpcbyname getservbyname
4d476f
+do :
4d476f
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
4d476f
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
4d476f
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
4d476f
+  cat >>confdefs.h <<_ACEOF
4d476f
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
4d476f
+_ACEOF
4d476f
+
4d476f
+fi
4d476f
+done
4d476f
+
4d476f
+
4d476f
 # restore flags
4d476f
 CFLAGS="$af_check_libtirpc_save_cflags"
4d476f
 LDFLAGS="$af_check_libtirpc_save_ldflags"
4d476f
--- autofs-5.0.7.orig/include/config.h.in
4d476f
+++ autofs-5.0.7/include/config.h.in
4d476f
@@ -21,6 +21,12 @@
4d476f
 /* define if you have E4FSCK */
4d476f
 #undef HAVE_E4FSCK
4d476f
 
4d476f
+/* Define to 1 if you have the `getrpcbyname' function. */
4d476f
+#undef HAVE_GETRPCBYNAME
4d476f
+
4d476f
+/* Define to 1 if you have the `getservbyname' function. */
4d476f
+#undef HAVE_GETSERVBYNAME
4d476f
+
4d476f
 /* Define to 1 if you have the <inttypes.h> header file. */
4d476f
 #undef HAVE_INTTYPES_H
4d476f
 
4d476f
--- autofs-5.0.7.orig/lib/rpc_subs.c
4d476f
+++ autofs-5.0.7/lib/rpc_subs.c
4d476f
@@ -43,6 +43,14 @@
4d476f
                 } while (0)
4d476f
 #endif
4d476f
 
4d476f
+#ifdef WITH_LIBTIRPC
4d476f
+const rpcprog_t rpcb_prog = RPCBPROG;
4d476f
+const rpcvers_t rpcb_version = RPCBVERS;
4d476f
+#else
4d476f
+const rpcprog_t rpcb_prog = PMAPPROG;
4d476f
+const rpcvers_t rpcb_version = PMAPVERS;
4d476f
+#endif
4d476f
+
4d476f
 #include "mount.h"
4d476f
 #include "rpc_subs.h"
4d476f
 #include "automount.h"
4d476f
@@ -259,6 +267,9 @@ static int rpc_do_create_client(struct s
4d476f
 		laddr = (struct sockaddr *) &in4_laddr;
4d476f
 		in4_raddr->sin_port = htons(info->port);
4d476f
 		slen = sizeof(struct sockaddr_in);
4d476f
+		/* Use rpcbind v2 for AF_INET */
4d476f
+		if (info->program == rpcb_prog)
4d476f
+			info->version = PMAPVERS;
4d476f
 	} else if (addr->sa_family == AF_INET6) {
4d476f
 		struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr;
4d476f
 		in6_laddr.sin6_family = AF_INET6;
4d476f
@@ -315,6 +326,63 @@ static int rpc_do_create_client(struct s
4d476f
 }
4d476f
 #endif
4d476f
 
4d476f
+#if defined(HAVE_GETRPCBYNAME) || defined(HAVE_GETSERVBYNAME)
4d476f
+static pthread_mutex_t rpcb_mutex = PTHREAD_MUTEX_INITIALIZER;
4d476f
+#endif
4d476f
+
4d476f
+static rpcprog_t rpc_getrpcbyname(const rpcprog_t program)
4d476f
+{
4d476f
+#ifdef HAVE_GETRPCBYNAME
4d476f
+	static const char *rpcb_pgmtbl[] = {
4d476f
+		"rpcbind", "portmap", "portmapper", "sunrpc", NULL,
4d476f
+	};
4d476f
+	struct rpcent *entry;
4d476f
+	rpcprog_t prog_number;
4d476f
+	unsigned int i;
4d476f
+
4d476f
+	pthread_mutex_lock(&rpcb_mutex);
4d476f
+	for (i = 0; rpcb_pgmtbl[i] != NULL; i++) {
4d476f
+		entry = getrpcbyname(rpcb_pgmtbl[i]);
4d476f
+		if (entry) {
4d476f
+			prog_number = entry->r_number;
4d476f
+			pthread_mutex_unlock(&rpcb_mutex);
4d476f
+			return prog_number;
4d476f
+		}
4d476f
+	}
4d476f
+	pthread_mutex_unlock(&rpcb_mutex);
4d476f
+#endif
4d476f
+	return program;
4d476f
+}
4d476f
+
4d476f
+static unsigned short rpc_getrpcbport(const int proto)
4d476f
+{
4d476f
+#ifdef HAVE_GETSERVBYNAME
4d476f
+	static const char *rpcb_netnametbl[] = {
4d476f
+		"rpcbind", "portmapper", "sunrpc", NULL,
4d476f
+	};
4d476f
+	struct servent *entry;
4d476f
+	struct protoent *p_ent;
4d476f
+	unsigned short port;
4d476f
+	unsigned int i;
4d476f
+
4d476f
+	pthread_mutex_lock(&rpcb_mutex);
4d476f
+	p_ent = getprotobynumber(proto);
4d476f
+	if (!p_ent)
4d476f
+		goto done;
4d476f
+	for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
4d476f
+		entry = getservbyname(rpcb_netnametbl[i], p_ent->p_name);
4d476f
+		if (entry) {
4d476f
+			port = entry->s_port;
4d476f
+			pthread_mutex_unlock(&rpcb_mutex);
4d476f
+			return port;
4d476f
+		}
4d476f
+	}
4d476f
+done:
4d476f
+	pthread_mutex_unlock(&rpcb_mutex);
4d476f
+#endif
4d476f
+	return (unsigned short) PMAPPORT;
4d476f
+}
4d476f
+
4d476f
 /*
4d476f
  * Create an RPC client
4d476f
  */
4d476f
@@ -510,9 +578,15 @@ int rpc_portmap_getclient(struct conn_in
4d476f
 	info->host = host;
4d476f
 	info->addr = addr;
4d476f
 	info->addr_len = addr_len;
4d476f
-	info->program = PMAPPROG;
4d476f
-	info->port = PMAPPORT;
4d476f
-	info->version = PMAPVERS;
4d476f
+	info->program = rpc_getrpcbyname(rpcb_prog);
4d476f
+	info->port = ntohs(rpc_getrpcbport(proto));
4d476f
+	/*
4d476f
+	 * When using libtirpc we might need to change the rpcbind version
4d476f
+	 * to qurey AF_INET addresses. Since we might not have an address
4d476f
+	 * yet set AF_INET rpcbind version in rpc_do_create_client() when
4d476f
+	 * we always have an address.
4d476f
+	 */
4d476f
+	info->version = rpcb_version;
4d476f
 	info->proto = proto;
4d476f
 	info->send_sz = RPCSMALLMSGSIZE;
4d476f
 	info->recv_sz = RPCSMALLMSGSIZE;
4d476f
@@ -555,9 +629,15 @@ int rpc_portmap_getport(struct conn_info
4d476f
 		pmap_info.host = info->host;
4d476f
 		pmap_info.addr = info->addr;
4d476f
 		pmap_info.addr_len = info->addr_len;
4d476f
-		pmap_info.port = PMAPPORT;
4d476f
-		pmap_info.program = PMAPPROG;
4d476f
-		pmap_info.version = PMAPVERS;
4d476f
+		pmap_info.port = ntohs(rpc_getrpcbport(info->proto));
4d476f
+		pmap_info.program = rpc_getrpcbyname(rpcb_prog);
4d476f
+		/*
4d476f
+		 * When using libtirpc we might need to change the rpcbind
4d476f
+		 * version to qurey AF_INET addresses. Since we might not
4d476f
+		 * have an address yet set AF_INET rpcbind version in
4d476f
+		 * rpc_do_create_client() when we always have an address.
4d476f
+		 */
4d476f
+		pmap_info.version = rpcb_version;
4d476f
 		pmap_info.proto = info->proto;
4d476f
 		pmap_info.send_sz = RPCSMALLMSGSIZE;
4d476f
 		pmap_info.recv_sz = RPCSMALLMSGSIZE;