Skip to contentSkip to conversation

NFS: handle IPv6 addresses in nfs ctl

PATCH In review Aurélien Charbon 3 participants 5 messages Oct 22, 2007 – Nov 5, 2007

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 2/2 NFS: handle IPv6 addresses in nfs ctl

Here is a second missing part of the IPv6 support in NFS server code concerning knfd syscall interface. It updates write_getfd and write_getfd to accept IPv6 addresses.

I've updated it according to Brian's comments, and removed some unused code.

Applies on a kernel including ip_map cache modifications

Tests: tested with only IPv4 network and basic nfs ops (mount, file creation and modification)

---

fs/nfsd/nfsctl.c 2007-10-22 11:06:13.000000000 +0200 renamed from fs/nfsd/nfsctl.c 2007-10-22 10:32:51.000000000 +0200 +0 -0
diff -p -u -r -N linux-2.6.23-ipmap/fs/nfsd/nfsctl.c linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c
@@ -219,7 +219,7 @@ static ssize_t write_unexport(struct fil

static ssize_t write_getfs(struct file *file, char *buf, size_t size)

{
    struct nfsctl_fsparm *data;
-    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin6, sin6_storage;
    struct auth_domain *clp;
    int err = 0;
    struct knfsd_fh *res;
@@ -229,9 +229,20 @@ static ssize_t write_getfs(struct file *
        return -EINVAL;
    data = (struct nfsctl_fsparm*)buf;
    err = -EPROTONOSUPPORT;
-    if (data->gd_addr.sa_family != AF_INET)
+    switch (data->gd_addr.sa_family) {
+    case AF_INET6:
+        sin6 = &sin6_storage;
+        sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+        ipv6_addr_copy(&in6, &(sin6->sin6_addr));
+        break;
+    case AF_INET:
+        /* Map v4 address into v6 structure */
+        ipv6_addr_set(&in6, 0, 0, htonl(0x0000FFFF), (((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
+        break;
+    default:
        goto out;
-    sin = (struct sockaddr_in *)&data->gd_addr;
+    }
+
    if (data->gd_maxlen > NFS3_FHSIZE)
        data->gd_maxlen = NFS3_FHSIZE;

@@ -239,10 +250,7 @@ static ssize_t write_getfs(struct file *

    exp_readlock();

- /* IPv6 address mapping */
- ipv6_addr_set(&in6, 0, 0, htonl(0x0000FFFF), (((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
-
- if (!(clp = auth_unix_lookup(in6)))
+ if (!(clp = auth_unix_lookup(&in6)))

        err = -EPERM;
    else {
        err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -258,7 +266,7 @@ static ssize_t write_getfs(struct file *
static ssize_t write_getfd(struct file *file, char *buf, size_t size)
{
    struct nfsctl_fdparm *data;
-    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin6, sin6_storage;
    struct auth_domain *clp;
    int err = 0;
    struct knfsd_fh fh;
@@ -269,20 +277,30 @@ static ssize_t write_getfd(struct file *
        return -EINVAL;
    data = (struct nfsctl_fdparm*)buf;
    err = -EPROTONOSUPPORT;
-    if (data->gd_addr.sa_family != AF_INET)
+    if (data->gd_addr.sa_family != AF_INET && data->gd_addr.sa_family != AF_INET6)
        goto out;
    err = -EINVAL;
    if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
        goto out;

    res = buf;
-    sin = (struct sockaddr_in *)&data->gd_addr;
    exp_readlock();

- - /* IPv6 address mapping */
- ipv6_addr_set(&in6, 0, 0, htonl(0x0000FFFF), (((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));

- if (!(clp = auth_unix_lookup(in6)))
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:

+        /* IPv6 address mapping */
+        ipv6_addr_set(&in6, 0, 0, htonl(0x0000FFFF), ((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr);
+        break;
+    case AF_INET6:
+        sin6 = &sin6_storage;
+        sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+        ipv6_addr_copy(&in6, &(sin6->sin6_addr));
+        break;

+ default:
+ BUG();
+ }
+
+ if (!(clp = auth_unix_lookup(&in6)))

        err = -EPERM;
    else {
        err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
Signature · 7 lines
********************************
      Aurelien Charbon
      Linux NFSv4 team
          Bull SAS
    Echirolles - France
http://nfsv4.bullopensource.org/
********************************
fs/nfsd/nfsctl.c +32 -14

85 lines not on this page · raw message

_______________________________________________
NFSv4 mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

#1 lore raw

Hi Aurelien,

Again, a few more comments.

I might just modify these in my own tree and send out a patch that combines both into one, it might be less work.

fs/nfsd/nfsctl.c static ssize_t write_getfs(struct file * · line 234

Quoted 8 lines
fs/nfsd/nfsctl.c +3 -1
@@ -229,9 +229,20 @@ static ssize_t write_getfs(struct file *
 		return -EINVAL;
 	data = (struct nfsctl_fsparm*)buf;
 	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
+	switch (data->gd_addr.sa_family) {
+	case AF_INET6:
+		sin6 = &sin6_storage;

This should be:

	in6 = &sin6_storage;

Review static ssize_t write_getfs(struct file * · line 236

Quoted 2 lines
(quoted diff) +2 -0
+		sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+		ipv6_addr_copy(&in6, &(sin6->sin6_addr)); 

Extra () here.

fs/nfsd/nfsctl.c static ssize_t write_getfd(struct file * · line 295

Quoted 8 lines
fs/nfsd/nfsctl.c +7 -1
-    	if (!(clp = auth_unix_lookup(in6))) 
+	switch (data->gd_addr.sa_family) {
+	case AF_INET:
+		/* IPv6 address mapping */
+		ipv6_addr_set(&in6, 0, 0, htonl(0x0000FFFF), ((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr);
+		break;
+	case AF_INET6:
+		sin6 = &sin6_storage;

This should be:

	in6 = &sin6_storage;

Review static ssize_t write_getfs(struct file * · line 245

Quoted 2 lines
(quoted diff) +2 -0
+		sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+		ipv6_addr_copy(&in6, &(sin6->sin6_addr));

Extra () here.

-Brian

#2 lore raw

Hi Aurelien,

This is a combination of your two patches into one, cleaned-up with all my complaints. I also added an ipv6_addr_set_v4mapped() inline after someone else here convinced me it gets rid of a lot of cruft from the code. The DCCP, etc. code can be cleaned-up later if this gets accepted.

I have only compile-tested this, hoping you can test the functionality.

-Brian

Add IPv6 support to NFS server ip_map caching code and knfsd syscall interface - write_getfs() and write_getfd() will now accept IPv6 addresses.

fs/nfsd/export.c +6 -3
index 66d0aeb..c47ba77 100644
@@ -35,6 +35,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
 
@@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
 {
 	struct auth_domain	*dom;
 	int			i, err;
+	struct in6_addr		in6;
 
 	/* First, consistency check. */
 	err = -EINVAL;
@@ -1574,9 +1576,10 @@ exp_addclient(struct nfsctl_client *ncp)
 		goto out_unlock;
 
 	/* Insert client into hashtable. */
-	for (i = 0; i < ncp->cl_naddr; i++)
-		auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+	for (i = 0; i < ncp->cl_naddr; i++) {
+		ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &in6);
+		auth_unix_add_addr(&in6, dom);
+	}
 	auth_unix_forget_old(dom);
 	auth_domain_put(dom);
 
fs/nfsd/nfsctl.c +36 -6

91 lines not on this page · raw message

include/linux/sunrpc/svcauth.h +3 -2
index 22e1ef8..64ecb93 100644
@@ -15,6 +15,7 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/hash.h>
+#include <net/ipv6.h>
 
 #define SVC_CRED_NGROUPS	32
 struct svc_cred {
@@ -120,10 +121,10 @@ extern void	svc_auth_unregister(rpc_authflavor_t flavor);
 
 extern struct auth_domain *unix_domain_find(char *name);
 extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
+extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
 extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
+extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
include/net/ipv6.h +10 -0
index ae328b6..366fdca 100644
@@ -16,6 +16,7 @@
 #define _NET_IPV6_H
 
 #include <linux/ipv6.h>
+#include <linux/in.h>
 #include <linux/hardirq.h>
 #include <net/if_inet6.h>
 #include <net/ndisc.h>
@@ -400,6 +401,15 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
 		 a->s6_addr32[2] == htonl(0x0000ffff));
 }
 
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+					  struct in6_addr *v4mapped)
+{
+	ipv6_addr_set(v4mapped,
+		      0, 0,
+		      __constant_htonl(0x0000FFFF),
+		      addr);
+}
+
 /*
  * find the first different bit between two addresses
  * length of address must be a multiple of 32bits
net/sunrpc/svcauth_unix.c +79 -39

248 lines not on this page · raw message

#3 lore raw
In reply to Aurélien Charbon
Quoted 3 lines · On Monday October 22, [email protected] wrote:

Here is a second missing part of the IPv6 support in NFS server code concerning knfd syscall interface.
It updates write_getfd and write_getfd to accept IPv6 addresses.

Sorry for not replying to this earlier - I saw the Oct 12 post and thought about it but didn't actually reply before getting distracted :-(

I think this patch is unnecessary and hence not wanted. The getfs / getfs calls should be considered legacy calls. Adding functionality to them is not appropriate.

IPv6 addresses should be handled only via the
/proc/net/rpc/auth.unix.ip
interface.

Thanks,
NeilBrown

#4 lore raw

Hi Neil,
Thank you for the reply.

Quoted 5 lines · Neil Brown
Quoted 5 lines

I think this patch is unnecessary and hence not wanted. The getfs / getfs calls should be considered legacy calls. Adding functionality to them is not appropriate.

I agree with that.
But I don't think we really add functionality here.
Modifications are just necessary to match the auth_unix_lookup new prototype. I don't see how we can avoid that.

Aurélien

Signature · 7 lines
********************************
      Aurelien Charbon
      Linux NFSv4 team
          Bull SAS
    Echirolles - France
http://nfsv4.bullopensource.org/
********************************