Add the support of IPv6 in the NFSD server.

Signed-off-by: Gilles Quillard <gilles.quillard@bull.net>
---

diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/export.c linux-2.6.9-cel5-gq-04/fs/nfsd/export.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/export.c	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/export.c	2005-01-21 17:06:29.000000000 +0100
@@ -1162,7 +1162,7 @@
 
 	/* Insert client into hashtable. */
 	for (i = 0; i < ncp->cl_naddr; i++)
-		auth_unix_add_addr(ncp->cl_addrlist[i], dom);
+		auth_unix_add_addr6(&ncp->cl_addrlist[i], dom);
 
 	auth_unix_forget_old(dom);
 	auth_domain_put(dom);
diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/nfs4callback.c linux-2.6.9-cel5-gq-04/fs/nfsd/nfs4callback.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/nfs4callback.c	2005-01-03 13:26:04.000000000 +0100
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/nfs4callback.c	2005-01-21 17:06:29.000000000 +0100
@@ -518,7 +518,7 @@
 void
 nfsd4_probe_callback(struct nfs4_client *clp)
 {
-	struct sockaddr_in	addr;
+	struct sockaddr_in6	addr;
 	struct nfs4_callback *	cb = &clp->cl_callback;
 	struct rpc_timeout	timeparms = {
 		.to_initval	= (1U * HZ),
@@ -552,9 +552,9 @@
 
 	/* 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);
+	addr.sin6_family = AF_INET6;
+	addr.sin6_port = htons(cb->cb_port);
+	memcpy(&addr.sin6_addr, &cb->cb_addr, sizeof(struct in6_addr));
 
 	/* Initialize rpc_program */
 	program->name = "nfs4_cb";
@@ -609,7 +609,6 @@
 {
 	struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
 	struct nfs4_callback *cb = &clp->cl_callback;
-	u32 addr = htonl(cb->cb_addr);
 
 	dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status);
 
@@ -619,7 +618,8 @@
 		goto out;
 	}
 	atomic_set(&cb->cb_set, 1);
-	dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr));
+	dprintk("NFSD: callback set to client %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+		NIP6(cb->cb_addr));
 out:
 	put_nfs4_client(clp);
 }
diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/nfs4state.c linux-2.6.9-cel5-gq-04/fs/nfsd/nfs4state.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/nfs4state.c	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/nfs4state.c	2005-01-24 15:36:10.000000000 +0100
@@ -499,7 +499,8 @@
 
 /* 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)
+parse_ipv4(unsigned int addr_len, char *addr_val,
+	   struct in6_addr *cbaddrp, unsigned short *cbportp)
 {
 	int temp = 0;
 	u32 cbaddr = 0;
@@ -508,7 +509,7 @@
 	char *addr = addr_val;
 	int i, shift;
 
-	/* ipaddress */
+	/* ip address */
 	shift = 24;
 	for(i = 4; i > 0  ; i--) {
 		if ((temp = parse_octet(&addrlen, &addr)) < 0) {
@@ -518,7 +519,10 @@
 		if (shift > 0)
 		shift -= 8;
 	}
-	*cbaddrp = cbaddr;
+	cbaddrp->s6_addr32[0] = 0;
+	cbaddrp->s6_addr32[1] = 0;
+	cbaddrp->s6_addr32[2] = htonl(0xffff);
+	cbaddrp->s6_addr32[3] = htonl(cbaddr);
 
 	/* port */
 	shift = 8;
@@ -534,7 +538,140 @@
 	return 1;
 }
 
