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

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