public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Chuck Lever <chuck.lever@oracle.com>
To: steved@redhat.com
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 04/31] getport: replace getnameinfo(NI_NUMERICHOST) with inet_ntop(3)
Date: Mon, 29 Jun 2009 13:35:26 -0400	[thread overview]
Message-ID: <20090629173525.2076.67115.stgit@matisse.1015granger.net> (raw)
In-Reply-To: <20090629172704.2076.45402.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>

getnameinfo(3) with the NI_NUMERICHOST flag is used in
support/nfs/getport.c to convert socket addresses to universal address
strings.

Older versions of glibc do not have getnameinfo(3), however.  In order
for nfs-utils to build on older systems we switch in legacy code via
HAVE_GETNAMEINFO and use inet_ntoa(3).

A problem with this is that we have to double our test matrix to be
sure that both versions of these routines build and operate correctly.
Another minor problem is that inet_ntoa(3) is officially deprecated.

So let's always use a single implementation based on inet_ntop(3).
Universal address strings do not support link-local / scope IDs, so we
don't lose any functionality by using inet_ntop(3) here.

This means we open code a bit of logic that is available in most
modern versions of glibc, but in return we can use exactly the same
code for all builds (on systems with getnameinfo(3) and without).

An additional benefit is we can avoid using NI_MAXHOST for character
buffers that live on the stack: it's 1025 bytes.  Instead,
INET6_ADDRSTRLEN is used, which is just 46 bytes, plus an additional
eight bytes for the port information.  We add beefier buffer overflow
detection logic as well.

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

 support/nfs/getport.c |   70 ++++++++++++++++---------------------------------
 1 files changed, 23 insertions(+), 47 deletions(-)

diff --git a/support/nfs/getport.c b/support/nfs/getport.c
index 9d85e89..056d3c7 100644
--- a/support/nfs/getport.c
+++ b/support/nfs/getport.c
@@ -330,81 +330,57 @@ int nfs_universal2port(const char *uaddr)
  * the returned string.  Otherwise NULL is returned and
  * rpc_createerr.cf_stat is set to reflect the error.
  *
+ * inet_ntop(3) is used here, since getnameinfo(3) is not available
+ * in some earlier glibc releases, and we don't require support for
+ * scope IDs for universal addresses.
  */
-#ifdef HAVE_GETNAMEINFO
-
 char *nfs_sockaddr2universal(const struct sockaddr *sap,
 			     const socklen_t salen)
 {
-	struct sockaddr_un *sun = (struct sockaddr_un *)sap;
-	char buf[NI_MAXHOST];
+	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
+	const struct sockaddr_un *sun = (const struct sockaddr_un *)sap;
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	char buf[INET6_ADDRSTRLEN + 8 /* for port information */];
 	uint16_t port;
+	size_t count;
+	char *result;
+	int len;
 
 	switch (sap->sa_family) {
 	case AF_LOCAL:
 		return strndup(sun->sun_path, sizeof(sun->sun_path));
 	case AF_INET:
-		if (getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
-					NULL, 0, NI_NUMERICHOST) != 0)
+		if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr,
+					buf, (socklen_t)sizeof(buf)) == NULL)
 			goto out_err;
-		port = ntohs(((struct sockaddr_in *)sap)->sin_port);
+		port = ntohs(sin->sin_port);
 		break;
 	case AF_INET6:
-		if (getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
-					NULL, 0, NI_NUMERICHOST) != 0)
+		if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
+					buf, (socklen_t)sizeof(buf)) == NULL)
 			goto out_err;
-		port = ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
+		port = ntohs(sin6->sin6_port);
 		break;
 	default:
 		goto out_err;
 	}
 
-	(void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ".%u.%u",
+	count = sizeof(buf) - strlen(buf);
+	len = snprintf(buf + strlen(buf), count, ".%u.%u",
 			(unsigned)(port >> 8), (unsigned)(port & 0xff));
-
-	return strdup(buf);
-
-out_err:
-	rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
-	return NULL;
-}
-
-#else	/* HAVE_GETNAMEINFO */
-
-char *nfs_sockaddr2universal(const struct sockaddr *sap,
-			     const socklen_t salen)
-{
-	struct sockaddr_un *sun = (struct sockaddr_un *)sap;
-	char buf[NI_MAXHOST];
-	uint16_t port;
-	char *addr;
-
-	switch (sap->sa_family) {
-	case AF_LOCAL:
-		return strndup(sun->sun_path, sizeof(sun->sun_path));
-	case AF_INET:
-		addr = inet_ntoa(((struct sockaddr_in *)sap)->sin_addr);
-		if (addr != NULL && strlen(addr) > sizeof(buf))
-			goto out_err;
-		strcpy(buf, addr);
-		port = ntohs(((struct sockaddr_in *)sap)->sin_port);
-		break;
-	default:
+	/* before glibc 2.0.6, snprintf(3) could return -1 */
+	if (len < 0 || (size_t)len > count)
 		goto out_err;
-	}
 
-	(void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ".%u.%u",
-			(unsigned)(port >> 8), (unsigned)(port & 0xff));
-
-	return strdup(buf);
+	result = strdup(buf);
+	if (result != NULL)
+		return result;
 
 out_err:
 	rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
 	return NULL;
 }
 
