walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
a2fd65e
--- nfs-utils-1.1.4/support/nfs/getport.c.save	2009-01-06 12:22:33.100864000 -0500
a2fd65e
+++ nfs-utils-1.1.4/support/nfs/getport.c	2009-01-06 12:23:04.885428000 -0500
a2fd65e
@@ -73,6 +73,60 @@ static const char *nfs_gp_rpcb_pgmtbl[] 
a2fd65e
 	NULL,
a2fd65e
 };
a2fd65e
 
a2fd65e
+#ifdef HAVE_DECL_AI_ADDRCONFIG
a2fd65e
+/*
a2fd65e
+ * getaddrinfo(3) generates a usable loopback address based on how the
a2fd65e
+ * local network interfaces are configured.  RFC 3484 requires that the
a2fd65e
+ * results are sorted so that the first result has the best likelihood
a2fd65e
+ * of working, so we try just that first result.
a2fd65e
+ *
a2fd65e
+ * Returns TRUE on success.
a2fd65e
+ */
a2fd65e
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
a2fd65e
+{
a2fd65e
+	struct addrinfo *gai_results;
a2fd65e
+	struct addrinfo gai_hint = {
a2fd65e
+		.ai_flags	= AI_ADDRCONFIG,
a2fd65e
+	};
a2fd65e
+	socklen_t len = *salen;
a2fd65e
+	int ret = 0;
a2fd65e
+
a2fd65e
+	if (getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results))
a2fd65e
+		return 0;
a2fd65e
+
a2fd65e
+	switch (gai_results->ai_addr->sa_family) {
a2fd65e
+	case AF_INET:
a2fd65e
+	case AF_INET6:
a2fd65e
+		if (len >= gai_results->ai_addrlen) {
a2fd65e
+			memcpy(sap, gai_results->ai_addr,
a2fd65e
+					gai_results->ai_addrlen);
a2fd65e
+			*salen = gai_results->ai_addrlen;
a2fd65e
+			ret = 1;
a2fd65e
+		}
a2fd65e
+	}
a2fd65e
+
a2fd65e
+	freeaddrinfo(gai_results);
a2fd65e
+	return ret;
a2fd65e
+}
a2fd65e
+#else
a2fd65e
+/*
a2fd65e
+ * Old versions of getaddrinfo(3) don't support AI_ADDRCONFIG, so we
a2fd65e
+ * have a fallback for building on legacy systems.
a2fd65e
+ */
a2fd65e
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
a2fd65e
+{
a2fd65e
+	struct sockaddr_in *sin = (struct sockaddr_in *)sap;
a2fd65e
+
a2fd65e
+	memset(sin, 0, sizeof(*sin));
a2fd65e
+
a2fd65e
+	sin->sin_family = AF_INET;
a2fd65e
+	sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
a2fd65e
+	*salen = sizeof(*sin);
a2fd65e
+
a2fd65e
+	return 1;
a2fd65e
+}
a2fd65e
+#endif
a2fd65e
+
a2fd65e
 /*
a2fd65e
  * Discover the port number that should be used to contact an
a2fd65e
  * rpcbind service.  This will detect if the port has a local
a2fd65e
@@ -780,12 +834,10 @@ unsigned short nfs_getlocalport(const rp
a2fd65e
 				const rpcvers_t version,
a2fd65e
 				const unsigned short protocol)
a2fd65e
 {
a2fd65e
-	struct addrinfo *gai_results;
a2fd65e
-	struct addrinfo gai_hint = {
a2fd65e
-		.ai_flags	= AI_ADDRCONFIG,
a2fd65e
-	};
a2fd65e
+	struct sockaddr_storage address;
a2fd65e
+	struct sockaddr *lb_addr = (struct sockaddr *)&address;
a2fd65e
+	socklen_t lb_len = sizeof(lb_addr);
a2fd65e
 	unsigned short port = 0;
a2fd65e
-	int error;
a2fd65e
 
a2fd65e
 #ifdef NFS_GP_LOCAL
a2fd65e
 	const struct sockaddr_un sun = {
a2fd65e
@@ -811,12 +863,9 @@ unsigned short nfs_getlocalport(const rp
a2fd65e
 #endif	/* NFS_GP_LOCAL */
a2fd65e
 
a2fd65e
 	if (port == 0) {
a2fd65e
-		error = getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results);
a2fd65e
-		if (error == 0) {
a2fd65e
-			port = nfs_getport(gai_results->ai_addr,
a2fd65e
-						gai_results->ai_addrlen,
a2fd65e
+		if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
a2fd65e
+			port = nfs_getport(lb_addr, lb_len,
a2fd65e
 						program, version, protocol);
a2fd65e
-			freeaddrinfo(gai_results);
a2fd65e
 		} else
a2fd65e
 			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
a2fd65e
 	}
a2fd65e
--- nfs-utils-1.1.4/utils/mount/network.c.save	2009-01-06 12:22:12.950764000 -0500
a2fd65e
+++ nfs-utils-1.1.4/utils/mount/network.c	2009-01-06 12:23:10.432801000 -0500
a2fd65e
@@ -50,24 +50,6 @@
a2fd65e
 #include "nfsrpc.h"
a2fd65e
 #include "network.h"
a2fd65e
 
a2fd65e
-/*
a2fd65e
- * Earlier versions of glibc's /usr/include/netdb.h exclude these
a2fd65e
- * definitions because it was thought they were not part of a stable
a2fd65e
- * POSIX standard.  However, they are defined by RFC 2553 and 3493
a2fd65e
- * and in POSIX 1003.1-2001, so these definitions were added in later
a2fd65e
- * versions of netdb.h.
a2fd65e
- */
a2fd65e
-#ifndef AI_V4MAPPED
a2fd65e
-#define AI_V4MAPPED     0x0008  /* IPv4-mapped addresses are acceptable.  */
a2fd65e
-#endif	/* AI_V4MAPPED */
a2fd65e
-#ifndef AI_ALL
a2fd65e
-#define AI_ALL          0x0010  /* Return both IPv4 and IPv6 addresses.  */
a2fd65e
-#endif	/* AI_ALL */
a2fd65e
-#ifndef AI_ADDRCONFIG
a2fd65e
-#define AI_ADDRCONFIG   0x0020  /* Use configuration of this host to choose \
a2fd65e
-				   returned address type.  */
a2fd65e
-#endif	/* AI_ADDRCONFIG */
a2fd65e
-
a2fd65e
 #define PMAP_TIMEOUT	(10)
a2fd65e
 #define CONNECT_TIMEOUT	(20)
a2fd65e
 #define MOUNT_TIMEOUT	(30)
a2fd65e
@@ -175,9 +157,11 @@ static void nfs_set_port(struct sockaddr
a2fd65e
 	}
a2fd65e
 }
a2fd65e
 
