All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.