-#endif	/* HAVE_GETNAMEINFO */
-
 /*
  * Send a NULL request to the indicated RPC service.
  *


  parent reply	other threads:[~2009-06-29 17:35 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-29 17:34 [PATCH 00/31] mount.nfs patches for next nfs-utils release Chuck Lever
     [not found] ` <20090629172704.2076.45402.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
2009-06-29 17:34   ` [PATCH 01/31] getport: RPCB_GETADDR r_owner should be an empty string Chuck Lever
2009-06-29 17:35   ` [PATCH 02/31] getport: RPCB_GETADDR's r_addr should contain rpcbind port, not zero Chuck Lever
2009-06-29 17:35   ` [PATCH 03/31] getport: Remove AI_ADDRCONFIG from nfs_gp_loopback_address() Chuck Lever
2009-06-29 17:35   ` Chuck Lever [this message]
2009-06-29 17:35   ` [PATCH 05/31] getport: Remove unneeded @salen arguments Chuck Lever
2009-06-29 17:35   ` [PATCH 06/31] New versions of libtool add extra aclocal scripts Chuck Lever
2009-06-29 17:35   ` [PATCH 07/31] support: Use HAVE_LIBTIRPC to switch in bindresvport_sa(3t) Chuck Lever
2009-06-29 17:36   ` [PATCH 08/31] support: Don't return RPC_UNKNOWNHOST from rpc_socket.c Chuck Lever
2009-06-29 17:36   ` [PATCH 09/31] support: Set proper retransmit timeout for datagram transports Chuck Lever
2009-06-29 17:36   ` [PATCH 10/31] getport: RPC_PROGNOTREGISTERED is a permanent error Chuck Lever
2009-06-29 17:36   ` [PATCH 11/31] getport: Clear shared error fields before trying rpcbind queries Chuck Lever
2009-06-29 17:36   ` [PATCH 12/31] mount.nfs: Add more debugging output around nfs_getport() Chuck Lever
2009-06-29 17:36   ` [PATCH 13/31] getport: Restore historical TCP connect timeout error code Chuck Lever
2009-06-29 17:37   ` [PATCH 14/31] getport: Convert TCP connection refused to RPC_CANTRECV Chuck Lever
2009-06-29 17:37   ` [PATCH 15/31] mount.nfs: If port= specifies an unregistered port, retry, then fail Chuck Lever
2009-06-29 17:37   ` [PATCH 16/31] mount.nfs: force rpcbind queries if options aren't specified Chuck Lever
2009-06-29 17:37   ` [PATCH 17/31] mount.nfs: make nfs_options2pmap return errors Chuck Lever
2009-06-29 17:37   ` [PATCH 18/31] mount.nfs: rearchitect mount version/protocol negotiation logic Chuck Lever
2009-06-29 17:37   ` [PATCH 19/31] mount.nfs: Clean up nfs_is_permanent_error() Chuck Lever
2009-06-29 17:37   ` [PATCH 20/31] mount.nfs: Clean up after restructuring version/protocol negotiation Chuck Lever
2009-06-29 17:38   ` [PATCH 21/31] mount.nfs: Don't update extra_opts after text-based negotiation Chuck Lever
2009-06-29 17:38   ` [PATCH 22/31] support: Introduce sockaddr helpers to get and set IP port numbers Chuck Lever
2009-06-29 17:38   ` [PATCH 23/31] mount.nfs: Use correct data type in discover_nfs_mount_data_version() Chuck Lever
2009-06-29 17:38   ` [PATCH 24/31] mount.nfs: Remove unused parameter in try_mount() Chuck Lever
2009-06-29 17:38   ` [PATCH 25/31] mount.nfs: Fix some nfs_error() nits in network.c Chuck Lever
2009-06-29 17:39   ` [PATCH 26/31] mount.nfs: Remove unused @salen parameter from nfs_ca_gai() Chuck Lever
2009-06-29 17:39   ` [PATCH 27/31] mount.nfs: remove unused @addrlen argument from nfs_string_to_sockaddr() Chuck Lever
2009-06-29 17:39   ` [PATCH 28/31] umount.nfs: Use correct data type in nfsumount() Chuck Lever
2009-06-29 17:39   ` [PATCH 29/31] mount.nfs: Fix compiler warning in stropts.c Chuck Lever
2009-06-29 17:39   ` [PATCH 30/31] mount.nfs: Squelch unused parameter warnings on empty functions Chuck Lever
2009-06-29 17:39   ` [PATCH 31/31] mount.nfs: Squelch compiler warnings in nfs_strerror() Chuck Lever
2009-07-15 13:50   ` [PATCH 00/31] mount.nfs patches for next nfs-utils release Steve Dickson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090629173525.2076.67115.stgit@matisse.1015granger.net \
    --to=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=steved@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox