All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5)
@ 2009-08-14 16:57 Jeff Layton
  2009-08-14 16:57 ` [PATCH 1/6] sunrpc: add routine for comparing addresses Jeff Layton
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

Fifth attempt at a patchset to add support for NFSv4 callbacks over
IPv6. Changes from last patchset are mostly to address Chuck's comments:

1) made the new address comparison and copy routines into static inlines
and added them to clnt.h. Ditto for the get_scope_id function.

2) combined the patch to change nfs4_cb_conn to hold address in
sockaddr_storage with the one to convert gen_callback to use
rpc_uaddr2sockaddr. That eliminates changes to the parse_ipv4 function
that eventually gets ripped out.

Tested using opensolaris and linux and verifying that delegations could
be properly recalled. I also tested mounts to the server's link-local
address and verified that the callback channel connected correctly.

Jeff Layton (6):
  sunrpc: add routine for comparing addresses
  sunrpc: add common routine for copying address portion of a sockaddr
  nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
  nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage
  nfsd: add support for NFSv4 callbacks over IPv6
  nfsd: populate sin6_scope_id on callback address with scopeid from
    rq_addr on SETCLIENTID call

 fs/lockd/clntlock.c         |    2 +-
 fs/lockd/host.c             |    4 +-
 fs/lockd/mon.c              |    2 +-
 fs/lockd/svcsubs.c          |    2 +-
 fs/nfsd/nfs4callback.c      |   11 +---
 fs/nfsd/nfs4state.c         |  133 ++++++++++++++-----------------------------
 include/linux/lockd/lockd.h |   43 --------------
 include/linux/nfsd/state.h  |    6 +-
 include/linux/sunrpc/clnt.h |  113 ++++++++++++++++++++++++++++++++++++
 9 files changed, 166 insertions(+), 150 deletions(-)

_______________________________________________
NFSv4 mailing list
NFSv4@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

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

* [PATCH 1/6] sunrpc: add routine for comparing addresses
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 16:57 ` [PATCH 2/6] sunrpc: add common routine for copying address portion of a sockaddr Jeff Layton
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

lockd needs these sort of routines, as does the NFSv4 callback code.

Move lockd's routines into common code and rename them so that they can
be used by others.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/lockd/clntlock.c         |    2 +-
 fs/lockd/host.c             |    4 +-
 fs/lockd/mon.c              |    2 +-
 fs/lockd/svcsubs.c          |    2 +-
 include/linux/lockd/lockd.h |   43 --------------------------------------
 include/linux/sunrpc/clnt.h |   48 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 1f3b0fc..fc9032d 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -166,7 +166,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
 		 */
 		if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
 			continue;
-		if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
+		if (!rpc_cmp_addr(nlm_addr(block->b_host), addr))
 			continue;
 		if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
 			continue;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 7cb076a..4600c20 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -111,7 +111,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
 	 */
 	chain = &nlm_hosts[nlm_hash_address(ni->sap)];
 	hlist_for_each_entry(host, pos, chain, h_hash) {
-		if (!nlm_cmp_addr(nlm_addr(host), ni->sap))
+		if (!rpc_cmp_addr(nlm_addr(host), ni->sap))
 			continue;
 
 		/* See if we have an NSM handle for this client */
@@ -125,7 +125,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
 		if (host->h_server != ni->server)
 			continue;
 		if (ni->server &&
-		    !nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
+		    !rpc_cmp_addr(nlm_srcaddr(host), ni->src_sap))
 			continue;
 
 		/* Move to head of hash chain. */
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 30c9331..f956651 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -209,7 +209,7 @@ static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
 	struct nsm_handle *nsm;
 
 	list_for_each_entry(nsm, &nsm_handles, sm_link)
-		if (nlm_cmp_addr(nsm_addr(nsm), sap))
+		if (rpc_cmp_addr(nsm_addr(nsm), sap))
 			return nsm;
 	return NULL;
 }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 9e4d6aa..ad478da 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
 static int
 nlmsvc_match_ip(void *datap, struct nlm_host *host)
 {
-	return nlm_cmp_addr(nlm_srcaddr(host), datap);
+	return rpc_cmp_addr(nlm_srcaddr(host), datap);
 }
 
 /**
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index c325b18..e7a251a 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -338,49 +338,6 @@ static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
 	}
 }
 
-static inline int __nlm_cmp_addr4(const struct sockaddr *sap1,
-				  const struct sockaddr *sap2)
-{
-	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
-	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
-	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
-				  const struct sockaddr *sap2)
-{
-	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
-	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
-	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
-}
-#else	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
-static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
-				  const struct sockaddr *sap2)
-{
-	return 0;
-}
-#endif	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
-
-/*
- * Compare two host addresses
- *
- * Return TRUE if the addresses are the same; otherwise FALSE.
- */
-static inline int nlm_cmp_addr(const struct sockaddr *sap1,
-			       const struct sockaddr *sap2)
-{
-	if (sap1->sa_family == sap2->sa_family) {
-		switch (sap1->sa_family) {
-		case AF_INET:
-			return __nlm_cmp_addr4(sap1, sap2);
-		case AF_INET6:
-			return __nlm_cmp_addr6(sap1, sap2);
-		}
-	}
-	return 0;
-}
-
 /*
  * Compare two NLM locks.
  * When the second lock is of type F_UNLCK, this acts like a wildcard.
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ab3f6e9..b17df36 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -22,6 +22,7 @@
 #include <linux/sunrpc/timer.h>
 #include <asm/signal.h>
 #include <linux/path.h>
+#include <net/ipv6.h>
 
 struct rpc_inode;
 
@@ -188,5 +189,52 @@ static inline void rpc_set_port(struct sockaddr *sap,
 #define IPV6_SCOPE_DELIMITER		'%'
 #define IPV6_SCOPE_ID_LEN		sizeof("%nnnnnnnnnn")
 
+static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1,
+				   const struct sockaddr *sap2)
+{
+	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
+	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
+
+	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
+				   const struct sockaddr *sap2)
+{
+	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
+	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
+	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
+}
+#else	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
+static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
+				   const struct sockaddr *sap2)
+{
+	return false;
+}
+#endif	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
+
+/**
+ * rpc_cmp_addr - compare the address portion of two sockaddrs.
+ * @sap1: first sockaddr
+ * @sap2: second sockaddr
+ *
+ * Just compares the family and address portion. Ignores port, scope, etc.
+ * Returns true if the addrs are equal, false if they aren't.
+ */
+static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
+				const struct sockaddr *sap2)
+{
+	if (sap1->sa_family == sap2->sa_family) {
+		switch (sap1->sa_family) {
+		case AF_INET:
+			return __rpc_cmp_addr4(sap1, sap2);
+		case AF_INET6:
+			return __rpc_cmp_addr6(sap1, sap2);
+		}
+	}
+	return false;
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
-- 
1.6.0.6

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

* [PATCH 2/6] sunrpc: add common routine for copying address portion of a sockaddr
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
  2009-08-14 16:57 ` [PATCH 1/6] sunrpc: add routine for comparing addresses Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 16:57 ` [PATCH 3/6] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 include/linux/sunrpc/clnt.h |   50 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index b17df36..044f531 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -198,6 +198,17 @@ static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1,
 	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
 }
 
+static inline bool __rpc_copy_addr4(struct sockaddr *dst,
+				    const struct sockaddr *src)
+{
+	const struct sockaddr_in *ssin = (struct sockaddr_in *) src;
+	struct sockaddr_in *dsin = (struct sockaddr_in *) dst;
+
+	dsin->sin_family = ssin->sin_family;
+	dsin->sin_addr.s_addr = ssin->sin_addr.s_addr;
+	return true;
+}
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
 				   const struct sockaddr *sap2)
@@ -206,12 +217,29 @@ static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
 	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
 	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
 }
+
+static inline bool __rpc_copy_addr6(struct sockaddr *dst,
+				    const struct sockaddr *src)
+{
+	const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src;
+	struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst;
+
+	dsin6->sin6_family = ssin6->sin6_family;
+	ipv6_addr_copy(&dsin6->sin6_addr, &ssin6->sin6_addr);
+	return true;
+}
 #else	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
 static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
 				   const struct sockaddr *sap2)
 {
 	return false;
 }
+
+static inline bool __rpc_copy_addr6(struct sockaddr *dst,
+				    const struct sockaddr *src)
+{
+	return false;
+}
 #endif	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
 
 /**
@@ -236,5 +264,27 @@ static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
 	return false;
 }
 
+/**
+ * rpc_copy_addr - copy the address portion of one sockaddr to another
+ * @dst: destination sockaddr
+ * @src: source sockaddr
+ *
+ * Just copies the address portion and family. Ignores port, scope, etc.
+ * Caller is responsible for making certain that dst is large enough to hold
+ * the address in src. Returns true if address family is supported. Returns
+ * false otherwise.
+ */
+static inline bool rpc_copy_addr(struct sockaddr *dst,
+				 const struct sockaddr *src)
+{
+	switch (src->sa_family) {
+	case AF_INET:
+		return __rpc_copy_addr4(dst, src);
+	case AF_INET6:
+		return __rpc_copy_addr6(dst, src);
+	}
+	return false;
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
-- 
1.6.0.6

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

* [PATCH 3/6] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
  2009-08-14 16:57 ` [PATCH 1/6] sunrpc: add routine for comparing addresses Jeff Layton
  2009-08-14 16:57 ` [PATCH 2/6] sunrpc: add common routine for copying address portion of a sockaddr Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 16:57 ` [PATCH 4/6] nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage Jeff Layton
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

It's currently a __be32, which isn't big enough to hold an IPv6 address.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c        |   32 +++++++++++++++++++-------------
 include/linux/nfsd/state.h |    2 +-
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9295c4b..bfc14d8 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -55,6 +55,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/module.h>
 #include <linux/sunrpc/svcauth_gss.h>
+#include <linux/sunrpc/clnt.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -1220,13 +1221,15 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 	int status;
 	unsigned int		strhashval;
 	char			dname[HEXDIR_LEN];
+	char			addr_str[INET6_ADDRSTRLEN];
 	nfs4_verifier		verf = exid->verifier;
-	u32			ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
+	struct sockaddr		*sa = svc_addr(rqstp);
 
+	rpc_ntop(sa, addr_str, sizeof(addr_str));
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
-		" ip_addr=%u flags %x, spa_how %d\n",
+		"ip_addr=%s flags %x, spa_how %d\n",
 		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
-		ip_addr, exid->flags, exid->spa_how);
+		addr_str, exid->flags, exid->spa_how);
 
 	if (!check_name(exid->clname) || (exid->flags & ~EXCHGID4_FLAG_MASK_A))
 		return nfserr_inval;
@@ -1315,7 +1318,7 @@ out_new:
 
 	copy_verf(new, &verf);
 	copy_cred(&new->cl_cred, &rqstp->rq_cred);
-	new->cl_addr = ip_addr;
+	rpc_copy_addr((struct sockaddr *) &new->cl_addr, sa);
 	gen_clid(new);
 	gen_confirm(new);
 	add_to_unconfirmed(new, strhashval);
@@ -1389,7 +1392,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		     struct nfsd4_compound_state *cstate,
 		     struct nfsd4_create_session *cr_ses)
 {
-	u32 ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
+	struct sockaddr *sa = svc_addr(rqstp);
 	struct nfs4_client *conf, *unconf;
 	struct nfsd4_clid_slot *cs_slot = NULL;
 	int status = 0;
@@ -1417,7 +1420,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		cs_slot->sl_seqid++;
 	} else if (unconf) {
 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
-		    (ip_addr != unconf->cl_addr)) {
+		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
 			status = nfserr_clid_inuse;
 			goto out;
 		}
@@ -1564,7 +1567,7 @@ __be32
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		  struct nfsd4_setclientid *setclid)
 {
-	struct sockaddr_in	*sin = svc_addr_in(rqstp);
+	struct sockaddr		*sa = svc_addr(rqstp);
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -1596,8 +1599,11 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		/* RFC 3530 14.2.33 CASE 0: */
 		status = nfserr_clid_inuse;
 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
-			dprintk("NFSD: setclientid: string in use by client"
-				" at %pI4\n", &conf->cl_addr);
+			char addr_str[INET6_ADDRSTRLEN];
+			rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str,
+				 sizeof(addr_str));
+			dprintk("NFSD: setclientid: string in use by client "
+				"at %s\n", addr_str);
 			goto out;
 		}
 	}
@@ -1659,7 +1665,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		gen_clid(new);
 	}
 	copy_verf(new, &clverifier);
-	new->cl_addr = sin->sin_addr.s_addr;
+	rpc_copy_addr((struct sockaddr *) &new->cl_addr, sa);
 	new->cl_flavor = rqstp->rq_flavor;
 	princ = svc_gss_principal(rqstp);
 	if (princ) {
@@ -1693,7 +1699,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 			 struct nfsd4_compound_state *cstate,
 			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	struct sockaddr_in *sin = svc_addr_in(rqstp);
+	struct sockaddr *sa = svc_addr(rqstp);
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -1712,9 +1718,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	unconf = find_unconfirmed_client(clid);
 
 	status = nfserr_clid_inuse;
-	if (conf && conf->cl_addr != sin->sin_addr.s_addr)
+	if (conf && !rpc_cmp_addr((struct sockaddr *) &conf->cl_addr, sa))
 		goto out;
-	if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
+	if (unconf && !rpc_cmp_addr((struct sockaddr *) &unconf->cl_addr, sa))
 		goto out;
 
 	/*
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 58bb197..3510ddd 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -200,7 +200,7 @@ struct nfs4_client {
 	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
-	__be32			cl_addr; 	/* client ipaddress */
+	struct sockaddr_storage	cl_addr; 	/* client ipaddress */
 	u32			cl_flavor;	/* setclientid pseudoflavor */
 	char			*cl_principal;	/* setclientid principal name */
 	struct svc_cred		cl_cred; 	/* setclientid principal */
-- 
1.6.0.6


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

* [PATCH 4/6] nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
                   ` (2 preceding siblings ...)
  2009-08-14 16:57 ` [PATCH 3/6] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 16:57 ` [PATCH 5/6] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

...rather than as a separate address and port fields. This will be
necessary for implementing callbacks over IPv6. Also, convert
gen_callback to use the standard rpcuaddr2sockaddr routine rather than
its own private one.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4callback.c     |   11 +-----
 fs/nfsd/nfs4state.c        |   81 +++++---------------------------------------
 include/linux/nfsd/state.h |    4 +-
 3 files changed, 13 insertions(+), 83 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 3fd23f7..81d1c52 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -377,7 +377,6 @@ static int max_cb_time(void)
 
 int setup_callback_client(struct nfs4_client *clp)
 {
-	struct sockaddr_in	addr;
 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
 	struct rpc_timeout	timeparms = {
 		.to_initval	= max_cb_time(),
@@ -385,8 +384,8 @@ int setup_callback_client(struct nfs4_client *clp)
 	};
 	struct rpc_create_args args = {
 		.protocol	= IPPROTO_TCP,
-		.address	= (struct sockaddr *)&addr,
-		.addrsize	= sizeof(addr),
+		.address	= (struct sockaddr *) &cb->cb_addr,
+		.addrsize	= cb->cb_addrlen,
 		.timeout	= &timeparms,
 		.program	= &cb_program,
 		.prognumber	= cb->cb_prog,
@@ -400,12 +399,6 @@ int setup_callback_client(struct nfs4_client *clp)
 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
 		return -EINVAL;
 
-	/* Initialize address */
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(cb->cb_port);
-	addr.sin_addr.s_addr = htonl(cb->cb_addr);
-
 	/* Create RPC client */
 	client = rpc_create(&args);
 	if (IS_ERR(client)) {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index bfc14d8..96a7423 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -897,76 +897,6 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
 	return NULL;
 }
 
-/* a helper function for parse_callback */
-static int
-parse_octet(unsigned int *lenp, char **addrp)
-{
-	unsigned int len = *lenp;
-	char *p = *addrp;
-	int n = -1;
-	char c;
-
-	for (;;) {
-		if (!len)
-			break;
-		len--;
-		c = *p++;
-		if (c == '.')
-			break;
-		if ((c < '0') || (c > '9')) {
-			n = -1;
-			break;
-		}
-		if (n < 0)
-			n = 0;
-		n = (n * 10) + (c - '0');
-		if (n > 255) {
-			n = -1;
-			break;
-		}
-	}
-	*lenp = len;
-	*addrp = p;
-	return n;
-}
-
-/* parse and set the setclientid ipv4 callback address */
-static int
-parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
-{
-	int temp = 0;
-	u32 cbaddr = 0;
-	u16 cbport = 0;
-	u32 addrlen = addr_len;
-	char *addr = addr_val;
-	int i, shift;
-
-	/* ipaddress */
-	shift = 24;
-	for(i = 4; i > 0  ; i--) {
-		if ((temp = parse_octet(&addrlen, &addr)) < 0) {
-			return 0;
-		}
-		cbaddr |= (temp << shift);
-		if (shift > 0)
-		shift -= 8;
-	}
-	*cbaddrp = cbaddr;
-
-	/* port */
-	shift = 8;
-	for(i = 2; i > 0  ; i--) {
-		if ((temp = parse_octet(&addrlen, &addr)) < 0) {
-			return 0;
-		}
-		cbport |= (temp << shift);
-		if (shift > 0)
-			shift -= 8;
-	}
-	*cbportp = cbport;
-	return 1;
-}
-
 static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
@@ -976,14 +906,21 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 	if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
 		goto out_err;
 
-	if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
-	                 &cb->cb_addr, &cb->cb_port)))
+	cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
+					    se->se_callback_addr_len,
+					    (struct sockaddr *) &cb->cb_addr,
+					    sizeof(cb->cb_addr));
+
+	if (!cb->cb_addrlen || cb->cb_addr.ss_family != AF_INET)
 		goto out_err;