-static void
+/* parse and set the setclientid ipv6 callback address and port */
+static int
+parse_ipv6(unsigned int addr_len, char *addr_val, int nb_colon, int nb_dot,
+	struct in6_addr *cbaddrp, unsigned short *cbportp)
+{
+	unsigned int val = 0;
+	unsigned char cbaddr[32];
+	int port = 0;
+	char *pt_addr, *pt_port, *pt_cbaddr;
+	int digit_found = 0;
+	int ch;
+	int i;
+
+	pt_cbaddr = cbaddr;
+	pt_addr = addr_val;
+	if (strsep(&addr_val, ".") == NULL)
+		return 0;
+	pt_port = addr_val;
+
+	if (*pt_addr == ':') {
+		if (*++pt_addr != ':')
+			return 0;
+		else {
+			*pt_cbaddr++ = 0;
+			*pt_cbaddr++ = 0;
+		}
+	}
+	while ((ch = *pt_addr++) != '\0') {
+		i = -1;
+		if (ch >= '0' && ch <= '9') {
+			i = ch - '0';
+		} else if (ch >= 'a' && ch <= 'f') {
+			i = ch - 'a' + 10;
+		} else if (ch >= 'A' && ch <= 'F') {
+			i = ch - 'A' + 10;
+		}
+		if (i != -1) {
+			val <<= 4;
+			val |= i;
+			if (val > 0xffff) {
+			    	return (0);
+			}
+			digit_found = 1;
+			continue;
+		}
+		if (ch == ':') {
+			if (!digit_found) {
+				for (i = 0; i < 8 - nb_colon; i++) {
+					*pt_cbaddr++ = 0;
+					*pt_cbaddr++ = 0;
+				}
+			} else if (*pt_addr == '\0') {
+				return (0);
+			} else {
+				*pt_cbaddr++ = (u_char) (val >> 8) & 0xff;
+				*pt_cbaddr++ = (u_char) val & 0xff;
+			}
+			digit_found = 0;
+			val = 0;
+			continue;
+		}
+		return 0;
+	}
+	if (val) {
+		*pt_cbaddr++ = (u_char) (val >> 8) & 0xff;
+		*pt_cbaddr++ = (u_char) val & 0xff;
+	}
+
+	val = 0;
+	while ((ch = *pt_port++) != '\0') {
+		if (ch >= '0' && ch <= '9') {
+			int p = val * 10;
+			val = p + (ch - '0');
+		}
+		if (ch == '.') {
+			port += val << 8;
+			val = 0;
+		}
+	}
+	port += val;
+	if (port > 0xffff)
+		return 0;
+
+	memcpy((char *)cbaddrp, cbaddr, 16);
+	*cbportp = port;
+
+	return 1;
+}
+
+/* parse and set the setclientid callback address andd port */
+static int
+parse_callback_addr(unsigned int addr_len, char *addr_val, struct in6_addr *cbaddrp,
+	unsigned short *cbportp)
+{
+	char *pt;
+	int i, rc = 0;
+	int nb_colon = 0, nb_dot = 0;
+
+	pt = addr_val;
+	for (i = 0; i < addr_len; i++) {
+		if (*pt == ':')
+			nb_colon++;
+		else if (*pt == '.')
+			nb_dot++;
+		pt++;
+	}
+	if (nb_dot == 5) {
+	    // The possible formats are possible for IPv4 addresses (RFC 3530 + 2373):
+	    // d1.d2.d3.d4.p1.p2
+	    // x1:x2:x3:x4:x5:x6:x7:x8.p1.p2 (and :: compressed form)
+	    // 0:0:0:0:0:0:d1.d2.d3.d4.p1.p2 or ::d1.d2.d3.d4.p1.p2
+	    // 0:0:0:0:0:FFFF:d1.d2.d3.d4.p1.p2 or ::FFFF:d1.d2.d3.d4.p1.p2
+       	    if (nb_colon == 0)
+		rc = parse_ipv4(addr_len, addr_val, cbaddrp, cbportp);
+	    else if (nb_colon == 2 &&
+		     !memcmp(addr_val, "::", 2))
+		rc = parse_ipv4(addr_len - 2, addr_val + 2, cbaddrp, cbportp);
+	    else if (nb_colon == 3 && 
+		     (!memcmp(addr_val, "::ffff:", 7) || 
+		      !memcmp(addr_val, "::FFFF:", 7)))
+	       	rc = parse_ipv4(addr_len - 7, addr_val + 7, cbaddrp, cbportp);
+	    else if (nb_colon == 6 && 
+		     (!memcmp(addr_val, "0:0:0:0:0:0:", 12) || 
+		      !memcmp(addr_val, "0:0:0:0:0:ffff:", 12) ||
+		      !memcmp(addr_val, "0:0:0:0:0:FFFF:", 12)))
+		rc = parse_ipv4(addr_len - 12, addr_val + 12, cbaddrp, cbportp);
+	} else if (nb_colon > 1 && nb_colon < 8)
+	    rc = parse_ipv6(addr_len, addr_val, nb_colon, nb_dot, cbaddrp, cbportp);
+	else
+		return 0;
+	return rc;
+}
+
+void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
 	struct nfs4_callback *cb = &clp->cl_callback;