a2fd65e
+#ifdef HAVE_DECL_AI_ADDRCONFIG
a2fd65e
 /**
a2fd65e
  * nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
a2fd65e
  * @hostname: pointer to C string containing DNS hostname to resolve
a2fd65e
+ * @af_hint: hint to restrict resolution to one address family
a2fd65e
  * @sap: pointer to buffer to fill with socket address
a2fd65e
  * @len: IN: size of buffer to fill; OUT: size of socket address
a2fd65e
  *
a2fd65e
@@ -228,11 +212,66 @@ int nfs_name_to_address(const char *host
a2fd65e
 	freeaddrinfo(gai_results);
a2fd65e
 	return ret;
a2fd65e
 }
a2fd65e
+#else	/* HAVE_DECL_AI_ADDRCONFIG */
a2fd65e
+/**
a2fd65e
+ * nfs_name_to_address - resolve hostname to an IPv4 socket address
a2fd65e
+ * @hostname: pointer to C string containing DNS hostname to resolve
a2fd65e
+ * @af_hint: hint to restrict resolution to one address family
a2fd65e
+ * @sap: pointer to buffer to fill with socket address
a2fd65e
+ * @len: IN: size of buffer to fill; OUT: size of socket address
a2fd65e
+ *
a2fd65e
+ * Returns 1 and places a socket address at @sap if successful;
a2fd65e
+ * otherwise zero.
a2fd65e
+ *
a2fd65e
+ * Some older getaddrinfo(3) implementations don't support
a2fd65e
+ * AI_ADDRCONFIG or AI_V4MAPPED properly.  For those cases, a DNS
a2fd65e
+ * resolver based on the traditional gethostbyname(3) is provided.
a2fd65e
+ */
a2fd65e
+int nfs_name_to_address(const char *hostname,
a2fd65e
+			const sa_family_t af_hint,
a2fd65e
+			struct sockaddr *sap, socklen_t *salen)
a2fd65e
+{
a2fd65e
+	struct sockaddr_in *sin = (struct sockaddr_in *)sap;
a2fd65e
+	socklen_t len = *salen;
a2fd65e
+	struct hostent *hp;
a2fd65e
+
a2fd65e
+	*salen = 0;
a2fd65e
+
a2fd65e
+	if (af_hint != AF_INET) {
a2fd65e
+		nfs_error(_("%s: address family not supported by DNS resolver\n"),
a2fd65e
+				progname, hostname);
a2fd65e
+		return 0;
a2fd65e
+	}
a2fd65e
+
a2fd65e
+	sin->sin_family = AF_INET;
a2fd65e
+	if (inet_aton(hostname, &sin->sin_addr)) {
a2fd65e
+		*salen = sizeof(*sin);
a2fd65e
+		return 1;
a2fd65e
+	}
a2fd65e
+
a2fd65e
+	hp = gethostbyname(hostname);
a2fd65e
+	if (hp == NULL) {
a2fd65e
+		nfs_error(_("%s: DNS resolution failed for %s: %s"),
a2fd65e
+				progname, hostname, hstrerror(h_errno));
a2fd65e
+		return 0;
a2fd65e
+	}
a2fd65e
+
a2fd65e
+	if (hp->h_length > len) {
a2fd65e
+		nfs_error(_("%s: DNS resolution results too long for buffer\n"),
a2fd65e
+				progname);
a2fd65e
+		return 0;
a2fd65e
+	}
a2fd65e
+
a2fd65e
+	memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
a2fd65e
+	*salen = hp->h_length;
a2fd65e
+	return 1;
a2fd65e
+}
a2fd65e
+#endif	/* HAVE_DECL_AI_ADDRCONFIG */
a2fd65e
 
a2fd65e
 /**
a2fd65e
  * nfs_gethostbyname - resolve a hostname to an IPv4 address
a2fd65e
  * @hostname: pointer to a C string containing a DNS hostname
a2fd65e
- * @saddr: returns an IPv4 address 
a2fd65e
+ * @sin: returns an IPv4 address 
a2fd65e
  *
a2fd65e
  * Returns 1 if successful, otherwise zero.
a2fd65e
  */
a2fd65e
--- nfs-utils-1.1.4/configure.ac.save	2009-01-06 12:22:41.437331000 -0500
a2fd65e
+++ nfs-utils-1.1.4/configure.ac	2009-01-06 12:23:10.424809000 -0500
a2fd65e
@@ -246,6 +246,11 @@ if test "$enable_gss" = yes; then
a2fd65e
 
a2fd65e
 fi
a2fd65e
 
a2fd65e
+AC_CHECK_DECL([AI_ADDRCONFIG],
a2fd65e
+              AC_DEFINE([HAVE_DECL_AI_ADDRCONFIG], 1,
a2fd65e
+                         [Define this to 1 if AI_ADDRCONFIG macro is defined]), ,
a2fd65e
+              [ #include <netdb.h> ] )
a2fd65e
+
a2fd65e
 if test "$enable_ipv6" = yes; then
a2fd65e
   AC_CHECK_FUNC(inet_ntop, , ,
a2fd65e
                AC_MSG_ERROR(Function 'inet_ntop' not found.))
a2fd65e
@@ -254,7 +259,10 @@ if test "$enable_ipv6" = yes; then
a2fd65e
   AC_CHECK_LIB(tirpc, clnt_tli_create, ,
a2fd65e
                AC_MSG_ERROR([libtirpc needed for IPv6 support]))
a2fd65e
   AC_CHECK_HEADERS(tirpc/netconfig.h, ,
a2fd65e
-               AC_MSG_ERROR([libtirpc-devel needed for IPv6 support]))
a2fd65e
+               AC_MSG_ERROR([libtirpc headers needed for IPv6 support]))
a2fd65e
+  AC_CHECK_DECL([AI_ADDRCONFIG], ,
a2fd65e
+               AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support]),
a2fd65e
+               [ #include <netdb.h> ] )
a2fd65e
 fi
a2fd65e
 
a2fd65e
 dnl *************************************************************