NFS: handle IPv6 addresses in nfs ctl
Subsystems (4)
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.
Applies on a kernel including ip_map cache modifications
Tests: tested with only IPv4 network and basic nfs ops (mount, file creation and modification)
---
nfsctl.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
fs/nfsd/nfsctl.c 2007-10-12 10:49:31.000000000 +0200 renamed from fs/nfsd/nfsctl.c 2007-10-11 15:23:07.000000000 +0200 +0 -0
@@ -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 *sin, sin6_storage;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh *res;
@@ -228,9 +228,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)
+ sin = &sin6_storage;
+ switch (data->gd_addr.sa_family) {
+ case AF_INET6:
+ sin = (struct sockaddr_in6 *)&data->gd_addr;
+ in6 = sin->sin6_addr;
+ break;
+ case AF_INET:
+ /* Map v4 address into v6 structure */
+ ipv6_addr_v4map(((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
+ break;
+ default:
goto out;
- sin = (struct sockaddr_in *)&data->gd_addr;
+ }
+
if (data->gd_maxlen > NFS3_FHSIZE)
data->gd_maxlen = NFS3_FHSIZE;@@ -238,9 +249,6 @@ static ssize_t write_getfs(struct file *
exp_readlock();
- /* IPv6 address mapping */
- ipv6_addr_v4map(sin->sin_addr, in6);
-
if (!(clp = auth_unix_lookup(in6)))
err = -EPERM;
else {
@@ -257,7 +265,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 *sin, sin6_storage;
struct in6_addr in6;
struct auth_domain *clp;
int err = 0;
@@ -268,18 +276,29 @@ 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;
+ sin = &sin6_storage;
exp_readlock();- /* IPv6 address mapping */
- ipv6_addr_v4map(sin->sin_addr, in6);
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:
+ /* IPv6 address mapping */
+ ipv6_addr_v4map(((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
+ break;
+ case AF_INET6:
+ sin = (struct sockaddr_in6 *)&data->gd_addr;
+ in6 = sin->sin6_addr;
+ break;+ default:
+ BUG();
+ }
if (!(clp = auth_unix_lookup(in6)))
err = -EPERM;net/sunrpc/svcauth_unix.c 2007-10-12 10:03:56.000000000 +0200 renamed from net/sunrpc/svcauth_unix.c 2007-10-12 10:47:27.000000000 +0200 +1 -1
@@ -677,7 +677,7 @@ svcauth_unix_set_client(struct svc_rqst case AF_INET: sin = svc_addr_in(rqstp); sin6 = &sin6_storage; - ipv6_addr_set(&sin6->sin6_addr, 0, 0, + ipv6_addr_set(&sin6->sin6_addr, 0, 0, htonl(0x0000FFFF), sin->sin_addr.s_addr); break; case AF_INET6:
Signature · 6 lines
********************************
Aurelien Charbon
Bull SAS
Echirolles - France
http://www.bullopensource.org/
********************************fs/nfsd/nfsctl.c +30 -11
80 lines not on this page · raw message
Hi Aurelien,
Comments in-line.
Review
Quoted 4 lines · Aurélien Charbon
Here is a second missing part of the IPv6 support in NFS server code concerning knfd syscall interface.
(quoted diff) +1
-1- struct sockaddr_in *sin; + struct sockaddr_in6 *sin, sin6_storage;
Nit, should call this sin6 now.
fs/nfsd/nfsctl.c static ssize_t write_getfs(struct file * · line 231
Quoted 6 lines
fs/nfsd/nfsctl.c +1
-1@@ -228,9 +228,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 ) + sin = &sin6_storage;
This should be moved in the AF_INET case.
fs/nfsd/nfsctl.c static ssize_t write_getfs(struct file * · line 235
Quoted 4 lines
fs/nfsd/nfsctl.c +4
-0+switch (data->gd_addr.sa_family) { +case AF_INET6 : + sin = (struct sockaddr_in6 *)&data->gd_addr; + in6 = sin->sin6_addr;
in6 is a structure, not a pointer. If you want it do this you have to use ipv6_addr_copy().
fs/nfsd/nfsctl.c static ssize_t write_getfs(struct file *
Quoted 4 lines
fs/nfsd/nfsctl.c +3
-0+case AF_INET : +/* Map v4 address into v6 structure */ +ipv6_addr_v4map (((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
ipv6_addr_set(...)
fs/nfsd/nfsctl.c static ssize_t write_getfs(struct file * · line 268
Quoted 6 lines
fs/nfsd/nfsctl.c +1
-1@@ -257,7 +265,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 *sin, sin6_storage;
Nit, sin -> sin6.
Quoted 5 lines
fs/nfsd/nfsctl.c +0
-1@@ -268,18 +276,29 @@ static ssize_t write_getfd(struct file *return -EINVAL ; data = (struct nfsctl_fdparm *)buf; err = -EPROTONOSUPPORT ; -if (data->gd_addr.sa_family !=AF_INET )
fs/nfsd/nfsctl.c static ssize_t write_getfd(struct file * · line 287
Quoted 10 lines
fs/nfsd/nfsctl.c +3
-1+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; + sin = &sin6_storage;
Move in AF_INET case.
fs/nfsd/nfsctl.c static ssize_t write_getfd(struct file *
Quoted 7 lines
fs/nfsd/nfsctl.c +4
-2-/* IPv6 address mapping */ -ipv6_addr_v4map (sin->sin_addr, in6); +switch (data->gd_addr.sa_family) { +case AF_INET : +/* IPv6 address mapping */ +ipv6_addr_v4map (((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
Use ipv6_set_addr(...)
fs/nfsd/nfsctl.c static ssize_t write_getfd(struct file * · line 297
Quoted 4 lines
fs/nfsd/nfsctl.c +4
-0+break ; +case AF_INET6 : + sin = (struct sockaddr_in6 *)&data->gd_addr; + in6 = sin->sin6_addr;
Must use ipv6_addr_copy() here too.
-Brian