@@ -543,9 +680,12 @@
         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)))
-		goto out_err;
+	if ( !(parse_callback_addr(se->se_callback_addr_len, se->se_callback_addr_val,
+		         &cb->cb_addr, &cb->cb_port))) {
+		printk(KERN_INFO "NFSD: BAD callback address. client will not receive delegations\n");
+		cb->cb_parsed = 0;
+		return;
+	}
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
 	cb->cb_parsed = 1;
@@ -595,7 +735,7 @@
 int
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
 {
-	u32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct in6_addr 	ip_addr;
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -617,6 +757,7 @@
 	strhashval = clientstr_hashval(clname.data, clname.len);
 
 	conf = NULL;
+	memcpy(&ip_addr, &rqstp->rq_addr.sin6_addr, sizeof(struct in6_addr));
 	nfs4_lock_state();
 	list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
 		if (!cmp_name(&clp->cl_name, &clname))
@@ -628,15 +769,18 @@
 		 */
 		status = nfserr_clid_inuse;
 		if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
-			printk("NFSD: setclientid: string in use by client"
+			printk("NFSD: setclientid (1): string in use by client"
 			"(clientid %08x/%08x)\n",
 			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
 			goto out;
 		}
-		if (clp->cl_addr != ip_addr) { 
-			printk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+		if (memcmp(&clp->cl_addr, &ip_addr, sizeof(struct in6_addr))) { 
+			printk("NFSD: setclientid (2): string in use by client"
+			"(clientid %08x/%08x)\n"
+			"cl_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n"
+			"ip_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id,
+			NIP6(clp->cl_addr), NIP6(ip_addr));
 			goto out;
 		}
 
@@ -666,7 +810,7 @@
 		if (!(new = create_client(clname)))
 			goto out;
 		copy_verf(new, &clverifier);
-		new->cl_addr = ip_addr;
+		memcpy(&new->cl_addr, &ip_addr, sizeof(struct in6_addr));
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -694,7 +838,7 @@
 		if (!(new = create_client(clname)))
 			goto out;
 		copy_verf(new,&conf->cl_verifier);
-		new->cl_addr = ip_addr;
+		memcpy(&new->cl_addr, &ip_addr, sizeof(struct in6_addr));
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		copy_clid(new, conf);
 		gen_confirm(new);
@@ -712,7 +856,7 @@
 		if (!(new = create_client(clname)))
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		memcpy(&new->cl_addr, &ip_addr, sizeof(struct in6_addr));
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -738,7 +882,7 @@
 		if (!(new = create_client(clname)))
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		memcpy(&new->cl_addr, &ip_addr, sizeof(struct in6_addr));
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -770,7 +914,7 @@
 int
 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct in6_addr ip_addr;
 	unsigned int idhashval;
 	struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
@@ -786,6 +930,7 @@
 	 */
 
 	idhashval = clientid_hashval(clid->cl_id);
+	memcpy(&ip_addr, &rqstp->rq_addr.sin6_addr, sizeof(struct in6_addr));
 	nfs4_lock_state();
 	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
 		if (!cmp_clid(&clp->cl_clientid, clid))
@@ -797,10 +942,13 @@
 		 * don't match, return ERR_INVAL just as if the record had
 		 * not been found.
 		 */
-		if (clp->cl_addr != ip_addr) { 
-			dprintk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+		if (memcmp(&clp->cl_addr, &ip_addr, sizeof(struct in6_addr))) { 
+			printk("NFSD: setclientid (3): string in use by client"
+			"(clientid %08x/%08x)\n"
+			"cl_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n"
+			"ip_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id,
+			NIP6(clp->cl_addr), NIP6(ip_addr));
 			goto out;
 		}
 		conf = clp;
@@ -810,10 +958,13 @@
 		if (!cmp_clid(&clp->cl_clientid, clid))
 			continue;
 		status = nfserr_inval;
-		if (clp->cl_addr != ip_addr) { 
-			dprintk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+		if (memcmp(&clp->cl_addr, &ip_addr, sizeof(struct in6_addr))) { 
+			printk("NFSD: setclientid (4): string in use by client"
+			"(clientid %08x/%08x)\n"
+			"cl_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n"
+			"ip_addr = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id,
+			NIP6(clp->cl_addr), NIP6(ip_addr));
 			goto out;
 		}
 		unconf = clp;
diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/nfsctl.c linux-2.6.9-cel5-gq-04/fs/nfsd/nfsctl.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/nfsctl.c	2004-10-18 23:53:26.000000000 +0200
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/nfsctl.c	2005-01-21 17:06:29.000000000 +0100
@@ -16,6 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
@@ -176,7 +177,7 @@
 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;
 	struct auth_domain *clp;
 	int err = 0;
 	struct knfsd_fh *res;
@@ -185,16 +186,16 @@
 		return -EINVAL;
 	data = (struct nfsctl_fsparm*)buf;
 	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
+	if (data->gd_addr.ss_family != AF_INET6)
 		goto out;
-	sin = (struct sockaddr_in *)&data->gd_addr;
+	sin = (struct sockaddr_in6 *)&data->gd_addr;
 	if (data->gd_maxlen > NFS3_FHSIZE)
 		data->gd_maxlen = NFS3_FHSIZE;
 
 	res = (struct knfsd_fh*)buf;
 
 	exp_readlock();
-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
+	if (!(clp = auth_unix_lookup6(&sin->sin6_addr)))
 		err = -EPERM;
 	else {
 		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -210,7 +211,7 @@
 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;
 	struct auth_domain *clp;
 	int err = 0;
 	struct knfsd_fh fh;
@@ -220,16 +221,16 @@
 		return -EINVAL;
 	data = (struct nfsctl_fdparm*)buf;
 	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
+	if (data->gd_addr.ss_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 = (struct sockaddr_in6 *)&data->gd_addr;
 	exp_readlock();
-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
+	if (!(clp = auth_unix_lookup6(&sin->sin6_addr)))
 		err = -EPERM;
 	else {
 		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/nfsfh.c linux-2.6.9-cel5-gq-04/fs/nfsd/nfsfh.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/nfsfh.c	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/nfsfh.c	2005-01-21 17:06:29.000000000 +0100
@@ -184,9 +184,9 @@
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
 			printk(KERN_WARNING
-			       "nfsd: request from insecure port (%08x:%d)!\n",
-			       ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			       ntohs(rqstp->rq_addr.sin_port));
+			       "nfsd: request from insecure port (%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d)!\n",
+			       NIP6(rqstp->rq_addr.sin6_addr),
+			       ntohs(rqstp->rq_addr.sin6_port));
 			goto out;
 		}
 
diff -Nru linux-2.6.9-cel5-gq-03/fs/nfsd/nfsproc.c linux-2.6.9-cel5-gq-04/fs/nfsd/nfsproc.c
--- linux-2.6.9-cel5-gq-03/fs/nfsd/nfsproc.c	2004-10-18 23:53:46.000000000 +0200
+++ linux-2.6.9-cel5-gq-04/fs/nfsd/nfsproc.c	2005-01-21 17:06:29.000000000 +0100
@@ -128,9 +128,9 @@
 
 	if (NFSSVC_MAXBLKSIZE < argp->count) {
 		printk(KERN_NOTICE
-			"oversized read request from %08x:%d (%d bytes)\n",
-				ntohl(rqstp->rq_addr.sin_addr.s_addr),
-				ntohs(rqstp->rq_addr.sin_port),
+			"oversized read request from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d (%d bytes)\n",
+				NIP6(rqstp->rq_addr.sin6_addr),
+				ntohs(rqstp->rq_addr.sin6_port),
 				argp->count);
 		argp->count = NFSSVC_MAXBLKSIZE;
 	}
diff -Nru linux-2.6.9-cel5-gq-03/include/linux/nfsd/cache.h linux-2.6.9-cel5-gq-04/include/linux/nfsd/cache.h
--- linux-2.6.9-cel5-gq-03/include/linux/nfsd/cache.h	2004-10-18 23:53:07.000000000 +0200
+++ linux-2.6.9-cel5-gq-04/include/linux/nfsd/cache.h	2005-01-21 17:06:29.000000000 +0100
@@ -26,7 +26,7 @@
 	unsigned char		c_state,	/* unused, inprog, done */
 				c_type,		/* status, buffer */
 				c_secure : 1;	/* req came from port < 1024 */
-	struct sockaddr_in	c_addr;
+	struct sockaddr_in6	c_addr;
 	u32			c_xid;
 	u32			c_prot;
 	u32			c_proc;
diff -Nru linux-2.6.9-cel5-gq-03/include/linux/nfsd/state.h linux-2.6.9-cel5-gq-04/include/linux/nfsd/state.h
--- linux-2.6.9-cel5-gq-03/include/linux/nfsd/state.h	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-04/include/linux/nfsd/state.h	2005-01-21 17:06:29.000000000 +0100
@@ -96,7 +96,7 @@
 struct nfs4_callback {
 	/* SETCLIENTID info */
 	u32			cb_parsed;  /* addr parsed */
-	u32                     cb_addr;
+	struct in6_addr		cb_addr;
 	unsigned short          cb_port;
 	u32                     cb_prog;
 	u32                     cb_ident;
@@ -126,7 +126,7 @@
 	struct xdr_netobj	cl_name; 	/* id generated by client */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
-	u32			cl_addr; 	/* client ipaddress */
+	struct in6_addr		cl_addr; 	/* client ipaddress */
 	struct svc_cred		cl_cred; 	/* setclientid principal */
 	clientid_t		cl_clientid;	/* generated by server */
 	nfs4_verifier		cl_confirm;	/* generated by server */
diff -Nru linux-2.6.9-cel5-gq-03/include/linux/nfsd/syscall.h linux-2.6.9-cel5-gq-04/include/linux/nfsd/syscall.h
--- linux-2.6.9-cel5-gq-03/include/linux/nfsd/syscall.h	2004-10-18 23:55:29.000000000 +0200
+++ linux-2.6.9-cel5-gq-04/include/linux/nfsd/syscall.h	2005-01-21 17:06:29.000000000 +0100
@@ -13,8 +13,8 @@
 #ifdef __KERNEL__
 # include <linux/config.h>
 # include <linux/types.h>
-# include <linux/in.h>
 #endif 
+#include <linux/in6.h>
 #include <linux/posix_types.h>
 #include <linux/nfsd/const.h>
 #include <linux/nfsd/export.h>
@@ -49,7 +49,7 @@
 struct nfsctl_client {
 	char			cl_ident[NFSCLNT_IDMAX+1];
 	int			cl_naddr;
-	struct in_addr		cl_addrlist[NFSCLNT_ADDRMAX];
+	struct in6_addr		cl_addrlist[NFSCLNT_ADDRMAX];
 	int			cl_fhkeytype;
 	int			cl_fhkeylen;
 	unsigned char		cl_fhkey[NFSCLNT_KEYMAX];
@@ -68,14 +68,14 @@
 
 /* GETFD */
 struct nfsctl_fdparm {
-	struct sockaddr		gd_addr;
+	struct sockaddr_storage	gd_addr;
 	char			gd_path[NFS_MAXPATHLEN+1];
 	int			gd_version;
 };
 
 /* GETFS - GET Filehandle with Size */
 struct nfsctl_fsparm {
-	struct sockaddr		gd_addr;
+	struct sockaddr_storage	gd_addr;
 	char			gd_path[NFS_MAXPATHLEN+1];
 	int			gd_maxlen;
 };

