linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Three more IPv6-related mountd patches
@ 2010-05-03 19:23 Chuck Lever
       [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Chuck Lever @ 2010-05-03 19:23 UTC (permalink / raw)
  To: steved; +Cc: linux-nfs

Hi Steve-

Here are two clean-up patches, and one patch that modifies the
nfs_client struct so it can store both IPv4 and IPv6 addresses
concurrently.

---

Chuck Lever (3):
      mountd/exportfs: Make m_addrlist field a nfs_sockaddr
      libexport.a: Clean up client_add()
      libexport.a: Refactor client_init()


 support/export/client.c    |  158 ++++++++++++++++++++++++++------------------
 support/export/nfsctl.c    |   17 ++++-
 support/include/exportfs.h |   50 +++++++++++++-
 utils/mountd/auth.c        |    2 -
 utils/mountd/cache.c       |    3 +
 5 files changed, 158 insertions(+), 72 deletions(-)

-- 
Chuck Lever

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] libexport.a: Refactor client_init()
       [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2010-05-03 19:24   ` Chuck Lever
  2010-05-03 19:24   ` [PATCH 2/3] libexport.a: Clean up client_add() Chuck Lever
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Chuck Lever @ 2010-05-03 19:24 UTC (permalink / raw)
  To: steved; +Cc: linux-nfs

Clean up:  Move subnet hostname parsing logic out of client_init() to
make it simpler to introduce IPv6 support.

Make client_init() a helper, since it's already static.

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

 support/export/client.c |   99 +++++++++++++++++++++++++++--------------------
 1 files changed, 56 insertions(+), 43 deletions(-)

diff --git a/support/export/client.c b/support/export/client.c
index eafc2bf..9259180 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -30,8 +30,6 @@ extern int	innetgr(char *netgr, char *host, char *, char *);
 #endif
 
 static char	*add_name(char *old, const char *add);
-static int	client_init(nfs_client *clp, const char *hname,
-					struct hostent *hp);
 
 nfs_client	*clientlist[MCL_MAXTYPES] = { NULL, };
 
@@ -59,6 +57,62 @@ client_free(nfs_client *clp)
 	free(clp);
 }
 
+static int
+init_netmask(nfs_client *clp, const char *slash)
+{
+	if (strchr(slash + 1, '.') != NULL)
+		clp->m_addrlist[1].s_addr = inet_addr(slash + 1);
+	else {
+		int prefixlen = atoi(slash + 1);
+		if (0 < prefixlen && prefixlen <= 32)
+			clp->m_addrlist[1].s_addr =
+					htonl((uint32_t)~0 << (32 - prefixlen));
+		else
+			goto out_badprefix;
+	}
+
+	return 1;
+
+out_badprefix:
+	xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
+}
+
+static int
+init_subnetwork(nfs_client *clp)
+{
+	static char slash32[] = "/32";
+	char *cp;
+
+	cp = strchr(clp->m_hostname, '/');
+	if (cp == NULL)
+		cp = slash32;
+
+	*cp = '\0';
+	clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
+	*cp = '/';
+
+	return init_netmask(clp, cp);
+}
+
+static int
+client_init(nfs_client *clp, const char *hname, const struct hostent *hp)
+{
+	clp->m_hostname = strdup(hname);
+	if (clp->m_hostname == NULL)
+		return 0;
+
+	clp->m_exported = 0;
+	clp->m_count = 0;
+	clp->m_naddr = 0;
+
+	if (clp->m_type == MCL_SUBNETWORK)
+		return init_subnetwork(clp);
+
+	init_addrlist(clp, hp);
+	return 1;
+}
+
 /* if canonical is set, then we *know* this is already a canonical name
  * so hostname lookup is avoided.
  * This is used when reading /proc/fs/nfs/exports
@@ -154,47 +208,6 @@ client_dup(nfs_client *clp, struct hostent *hp)
 	return new;
 }
 
-static int
-client_init(nfs_client *clp, const char *hname, struct hostent *hp)
-{
-	clp->m_hostname = strdup(hname);
-	if (clp->m_hostname == NULL)
-		return 0;
-
-	clp->m_exported = 0;
-	clp->m_count = 0;
-	clp->m_naddr = 0;
-
-	if (clp->m_type == MCL_SUBNETWORK) {
-		char	*cp = strchr(clp->m_hostname, '/');
-		static char slash32[] = "/32";
-
-		if(!cp) cp = slash32;
-		*cp = '\0';
-		clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
-		if (strchr(cp + 1, '.')) {
-			clp->m_addrlist[1].s_addr = inet_addr(cp+1);
-		}
-		else {
-			int netmask = atoi(cp + 1);
-			if (0 < netmask && netmask <= 32) {
-				clp->m_addrlist[1].s_addr =
-					htonl ((uint32_t) ~0 << (32 - netmask));
-			}
-			else {
-				xlog(L_ERROR, "invalid netmask `%s' for %s",
-					     cp + 1, clp->m_hostname);
-				return 0;
-			}
-		}
-		*cp = '/';
-		return 1;
-	}
-	
-	init_addrlist(clp, hp);
-	return 1;
-}
-
 void
 client_add(nfs_client *clp)
 {


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] libexport.a: Clean up client_add()
       [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-05-03 19:24   ` [PATCH 1/3] libexport.a: Refactor client_init() Chuck Lever
@ 2010-05-03 19:24   ` Chuck Lever
  2010-05-03 19:24   ` [PATCH 3/3] mountd/exportfs: Make m_addrlist field a nfs_sockaddr Chuck Lever
  2010-05-05 19:39   ` [PATCH 0/3] Three more IPv6-related mountd patches Steve Dickson
  3 siblings, 0 replies; 5+ messages in thread
From: Chuck Lever @ 2010-05-03 19:24 UTC (permalink / raw)
  To: steved; +Cc: linux-nfs

Clean up: client_add()'s current callers never set unknown m_type
values, so the m_type check is unnecessary.

All of client_add()'s callers are in the same source file where it is
defined, so make it a static helper function.

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

 support/export/client.c    |   26 ++++++++++++--------------
 support/include/exportfs.h |    1 -
 2 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/support/export/client.c b/support/export/client.c
index 9259180..4600255 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -113,6 +113,18 @@ client_init(nfs_client *clp, const char *hname, const struct hostent *hp)
 	return 1;
 }
 
+static void
+client_add(nfs_client *clp)
+{
+	nfs_client **cpp;
+
+	cpp = &clientlist[clp->m_type];
+	while (*cpp != NULL)
+		cpp = &((*cpp)->m_next);
+	clp->m_next = NULL;
+	*cpp = clp;
+}
+
 /* if canonical is set, then we *know* this is already a canonical name
  * so hostname lookup is avoided.
  * This is used when reading /proc/fs/nfs/exports
@@ -209,20 +221,6 @@ client_dup(nfs_client *clp, struct hostent *hp)
 }
 
 void
-client_add(nfs_client *clp)
-{
-	nfs_client	**cpp;
-
-	if (clp->m_type < 0 || clp->m_type >= MCL_MAXTYPES)
-		xlog(L_FATAL, "unknown client type in client_add");
-	cpp = clientlist + clp->m_type;
-	while (*cpp)
-		cpp = &((*cpp)->m_next);
-	clp->m_next = NULL;
-	*cpp = clp;
-}
-
-void
 client_release(nfs_client *clp)
 {
 	if (clp->m_count <= 0)
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
index 9a19cbb..05891c5 100644
--- a/support/include/exportfs.h
+++ b/support/include/exportfs.h
@@ -69,7 +69,6 @@ extern exp_hash_table exportlist[MCL_MAXTYPES];
 extern nfs_client *		clientlist[MCL_MAXTYPES];
 
 nfs_client *			client_lookup(char *hname, int canonical);
-void				client_add(nfs_client *);
 nfs_client *			client_dup(nfs_client *, struct hostent *);
 int				client_gettype(char *hname);
 int				client_check(nfs_client *, struct hostent *);


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] mountd/exportfs: Make m_addrlist field a nfs_sockaddr
       [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-05-03 19:24   ` [PATCH 1/3] libexport.a: Refactor client_init() Chuck Lever
  2010-05-03 19:24   ` [PATCH 2/3] libexport.a: Clean up client_add() Chuck Lever
@ 2010-05-03 19:24   ` Chuck Lever
  2010-05-05 19:39   ` [PATCH 0/3] Three more IPv6-related mountd patches Steve Dickson
  3 siblings, 0 replies; 5+ messages in thread
From: Chuck Lever @ 2010-05-03 19:24 UTC (permalink / raw)
  To: steved; +Cc: linux-nfs

To store non-AF_INET addresses in the nfs_client structure, we need to
use more than in_addr for the m_addrlist field.  Make m_addrlist
larger, then add a few helper functions to handle type casting and
array indexing cleanly.

We could treat the nfs_client address list as if all the addresses
in the list were the same family.  This might work for MCL_SUBNETWORK
type nfs_clients.  However, during the transition to IPv6, most hosts
will have at least one IPv4 and one IPv6 address.  For MCL_FQDN, I
think we need to have the ability to store addresses from both
families in one nfs_client.

Additionally, IPv6 scope IDs are not part of struct sin6_addr.  To
support link-local IPv6 addresses and the like, a scope ID must be
stored.

Thus, each slot in the address list needs to be capable of storing an
entire socket address, and not simply the network address part.

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

 support/export/client.c    |   39 ++++++++++++++++++++++++++---------
 support/export/nfsctl.c    |   17 ++++++++++++---
 support/include/exportfs.h |   49 +++++++++++++++++++++++++++++++++++++++++++-
 utils/mountd/auth.c        |    2 +-
 utils/mountd/cache.c       |    3 ++-
 5 files changed, 93 insertions(+), 17 deletions(-)

diff --git a/support/export/client.c b/support/export/client.c
index 4600255..21ad272 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -37,6 +37,9 @@ nfs_client	*clientlist[MCL_MAXTYPES] = { NULL, };
 static void
 init_addrlist(nfs_client *clp, const struct hostent *hp)
 {
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+	};
 	char **ap;
 	int i;
 
@@ -44,9 +47,10 @@ init_addrlist(nfs_client *clp, const struct hostent *hp)
 		return;
 
 	ap = hp->h_addr_list;
-	for (i = 0; *ap != NULL && i < NFSCLNT_ADDRMAX; i++, ap++)
-		clp->m_addrlist[i] = *(struct in_addr *)*ap;
-
+	for (i = 0; *ap != NULL && i < NFSCLNT_ADDRMAX; i++, ap++) {
+		sin.sin_addr = *(struct in_addr *)*ap;
+		set_addrlist_in(clp, i, &sin);
+	}
 	clp->m_naddr = i;
 }
 
@@ -60,17 +64,22 @@ client_free(nfs_client *clp)
 static int
 init_netmask(nfs_client *clp, const char *slash)
 {
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+	};
+
 	if (strchr(slash + 1, '.') != NULL)
-		clp->m_addrlist[1].s_addr = inet_addr(slash + 1);
+		sin.sin_addr.s_addr = inet_addr(slash + 1);
 	else {
 		int prefixlen = atoi(slash + 1);
 		if (0 < prefixlen && prefixlen <= 32)
-			clp->m_addrlist[1].s_addr =
+			sin.sin_addr.s_addr =
 					htonl((uint32_t)~0 << (32 - prefixlen));
 		else
 			goto out_badprefix;
 	}
 
+	set_addrlist_in(clp, 1, &sin);
 	return 1;
 
 out_badprefix:
@@ -81,6 +90,9 @@ out_badprefix:
 static int
 init_subnetwork(nfs_client *clp)
 {
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+	};
 	static char slash32[] = "/32";
 	char *cp;
 
@@ -89,7 +101,8 @@ init_subnetwork(nfs_client *clp)
 		cp = slash32;
 
 	*cp = '\0';
-	clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
+	sin.sin_addr.s_addr = inet_addr(clp->m_hostname);
+	set_addrlist_in(clp, 0, &sin);
 	*cp = '/';
 
 	return init_netmask(clp, cp);
@@ -366,6 +379,7 @@ add_name(char *old, const char *add)
 static int
 check_fqdn(const nfs_client *clp, const struct hostent *hp)
 {
+	const struct sockaddr_in *sin;
 	struct in_addr addr;
 	char **ap;
 	int i;
@@ -373,9 +387,11 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp)
 	for (ap = hp->h_addr_list; *ap; ap++) {
 		addr = *(struct in_addr *)*ap;
 
-		for (i = 0; i < clp->m_naddr; i++)
-			if (clp->m_addrlist[i].s_addr == addr.s_addr)
+		for (i = 0; i < clp->m_naddr; i++) {
+			sin = get_addrlist_in(clp, i);
+			if (sin->sin_addr.s_addr == addr.s_addr)
 				return 1;
+		}
 	}
 	return 0;
 }
@@ -388,14 +404,17 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp)
 static int
 check_subnetwork(const nfs_client *clp, const struct hostent *hp)
 {
+	const struct sockaddr_in *address, *mask;
 	struct in_addr addr;
 	char **ap;
 
 	for (ap = hp->h_addr_list; *ap; ap++) {
+		address = get_addrlist_in(clp, 0);
+		mask = get_addrlist_in(clp, 1);
 		addr = *(struct in_addr *)*ap;
 
-		if (!((clp->m_addrlist[0].s_addr ^ addr.s_addr) &
-		      clp->m_addrlist[1].s_addr))
+		if (!((address->sin_addr.s_addr ^ addr.s_addr) &
+		      mask->sin_addr.s_addr))
 			return 1;
 	}
 	return 0;
diff --git a/support/export/nfsctl.c b/support/export/nfsctl.c
index e2877b9..ae357c7 100644
--- a/support/export/nfsctl.c
+++ b/support/export/nfsctl.c
@@ -66,7 +66,7 @@ str_tolower(char *s)
 static int
 cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
 {
-	int	i;
+	int i, j;
 
 	if (clp->m_type != MCL_FQDN) {
 		xlog(L_ERROR, "internal: can't export non-FQDN host");
@@ -76,10 +76,19 @@ cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
 	strncpy(cltarg->cl_ident, clp->m_hostname,
 		sizeof (cltarg->cl_ident) - 1);
 	str_tolower(cltarg->cl_ident);
-	cltarg->cl_naddr = clp->m_naddr;
-	for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++)
-		cltarg->cl_addrlist[i] = clp->m_addrlist[i];
 
+	j = 0;
+	for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++) {
+		struct sockaddr_in *sin = get_addrlist_in(clp, i);
+		if (sin->sin_family == AF_INET)
+			cltarg->cl_addrlist[j++] = sin->sin_addr;
+	}
+	if (j == 0) {
+		xlog(L_ERROR, "internal: no supported addresses in nfs_client");
+		return 0;
+	}
+
+	cltarg->cl_naddr = j;
 	return 1;
 }
 
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
index 05891c5..70bdd57 100644
--- a/support/include/exportfs.h
+++ b/support/include/exportfs.h
@@ -10,6 +10,8 @@
 #define EXPORTFS_H
 
 #include <netdb.h>
+
+#include "sockaddr.h"
 #include "nfslib.h"
 
 enum {
@@ -35,11 +37,56 @@ typedef struct mclient {
 	char *			m_hostname;
 	int			m_type;
 	int			m_naddr;
-	struct in_addr		m_addrlist[NFSCLNT_ADDRMAX];
+	union nfs_sockaddr	m_addrlist[NFSCLNT_ADDRMAX];
 	int			m_exported;	/* exported to nfsd */
 	int			m_count;
 } nfs_client;
 
+static inline const struct sockaddr *
+get_addrlist(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].sa;
+}
+
+static inline const struct sockaddr_in *
+get_addrlist_in(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].s4;
+}
+
+static inline const struct sockaddr_in6 *
+get_addrlist_in6(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].s6;
+}
+
+static inline void
+set_addrlist_in(nfs_client *clp, const int i, const struct sockaddr_in *sin)
+{
+	memcpy(&clp->m_addrlist[i].s4, sin, sizeof(*sin));
+}
+
+static inline void
+set_addrlist_in6(nfs_client *clp, const int i, const struct sockaddr_in6 *sin6)
+{
+	memcpy(&clp->m_addrlist[i].s6, sin6, sizeof(*sin6));
+}
+
+static inline void
+set_addrlist(nfs_client *clp, const int i, const struct sockaddr *sap)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		memcpy(&clp->m_addrlist[i].s4, sap, sizeof(struct sockaddr_in));
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		memcpy(&clp->m_addrlist[i].s6, sap, sizeof(struct sockaddr_in6));
+		break;
+#endif
+	}
+}
+
 typedef struct mexport {
 	struct mexport *	m_next;
 	struct mclient *	m_client;
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
index 13eba70..4b94b98 100644
--- a/utils/mountd/auth.c
+++ b/utils/mountd/auth.c
@@ -142,7 +142,7 @@ auth_authenticate_newcache(char *what, struct sockaddr_in *caller,
 		return NULL;
 
 	my_client.m_naddr = 1;
-	my_client.m_addrlist[0] = caller->sin_addr;
+	set_addrlist_in(&my_client, 0, caller);
 	my_exp.m_client = &my_client;
 
 	exp = NULL;
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 6343325..caef5b2 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -863,6 +863,7 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path)
 
 int cache_export(nfs_export *exp, char *path)
 {
+	struct sockaddr_in *sin = get_addrlist_in(exp->m_client, 0);
 	int err;
 	FILE *f;
 
@@ -871,7 +872,7 @@ int cache_export(nfs_export *exp, char *path)
 		return -1;
 
 	qword_print(f, "nfsd");
-	qword_print(f, inet_ntoa(exp->m_client->m_addrlist[0]));
+	qword_print(f, inet_ntoa(sin->sin_addr));
 	qword_printint(f, time(0)+30*60);
 	qword_print(f, exp->m_client->m_hostname);
 	err = qword_eol(f);


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] Three more IPv6-related mountd patches
       [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
                     ` (2 preceding siblings ...)
  2010-05-03 19:24   ` [PATCH 3/3] mountd/exportfs: Make m_addrlist field a nfs_sockaddr Chuck Lever
@ 2010-05-05 19:39   ` Steve Dickson
  3 siblings, 0 replies; 5+ messages in thread
From: Steve Dickson @ 2010-05-05 19:39 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs



On 05/03/2010 03:23 PM, Chuck Lever wrote:
> Hi Steve-
> 
> Here are two clean-up patches, and one patch that modifies the
> nfs_client struct so it can store both IPv4 and IPv6 addresses
> concurrently.
> 
> ---
> 
> Chuck Lever (3):
>       mountd/exportfs: Make m_addrlist field a nfs_sockaddr
>       libexport.a: Clean up client_add()
>       libexport.a: Refactor client_init()
> 
> 
>  support/export/client.c    |  158 ++++++++++++++++++++++++++------------------
>  support/export/nfsctl.c    |   17 ++++-
>  support/include/exportfs.h |   50 +++++++++++++-
>  utils/mountd/auth.c        |    2 -
>  utils/mountd/cache.c       |    3 +
>  5 files changed, 158 insertions(+), 72 deletions(-)
> 
All three committed and pushed...

steved.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-05-05 19:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-03 19:23 [PATCH 0/3] Three more IPv6-related mountd patches Chuck Lever
     [not found] ` <20100503192041.29316.35846.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-05-03 19:24   ` [PATCH 1/3] libexport.a: Refactor client_init() Chuck Lever
2010-05-03 19:24   ` [PATCH 2/3] libexport.a: Clean up client_add() Chuck Lever
2010-05-03 19:24   ` [PATCH 3/3] mountd/exportfs: Make m_addrlist field a nfs_sockaddr Chuck Lever
2010-05-05 19:39   ` [PATCH 0/3] Three more IPv6-related mountd patches Steve Dickson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).