[PATCH 3/5] getport: don't use getaddrinfo(3) on old systems

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Older glibc versions have a getaddrinfo(3) that doesn't support
AI_ADDRCONFIG.  Detect that case and build something else for
getport.c that will work adequately on those systems.

Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---

 support/nfs/getport.c |   69 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/support/nfs/getport.c b/support/nfs/getport.c
index 25dca6c..47824a2 100644
--- a/support/nfs/getport.c
+++ b/support/nfs/getport.c
@@ -73,6 +73,60 @@ static const char *nfs_gp_rpcb_pgmtbl[] = {
 	NULL,
 };
 
+#ifdef HAVE_DECL_AI_ADDRCONFIG
+/*
+ * getaddrinfo(3) generates a usable loopback address based on how the
+ * local network interfaces are configured.  RFC 3484 requires that the
+ * results are sorted so that the first result has the best likelihood
+ * of working, so we try just that first result.
+ *
+ * Returns TRUE on success.
+ */
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
+{
+	struct addrinfo *gai_results;
+	struct addrinfo gai_hint = {
+		.ai_flags	= AI_ADDRCONFIG,
+	};
+	socklen_t len = *salen;
+	int ret = 0;
+
+	if (getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results))
+		return 0;
+
+	switch (gai_results->ai_addr->sa_family) {
+	case AF_INET:
+	case AF_INET6:
+		if (len >= gai_results->ai_addrlen) {
+			memcpy(sap, gai_results->ai_addr,
+					gai_results->ai_addrlen);
+			*salen = gai_results->ai_addrlen;
+			ret = 1;
+		}
+	}
+
+	freeaddrinfo(gai_results);
+	return ret;
+}
+#else
+/*
+ * Old versions of getaddrinfo(3) don't support AI_ADDRCONFIG, so we
+ * have a fallback for building on legacy systems.
+ */
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
+{
+	struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+
+	memset(sin, 0, sizeof(*sin));
+
+	sin->sin_family = AF_INET;
+	sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	*salen = sizeof(*sin);
+
+	return 1;
+}
+#endif
+
 /*
  * Discover the port number that should be used to contact an
  * rpcbind service.  This will detect if the port has a local
@@ -780,12 +834,10 @@ unsigned short nfs_getlocalport(const rpcprot_t program,
 				const rpcvers_t version,
 				const unsigned short protocol)
 {
-	struct addrinfo *gai_results;
-	struct addrinfo gai_hint = {
-		.ai_flags	= AI_ADDRCONFIG,
-	};
+	struct sockaddr_storage address;
+	struct sockaddr *lb_addr = (struct sockaddr *)&address;
+	socklen_t lb_len = sizeof(lb_addr);
 	unsigned short port = 0;
-	int error;
 
 #ifdef NFS_GP_LOCAL
 	const struct sockaddr_un sun = {
@@ -811,12 +863,9 @@ unsigned short nfs_getlocalport(const rpcprot_t program,
 #endif	/* NFS_GP_LOCAL */
 
 	if (port == 0) {
-		error = getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results);
-		if (error == 0) {
-			port = nfs_getport(gai_results->ai_addr,
-						gai_results->ai_addrlen,
+		if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
+			port = nfs_getport(lb_addr, lb_len,
 						program, version, protocol);
-			freeaddrinfo(gai_results);
 		} else
 			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
 	}

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux