diff -p -u -r -N linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c --- linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c 2007-10-11 15:23:07.000000000 +0200 +++ linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c 2007-10-12 10:49:31.000000000 +0200 @@ -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;