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 3/5] libexport.a: Prepare init_subnetwork() for IPv6 support
Date: Tue, 24 Aug 2010 12:35:42 -0400	[thread overview]
Message-ID: <20100824163542.2433.28219.stgit@matisse.1015granger.net> (raw)
In-Reply-To: <20100824162926.2433.7535.stgit@matisse.1015granger.net>

Retire the slash32 logic in inet_netmask() in favor of a more generic
netmask parser that can support IPv6 addresses.

If an invalid IP address string is given to inet_addr(3), it returns
INADDR_NONE, which is actually a "valid" address (255.255.255.255).
We're none the wiser to the substitution until something breaks later.

This patch provides better sanity checking of the parsed address, now
that such an error can be reported to client_init()'s callers.
We can also check the prefixlen value a little more carefully as well.

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

 support/export/client.c |   81 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/support/export/client.c b/support/export/client.c
index a89142d..780c74d 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <netdb.h>
+#include <errno.h>
 
 #include "misc.h"
 #include "nfslib.h"
@@ -58,25 +59,58 @@ client_free(nfs_client *clp)
 }
 
 static int
-init_netmask(nfs_client *clp, const char *slash)
+init_netmask(nfs_client *clp, const char *slash, const sa_family_t family)
 {
 	struct sockaddr_in sin = {
 		.sin_family		= AF_INET,
 	};
+	unsigned long prefixlen;
+	uint32_t shift;
 
-	if (strchr(slash + 1, '.') != NULL)
-		sin.sin_addr.s_addr = inet_addr(slash + 1);
-	else {
-		int prefixlen = atoi(slash + 1);
-		if (0 < prefixlen && prefixlen <= 32)
-			sin.sin_addr.s_addr =
-					htonl((uint32_t)~0 << (32 - prefixlen));
-		else
+	/* No slash present; assume netmask is all ones */
+	if (slash == NULL) {
+		switch (family) {
+		case AF_INET:
+			prefixlen = 32;
+			break;
+		default:
+			goto out_badfamily;
+		}
+	} else {
+		char *endptr;
+
+		/* A spelled out netmask address, perhaps? */
+		if (strchr(slash + 1, '.') != NULL) {
+			if (inet_pton(AF_INET, slash + 1,
+						&sin.sin_addr.s_addr) == 0)
+				goto out_badmask;
+			set_addrlist_in(clp, 1, &sin);
+			return 1;
+		}
+
+		/* A prefixlen was given */
+		prefixlen = strtoul(slash + 1, &endptr, 10);
+		if (*endptr != '\0' && prefixlen != ULONG_MAX && errno != ERANGE)
 			goto out_badprefix;
 	}
 
-	set_addrlist_in(clp, 1, &sin);
-	return 1;
+	switch (family) {
+	case AF_INET:
+		if (prefixlen > 32)
+			goto out_badprefix;
+		shift = 32 - (uint32_t)prefixlen;
+		sin.sin_addr.s_addr = htonl((uint32_t)~0 << shift);
+		set_addrlist_in(clp, 1, &sin);
+		return 1;
+	}
+
+out_badfamily:
+	xlog(L_ERROR, "Unsupported address family for %s", clp->m_hostname);
+	return 0;
+
+out_badmask:
+	xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
 
 out_badprefix:
 	xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname);
@@ -86,25 +120,28 @@ out_badprefix:
 static int
 init_subnetwork(nfs_client *clp)
 {
-	static char slash32[] = "/32";
 	struct addrinfo *ai;
-	char *cp;
-
-	cp = strchr(clp->m_hostname, '/');
-	if (cp == NULL)
-		cp = slash32;
-
-	*cp = '\0';
-	ai = host_pton(clp->m_hostname);
-	*cp = '/';
+	sa_family_t family;
+	char *slash;
+
+	slash = strchr(clp->m_hostname, '/');
+	if (slash != NULL) {
+		*slash = '\0';
+		ai = host_pton(clp->m_hostname);
+		*slash = '/';
+	} else
+		ai = host_pton(clp->m_hostname);
 	if (ai == NULL) {
 		xlog(L_ERROR, "Invalid IP address %s", clp->m_hostname);
 		return false;
 	}
+
 	set_addrlist(clp, 0, ai->ai_addr);
+	family = ai->ai_addr->sa_family;
+
 	freeaddrinfo(ai);
 
-	return init_netmask(clp, cp);
+	return init_netmask(clp, slash, family);
 }
 
 static int


  parent reply	other threads:[~2010-08-24 16:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-24 16:35 [PATCH 0/5] Support IPv6 in libexport.a Chuck Lever
2010-08-24 16:35 ` [PATCH 1/5] libexport.a: Prepare to recognize IPv6 addresses in client_gettype() Chuck Lever
2010-08-24 16:35 ` [PATCH 2/5] libexport.a: Use host helper to parse address in client_init() Chuck Lever
2010-08-24 16:35 ` Chuck Lever [this message]
2010-08-24 16:35 ` [PATCH 4/5] libexport.a: IPv6 support for client_init_subnet() Chuck Lever
2010-08-24 16:36 ` [PATCH 5/5] libexport.a: IPv6 support in client_check() Chuck Lever
2010-08-31 19:43 ` [PATCH 0/5] Support IPv6 in libexport.a Steve Dickson
     [not found]   ` <4C7D5B63.9060907-AfCzQyP5zfLQT0dZR+AlfA@public.gmane.org>
2010-08-31 20:36     ` Chuck Lever
2010-08-31 23:41       ` 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=20100824163542.2433.28219.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