+
 	cb->cb_minorversion = 0;
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
 	return;
 out_err:
+	cb->cb_addr.ss_family = AF_UNSPEC;
+	cb->cb_addrlen = 0;
 	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
 		"will not receive delegations\n",
 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 3510ddd..fb0c404 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -81,8 +81,8 @@ struct nfs4_delegation {
 /* client delegation callback info */
 struct nfs4_cb_conn {
 	/* SETCLIENTID info */
-	u32                     cb_addr;
-	unsigned short          cb_port;
+	struct sockaddr_storage	cb_addr;
+	size_t			cb_addrlen;
 	u32                     cb_prog;
 	u32			cb_minorversion;
 	u32                     cb_ident;	/* minorversion 0 only */
-- 
1.6.0.6


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

* [PATCH 5/6] nfsd: add support for NFSv4 callbacks over IPv6
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
                   ` (3 preceding siblings ...)
  2009-08-14 16:57 ` [PATCH 4/6] nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 16:57 ` [PATCH 6/6] nfsd: populate sin6_scope_id on callback address with scopeid from rq_addr on SETCLIENTID call Jeff Layton
  2009-08-14 18:05 ` [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Chuck Lever
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

The framework to add this is all in place. Now, add the code to allow
support for establishing a callback channel on an IPv6 socket.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 96a7423..9ec0ca1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -901,9 +901,16 @@ static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
-
-	/* Currently, we only support tcp for the callback channel */
-	if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
+	unsigned short expected_family;
+
+	/* Currently, we only support tcp and tcp6 for the callback channel */
+	if (se->se_callback_netid_len == 3 &&
+	    !memcmp(se->se_callback_netid_val, "tcp", 3))
+		expected_family = AF_INET;
+	else if (se->se_callback_netid_len == 4 &&
+		 !memcmp(se->se_callback_netid_val, "tcp6", 4))
+		expected_family = AF_INET6;
+	else
 		goto out_err;
 
 	cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
@@ -911,7 +918,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 					    (struct sockaddr *) &cb->cb_addr,
 					    sizeof(cb->cb_addr));
 
-	if (!cb->cb_addrlen || cb->cb_addr.ss_family != AF_INET)
+	if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family)
 		goto out_err;
 
 	cb->cb_minorversion = 0;
-- 
1.6.0.6

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

* [PATCH 6/6] nfsd: populate sin6_scope_id on callback address with scopeid from rq_addr on SETCLIENTID call
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
                   ` (4 preceding siblings ...)
  2009-08-14 16:57 ` [PATCH 5/6] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
@ 2009-08-14 16:57 ` Jeff Layton
  2009-08-14 18:05 ` [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Chuck Lever
  6 siblings, 0 replies; 9+ messages in thread
From: Jeff Layton @ 2009-08-14 16:57 UTC (permalink / raw)
  To: bfields, chuck.lever; +Cc: linux-nfs, nfsv4

When a SETCLIENTID call comes in, one of the args given is the svc_rqst.
This struct contains an rq_addr field which holds the address that sent
the call. If this is an IPv6 address, then we can use the sin6_scope_id
field in this address to populate the sin6_scope_id field in the
callback address.

AFAICT, the rq_addr.sin6_scope_id is non-zero if and only if the client
mounted the server's link-local address.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c         |    7 +++++--
 include/linux/sunrpc/clnt.h |   15 +++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9ec0ca1..d2a0524 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -898,7 +898,7 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
 }
 
 static void
-gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
+gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
 {
 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
 	unsigned short expected_family;
@@ -921,6 +921,9 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 	if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family)
 		goto out_err;
 
+	if (cb->cb_addr.ss_family == AF_INET6)
+		((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid;
+
 	cb->cb_minorversion = 0;
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
@@ -1621,7 +1624,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	}
 	copy_cred(&new->cl_cred, &rqstp->rq_cred);
 	gen_confirm(new);
-	gen_callback(new, setclid);
+	gen_callback(new, setclid, rpc_get_scope_id(sa));
 	add_to_unconfirmed(new, strhashval);
 	setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
 	setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 044f531..3d02558 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -286,5 +286,20 @@ static inline bool rpc_copy_addr(struct sockaddr *dst,
 	return false;
 }
 
+/**
+ * rpc_get_scope_id - return scopeid for a given sockaddr
+ * @sa: sockaddr to get scopeid from
+ *
+ * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if
+ * not an AF_INET6 address.
+ */
+static inline u32 rpc_get_scope_id(const struct sockaddr *sa)
+{
+	if (sa->sa_family != AF_INET6)
+		return 0;
+
+	return ((struct sockaddr_in6 *) sa)->sin6_scope_id;
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
-- 
1.6.0.6

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

* Re: [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5)
  2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
                   ` (5 preceding siblings ...)
  2009-08-14 16:57 ` [PATCH 6/6] nfsd: populate sin6_scope_id on callback address with scopeid from rq_addr on SETCLIENTID call Jeff Layton
@ 2009-08-14 18:05 ` Chuck Lever
  2009-08-21 15:44   ` J. Bruce Fields
  6 siblings, 1 reply; 9+ messages in thread
From: Chuck Lever @ 2009-08-14 18:05 UTC (permalink / raw)
  To: Jeff Layton, Bruce Fields; +Cc: NFS list, Linux NFSv4 mailing list

On Aug 14, 2009, at 12:57 PM, Jeff Layton wrote:
> Fifth attempt at a patchset to add support for NFSv4 callbacks over
> IPv6. Changes from last patchset are mostly to address Chuck's  
> comments:
>
> 1) made the new address comparison and copy routines into static  
> inlines
> and added them to clnt.h. Ditto for the get_scope_id function.
>
> 2) combined the patch to change nfs4_cb_conn to hold address in
> sockaddr_storage with the one to convert gen_callback to use
> rpc_uaddr2sockaddr. That eliminates changes to the parse_ipv4 function
> that eventually gets ripped out.
>
> Tested using opensolaris and linux and verifying that delegations  
> could
> be properly recalled. I also tested mounts to the server's link-local
> address and verified that the callback channel connected correctly.

Looks good.

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

> Jeff Layton (6):
>  sunrpc: add routine for comparing addresses
>  sunrpc: add common routine for copying address portion of a sockaddr
>  nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
>  nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage
>  nfsd: add support for NFSv4 callbacks over IPv6
>  nfsd: populate sin6_scope_id on callback address with scopeid from
>    rq_addr on SETCLIENTID call
>
> fs/lockd/clntlock.c         |    2 +-
> fs/lockd/host.c             |    4 +-
> fs/lockd/mon.c              |    2 +-
> fs/lockd/svcsubs.c          |    2 +-
> fs/nfsd/nfs4callback.c      |   11 +---
> fs/nfsd/nfs4state.c         |  133 +++++++++++++ 
> +-----------------------------
> include/linux/lockd/lockd.h |   43 --------------
> include/linux/nfsd/state.h  |    6 +-
> include/linux/sunrpc/clnt.h |  113 ++++++++++++++++++++++++++++++++++ 
> ++
> 9 files changed, 166 insertions(+), 150 deletions(-)
>

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

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

* Re: [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5)
  2009-08-14 18:05 ` [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Chuck Lever
@ 2009-08-21 15:44   ` J. Bruce Fields
  0 siblings, 0 replies; 9+ messages in thread
From: J. Bruce Fields @ 2009-08-21 15:44 UTC (permalink / raw)
  To: Chuck Lever; +Cc: Jeff Layton, NFS list, Linux NFSv4 mailing list

On Fri, Aug 14, 2009 at 02:05:03PM -0400, Chuck Lever wrote:
> On Aug 14, 2009, at 12:57 PM, Jeff Layton wrote:
>> Fifth attempt at a patchset to add support for NFSv4 callbacks over
>> IPv6. Changes from last patchset are mostly to address Chuck's  
>> comments:
>>
>> 1) made the new address comparison and copy routines into static  
>> inlines
>> and added them to clnt.h. Ditto for the get_scope_id function.
>>
>> 2) combined the patch to change nfs4_cb_conn to hold address in
>> sockaddr_storage with the one to convert gen_callback to use
>> rpc_uaddr2sockaddr. That eliminates changes to the parse_ipv4 function
>> that eventually gets ripped out.
>>
>> Tested using opensolaris and linux and verifying that delegations  
>> could
>> be properly recalled. I also tested mounts to the server's link-local
>> address and verified that the callback channel connected correctly.
>
> Looks good.
>
> Acked-by: Chuck Lever <chuck.lever@oracle.com>

Applied, thanks to you both.

--b.

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

end of thread, other threads:[~2009-08-21 15:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-14 16:57 [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Jeff Layton
2009-08-14 16:57 ` [PATCH 1/6] sunrpc: add routine for comparing addresses Jeff Layton
2009-08-14 16:57 ` [PATCH 2/6] sunrpc: add common routine for copying address portion of a sockaddr Jeff Layton
2009-08-14 16:57 ` [PATCH 3/6] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
2009-08-14 16:57 ` [PATCH 4/6] nfsd: convert nfs4_cb_conn struct to hold address in sockaddr_storage Jeff Layton
2009-08-14 16:57 ` [PATCH 5/6] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
2009-08-14 16:57 ` [PATCH 6/6] nfsd: populate sin6_scope_id on callback address with scopeid from rq_addr on SETCLIENTID call Jeff Layton
2009-08-14 18:05 ` [PATCH 0/6] nfsd: add support for NFSv4 callbacks over IPv6 (try #5) Chuck Lever
2009-08-21 15:44   ` J. Bruce Fields

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.