The complete set of NFSv4 patches to support IPv6 combined into one patch.

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

diff -Nru linux-2.6.9-cel5/fs/lockd/clntproc.c linux-2.6.9-cel5-gq-08/fs/lockd/clntproc.c
--- linux-2.6.9-cel5/fs/lockd/clntproc.c	2005-03-04 09:32:40.775858544 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/clntproc.c	2005-03-04 09:38:39.725289936 +0100
@@ -191,7 +191,7 @@
 {
 	struct nfs_server	*nfssrv = NFS_SERVER(inode);
 	struct rpc_xprt		*xprt = nfssrv->client->cl_xprt;
-	struct sockaddr_in	addr;
+	struct sockaddr_in6	addr;
 	struct nlm_host		*host;
 	struct nlm_rqst		reqst, *call = &reqst;
 	sigset_t		oldset;
diff -Nru linux-2.6.9-cel5/fs/lockd/host.c linux-2.6.9-cel5-gq-08/fs/lockd/host.c
--- linux-2.6.9-cel5/fs/lockd/host.c	2005-03-04 09:32:40.776858392 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/host.c	2005-03-04 09:39:28.809827952 +0100
@@ -38,7 +38,7 @@
  * Find an NLM server handle in the cache. If there is none, create it.
  */
 struct nlm_host *
-nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
+nlmclnt_lookup_host(struct sockaddr_in6 *sin, int proto, int version)
 {
 	return nlm_lookup_host(0, sin, proto, version);
 }
@@ -57,17 +57,17 @@
  * Common host lookup routine for server & client
  */
 struct nlm_host *
-nlm_lookup_host(int server, struct sockaddr_in *sin,
+nlm_lookup_host(int server, struct sockaddr_in6 *sin,
 					int proto, int version)
 {
 	struct nlm_host	*host, **hp;
-	u32		addr;
+	struct in6_addr *addr = &sin->sin6_addr;
 	int		hash;
 
-	dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n",
-			(unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version);
+	dprintk("lockd: nlm_lookup_host(%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x, p=%d, v=%d)\n",
+		NIP6(*addr), proto, version);
 
-	hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
+	hash = NLM_ADDRHASH(addr->s6_addr32[3]);
 
 	/* Lock hash table */
 	down(&nlm_host_sema);
@@ -83,7 +83,7 @@
 		if (host->h_server != server)
 			continue;
 
-		if (nlm_cmp_addr(&host->h_addr, sin)) {
+		if (!nlm_cmp_addr(&host->h_addr, sin)) {
 			if (hp != nlm_hosts + hash) {
 				*hp = host->h_next;
 				host->h_next = nlm_hosts[hash];
@@ -102,15 +102,10 @@
 		goto nohost;
 	memset(host, 0, sizeof(*host));
 
-	addr = sin->sin_addr.s_addr;
-	sprintf(host->h_name, "%d.%d.%d.%d",
-			(unsigned char) (ntohl(addr) >> 24),
-			(unsigned char) (ntohl(addr) >> 16),
-			(unsigned char) (ntohl(addr) >>  8),
-			(unsigned char) (ntohl(addr) >>  0));
+	sprintf(host->h_name, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*addr));
 
 	host->h_addr       = *sin;
-	host->h_addr.sin_port = 0;	/* ouch! */
+	host->h_addr.sin6_port = 0;	/* ouch! */
 	host->h_version    = version;
 	host->h_proto      = proto;
 	host->h_authflavor = RPC_AUTH_UNIX;
@@ -168,8 +163,8 @@
 {
 	struct rpc_clnt	*clnt;
 
-	dprintk("lockd: nlm_bind_host(%08x)\n",
-			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
+	dprintk("lockd: nlm_bind_host(%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x)\n",
+			NIP6(host->h_addr.sin6_addr));
 
 	/* Lock host handle */
 	down(&host->h_sema);
diff -Nru linux-2.6.9-cel5/fs/lockd/mon.c linux-2.6.9-cel5-gq-08/fs/lockd/mon.c
--- linux-2.6.9-cel5/fs/lockd/mon.c	2005-03-04 09:32:40.777858240 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/mon.c	2005-03-04 09:49:42.810485664 +0100
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/utsname.h>
 #include <linux/kernel.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/lockd/lockd.h>
@@ -42,7 +43,7 @@
 		goto out;
 	}
 
-	args.addr = host->h_addr.sin_addr.s_addr;
+	memcpy(&args.addr, &host->h_addr.sin6_addr, sizeof(struct in6_addr));
 	args.proto= (host->h_proto<<1) | host->h_server;
 	args.prog = NLM_PROGRAM;
 	args.vers = host->h_version;
@@ -104,11 +105,7 @@
 static struct rpc_clnt *
 nsm_create(void)
 {
-	struct sockaddr_in	sin = {
-		.sin_family	= AF_INET,
-		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
-		.sin_port	= 0,
-	};
+	struct sockaddr_in6	sin;
 	struct rpc_create_args args = {
 		.protocol	= IPPROTO_UDP,
 		.address	= (struct sockaddr *)&sin,
@@ -121,6 +118,7 @@
 					RPC_CLNT_ONESHOT | RPC_CLNT_RESVPORT,
 	};
 
+	init_sockaddr_loopback6(0, &sin);
 	return rpc_create(&args);
 }
 
@@ -131,17 +129,17 @@
 static u32 *
 xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
 {
-	char	buffer[20];
-	u32	addr = ntohl(argp->addr);
+	char		buffer[40];
+	struct in6_addr	addr = argp->addr;
 
 	/*
-	 * Use the dotted-quad IP address of the remote host as
+	 * Use the IPv6 address of the remote host as
 	 * identifier. Linux statd always looks up the canonical
 	 * hostname first for whatever remote hostname it receives,
 	 * so this works alright.
 	 */
-	sprintf(buffer, "%d.%d.%d.%d", (addr>>24) & 0xff, (addr>>16) & 0xff,
-				 	(addr>>8) & 0xff,  (addr) & 0xff);
+	sprintf(buffer, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+		NIP6(addr));
 	if (!(p = xdr_encode_string(p, buffer))
 	 || !(p = xdr_encode_string(p, system_utsname.nodename)))
 		return ERR_PTR(-EIO);
@@ -158,7 +156,10 @@
 	p = xdr_encode_common(rqstp, p, argp);
 	if (IS_ERR(p))
 		return PTR_ERR(p);
-	*p++ = argp->addr;
+	*p++ = argp->addr.s6_addr32[0];
+	*p++ = argp->addr.s6_addr32[1];
+	*p++ = argp->addr.s6_addr32[2];
+	*p++ = argp->addr.s6_addr32[3];
 	*p++ = argp->vers;
 	*p++ = argp->proto;
 	*p++ = 0;
diff -Nru linux-2.6.9-cel5/fs/lockd/svc4proc.c linux-2.6.9-cel5-gq-08/fs/lockd/svc4proc.c
--- linux-2.6.9-cel5/fs/lockd/svc4proc.c	2005-03-04 09:32:40.778858088 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/svc4proc.c	2005-03-04 09:49:36.135500416 +0100
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/slab.h>
-#include <linux/in.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfsd/nfsd.h>
@@ -416,26 +416,26 @@
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in6	saddr = rqstp->rq_addr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
 
 	struct nlm_host		*host;
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	if (! IS_ADDR6_LOOPBACK(&saddr.sin6_addr) 
+	 || ntohs(saddr.sin6_port) >= 1024) {
 		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+			"lockd: rejected NSM callback from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d\n",
+			NIP6(rqstp->rq_addr.sin6_addr),
+			ntohs(rqstp->rq_addr.sin6_port));
 		return rpc_system_err;
 	}
 
 	/* Obtain the host pointer for this NFS server and try to
 	 * reclaim all locks we hold on this server.
 	 */
-	saddr.sin_addr.s_addr = argp->addr;
+	memcpy(&saddr.sin6_addr, &argp->addr, sizeof(struct in6_addr));
 
 	if ((argp->proto & 1)==0) {
 		if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
diff -Nru linux-2.6.9-cel5/fs/lockd/svc.c linux-2.6.9-cel5-gq-08/fs/lockd/svc.c
--- linux-2.6.9-cel5/fs/lockd/svc.c	2005-03-04 09:32:40.778858088 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/svc.c	2005-03-04 09:38:39.727289632 +0100
@@ -166,8 +166,8 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08x\n",
-			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("lockd: request from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			NIP6(rqstp->rq_addr.sin6_addr));
 
 		svc_process(serv, rqstp);
 
diff -Nru linux-2.6.9-cel5/fs/lockd/svclock.c linux-2.6.9-cel5-gq-08/fs/lockd/svclock.c
--- linux-2.6.9-cel5/fs/lockd/svclock.c	2005-03-04 09:32:40.779857936 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/svclock.c	2005-03-04 09:38:39.728289480 +0100
@@ -142,7 +142,7 @@
  * Find a block with a given NLM cookie.
  */
 static inline struct nlm_block *
-nlmsvc_find_block(struct nlm_cookie *cookie,  struct sockaddr_in *sin)
+nlmsvc_find_block(struct nlm_cookie *cookie,  struct sockaddr_in6 *sin)
 {
 	struct nlm_block *block;
 
@@ -581,19 +581,20 @@
 	struct nlm_rqst		*call = (struct nlm_rqst *) task->tk_calldata;
 	struct nlm_block	*block;
 	unsigned long		timeout;
-	struct sockaddr_in	addr, *peer_addr = &addr;
+	struct sockaddr_in6	addr, *peer_addr = &addr;
+	char	str[64];
 
 	rpc_peeraddr(task->tk_client, &addr, sizeof(addr));
+
 	dprintk("lockd: GRANT_MSG RPC callback\n");
-	dprintk("callback: looking for cookie %x, host (%08x)\n", 
-		*(unsigned int *)(call->a_args.cookie.data),
-		ntohl(peer_addr->sin_addr.s_addr));
+	sprintf(str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(addr.sin6_addr));
+	dprintk("callback: looking for cookie %x, host (%s)\n", 
+		*(unsigned int *)(call->a_args.cookie.data), str);
 	lock_kernel();
 	if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
 		unlock_kernel();
-		dprintk("lockd: no block for cookie %x, host (%08x)\n",
-			*(u32 *)(call->a_args.cookie.data),
-			ntohl(peer_addr->sin_addr.s_addr));
+		dprintk("lockd: no block for cookie %x, host (%s)\n",
+			*(u32 *)(call->a_args.cookie.data), str);
 		return;
 	}
 
@@ -628,9 +629,8 @@
 	struct nlm_block	*block;
 	struct nlm_file		*file;
 
-	dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 
-		*(unsigned int *)(cookie->data), 
-		ntohl(rqstp->rq_addr.sin_addr.s_addr), status);
+	dprintk("grant_reply: looking for cookie %x, host (%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x), s=%d \n", 
+		*(unsigned int *)(cookie->data), NIP6(rqstp->rq_addr.sin6_addr), status);
 	if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
 		return;
 	file = block->b_file;
diff -Nru linux-2.6.9-cel5/fs/lockd/svcproc.c linux-2.6.9-cel5-gq-08/fs/lockd/svcproc.c
--- linux-2.6.9-cel5/fs/lockd/svcproc.c	2005-03-04 09:32:40.780857784 +0100
+++ linux-2.6.9-cel5-gq-08/fs/lockd/svcproc.c	2005-03-04 09:49:39.451996232 +0100
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/slab.h>
-#include <linux/in.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfsd/nfsd.h>
@@ -444,25 +444,25 @@
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in6	saddr = rqstp->rq_addr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
 	struct nlm_host		*host;
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	if (! IS_ADDR6_LOOPBACK(&saddr.sin6_addr) 
+	 || ntohs(saddr.sin6_port) >= 1024) {
 		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+			"lockd: rejected NSM callback from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d\n",
+			NIP6(rqstp->rq_addr.sin6_addr),
+			ntohs(rqstp->rq_addr.sin6_port));
 		return rpc_system_err;
 	}
 
 	/* Obtain the host pointer for this NFS server and try to
 	 * reclaim all locks we hold on this server.
 	 */
-	saddr.sin_addr.s_addr = argp->addr;
+	memcpy(&saddr.sin6_addr, &argp->addr, sizeof(struct in6_addr));
 	if ((argp->proto & 1)==0) {
 		if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
 			nlmclnt_recovery(host, argp->state);
diff -Nru linux-2.6.9-cel5/fs/lockd/xdr4.c linux-2.6.9-cel5-gq-08/fs/lockd/xdr4.c
--- linux-2.6.9-cel5/fs/lockd/xdr4.c	2004-10-18 23:53:06.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/lockd/xdr4.c	2005-03-04 09:38:39.897263792 +0100
@@ -354,7 +354,10 @@
 		return 0;
 	argp->state = ntohl(*p++);
 	/* Preserve the address in network byte order */
-	argp->addr = *p++;
+	argp->addr.s6_addr32[0] = *p++;
+	argp->addr.s6_addr32[1] = *p++;
+	argp->addr.s6_addr32[2] = *p++;
+	argp->addr.s6_addr32[3] = *p++;
 	return xdr_argsize_check(rqstp, p);
 }
 
diff -Nru linux-2.6.9-cel5/fs/lockd/xdr.c linux-2.6.9-cel5-gq-08/fs/lockd/xdr.c
--- linux-2.6.9-cel5/fs/lockd/xdr.c	2004-10-18 23:53:11.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/lockd/xdr.c	2005-03-04 09:38:39.898263640 +0100
@@ -349,7 +349,10 @@
 		return 0;
 	argp->state = ntohl(*p++);
 	/* Preserve the address in network byte order */
-	argp->addr = *p++;
+	argp->addr.s6_addr32[0] = *p++;
+	argp->addr.s6_addr32[1] = *p++;
+	argp->addr.s6_addr32[2] = *p++;
+	argp->addr.s6_addr32[3] = *p++;
 	argp->vers = *p++;
 	argp->proto = *p++;
 	return xdr_argsize_check(rqstp, p);
diff -Nru linux-2.6.9-cel5/fs/nfs/callback.c linux-2.6.9-cel5-gq-08/fs/nfs/callback.c
--- linux-2.6.9-cel5/fs/nfs/callback.c	2005-03-04 09:32:37.022429152 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/callback.c	2005-03-04 09:35:16.889125720 +0100
@@ -63,8 +63,8 @@
 					__FUNCTION__, -err);
 			break;
 		}
-		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("%s: request from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+				__FUNCTION__, NIP6(rqstp->rq_addr.sin6_addr));
 		svc_process(serv, rqstp);
 	}
 
@@ -141,14 +141,14 @@
 
 static int nfs_callback_set_client(struct svc_rqst *rqstp)
 {
-	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+	struct in6_addr *addr = &rqstp->rq_addr.sin6_addr;
 	struct nfs4_client *clp;
 
 	/* Don't talk to strangers */
 	clp = nfs4_find_client(addr);
 	if (clp == NULL)
 		return SVC_DROP;
-	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
+	dprintk("%s: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x NFSv4 callback!\n", __FUNCTION__, NIP6(*addr));
 	nfs4_put_client(clp);
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
diff -Nru linux-2.6.9-cel5/fs/nfs/callback.h linux-2.6.9-cel5-gq-08/fs/nfs/callback.h
--- linux-2.6.9-cel5/fs/nfs/callback.h	2004-10-18 23:54:55.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/nfs/callback.h	2005-03-04 09:35:16.946117056 +0100
@@ -38,7 +38,7 @@
 };
 
 struct cb_getattrargs {
-	struct sockaddr_in *addr;
+	struct sockaddr_in6 *addr;
 	struct nfs_fh fh;
 	uint32_t bitmap[2];
 };
@@ -53,7 +53,7 @@
 };
 
 struct cb_recallargs {
-	struct sockaddr_in *addr;
+	struct sockaddr_in6 *addr;
 	struct nfs_fh fh;
 	nfs4_stateid stateid;
 	uint32_t truncate;
diff -Nru linux-2.6.9-cel5/fs/nfs/callback_proc.c linux-2.6.9-cel5-gq-08/fs/nfs/callback_proc.c
--- linux-2.6.9-cel5/fs/nfs/callback_proc.c	2004-10-18 23:55:36.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/nfs/callback_proc.c	2005-03-04 09:35:16.947116904 +0100
@@ -22,7 +22,7 @@
 	
 	res->bitmap[0] = res->bitmap[1] = 0;
 	res->status = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client(&args->addr->sin6_addr);
 	if (clp == NULL)
 		goto out;
 	inode = nfs_delegation_find_inode(clp, &args->fh);
@@ -59,7 +59,7 @@
 	unsigned res;
 	
 	res = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client(&args->addr->sin6_addr);
 	if (clp == NULL)
 		goto out;
 	inode = nfs_delegation_find_inode(clp, &args->fh);
diff -Nru linux-2.6.9-cel5/fs/nfs/delegation.c linux-2.6.9-cel5-gq-08/fs/nfs/delegation.c
--- linux-2.6.9-cel5/fs/nfs/delegation.c	2004-10-18 23:54:40.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/nfs/delegation.c	2005-03-04 09:35:16.958115232 +0100
@@ -104,8 +104,8 @@
 		if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
 					sizeof(delegation->stateid)) != 0 ||
 				delegation->type != nfsi->delegation->type) {
-			printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
-					__FUNCTION__, NIPQUAD(clp->cl_addr));
+			printk("%s: server %x:%x:%x:%x:%x:%x:%x:%x, handed out a duplicate delegation!\n",
+					__FUNCTION__, NIP6(clp->cl_addr));
 			status = -EIO;
 		}
 	}
diff -Nru linux-2.6.9-cel5/fs/nfs/dir.c linux-2.6.9-cel5-gq-08/fs/nfs/dir.c
--- linux-2.6.9-cel5/fs/nfs/dir.c	2005-03-04 09:32:58.540157960 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/dir.c	2005-03-04 09:39:28.868818984 +0100
@@ -1382,7 +1382,7 @@
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL, *rehash = NULL;
-	int error = -EBUSY;
+	int error;
 
 	/*
 	 * To prevent any new references to the target during the rename,
@@ -1409,6 +1409,12 @@
 	 */
 	if (!new_inode)
 		goto go_ahead;
+	/* If target is a hard link to the source, then noop */
+	error = 0;
+	if (NFS_FILEID(new_inode) == NFS_FILEID(old_inode))
+		goto out;
+
+	error = -EBUSY;
 	if (S_ISDIR(new_inode->i_mode))
 		goto out;
 	else if (atomic_read(&new_dentry->d_count) > 2) {
diff -Nru linux-2.6.9-cel5/fs/nfs/inode.c linux-2.6.9-cel5-gq-08/fs/nfs/inode.c
--- linux-2.6.9-cel5/fs/nfs/inode.c	2005-03-04 09:32:56.327494336 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/inode.c	2005-03-04 09:49:25.649094592 +0100
@@ -26,6 +26,7 @@
 #include <linux/unistd.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/stats.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_iostat.h>
 #include <linux/nfs_mount.h>
@@ -1391,9 +1392,9 @@
 	struct nfs_server *server = data;
 	struct nfs_server *old = NFS_SB(sb);
 
-	if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
+	if (memcmp(&old->addr.sin6_addr, &server->addr.sin6_addr, sizeof(struct in6_addr)))
 		return 0;
-	if (old->addr.sin_port != server->addr.sin_port)
+	if (old->addr.sin6_port != server->addr.sin6_port)
 		return 0;
 	return !nfs_compare_fh(&old->fh, &server->fh);
 }
@@ -1448,9 +1449,23 @@
 	memcpy(root->data, data->root.data, root->size);
 
 	/* We now require that the mount process passes the remote address */
-	memcpy(&server->addr, &data->addr, sizeof(server->addr));
-	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
-		printk("NFS: mount program didn't pass remote address!\n");
+	if (data->addr.sin_family == AF_INET) {
+		if (data->addr.sin_addr.s_addr == INADDR_ANY) {
+			printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
+			kfree(server);
+			return ERR_PTR(-EINVAL);
+		}
+		map_sockaddr_4to6(&data->addr, &server->addr);
+	} else if (data->addr.sin_family == AF_INET6) {
+		if (data->addr6.sin6_family != AF_INET6 ||
+	    	    IS_ADDR6_ANY(data->addr6.sin6_addr.s6_addr32)) {
+			printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
+			kfree(server);
+			return ERR_PTR(-EINVAL);
+		}
+		memcpy(&server->addr, &data->addr6, sizeof(struct sockaddr_in6));
+	} else {
+		printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
 		kfree(server);
 		return ERR_PTR(-EINVAL);
 	}
@@ -1665,7 +1680,7 @@
 		return -EINVAL;
 	}
 
-	clp = nfs4_get_client(&server->addr.sin_addr);
+	clp = nfs4_get_client(&server->addr.sin6_addr);
 	if (!clp) {
 		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
 		return -EIO;
@@ -1835,22 +1850,38 @@
 		goto out_err;
 
 	/* We now require that the mount process passes the remote address */
-	if (data->host_addrlen != sizeof(server->addr)) {
+	if (data->host_addrlen == sizeof(struct sockaddr_in)) {
+		struct sockaddr_in saddr;
+		if (copy_from_user(&saddr, data->host_addr,
+			    sizeof(struct sockaddr_in))) {
+			printk(KERN_ERR "NFS: memory fault while copying mount data!\n");
+			s = ERR_PTR(-EFAULT);
+		        goto out_free;
+		}
+		if (saddr.sin_family != AF_INET || 
+		    saddr.sin_addr.s_addr == INADDR_ANY) {
+			printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
+			s = ERR_PTR(-EINVAL);
+			goto out_free;
+		}
+		map_sockaddr_4to6(&saddr, &server->addr);
+	} else if (data->host_addrlen == sizeof(struct sockaddr_in6)) {
+		if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
+			printk(KERN_ERR "NFS: memory fault while copying mount data!\n");
+			s = ERR_PTR(-EFAULT);
+			goto out_free;
+		}
+		if (server->addr.sin6_family != AF_INET6 ||
+	    	    IS_ADDR6_ANY(server->addr.sin6_addr.s6_addr32)) {
+			printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
+			s = ERR_PTR(-EINVAL);
+			goto out_free;
+		}
+	} else {
 		printk(KERN_ERR "NFS: mount program didn't pass remote IP address!\n");
 		s = ERR_PTR(-EINVAL);
 		goto out_free;
 	}
-	if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
-		printk(KERN_ERR "NFS: memory fault while copying mount data!\n");
-		s = ERR_PTR(-EFAULT);
-		goto out_free;
-	}
-	if (server->addr.sin_family != AF_INET ||
-	    server->addr.sin_addr.s_addr == INADDR_ANY) {
-		printk(KERN_ERR "NFS: mount program passed bogus remote IP address!\n");
-		s = ERR_PTR(-EINVAL);
-		goto out_free;
-	}
 
 	s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
 
diff -Nru linux-2.6.9-cel5/fs/nfs/nfs4proc.c linux-2.6.9-cel5-gq-08/fs/nfs/nfs4proc.c
--- linux-2.6.9-cel5/fs/nfs/nfs4proc.c	2005-03-04 09:32:40.851846992 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/nfs4proc.c	2005-03-04 09:35:16.960114928 +0100
@@ -2348,8 +2348,9 @@
 		*p = htonl((u32)boot_time.tv_nsec);
 	}
 	setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-			sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
-			clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
+			sizeof(setclientid.sc_name),
+			"%s/%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+			clp->cl_ipaddr, NIP6(clp->cl_addr));
 	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
 			sizeof(setclientid.sc_netid), "tcp");
 	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
diff -Nru linux-2.6.9-cel5/fs/nfs/nfs4state.c linux-2.6.9-cel5-gq-08/fs/nfs/nfs4state.c
--- linux-2.6.9-cel5/fs/nfs/nfs4state.c	2005-03-04 09:32:33.034035480 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/nfs4state.c	2005-03-04 09:35:16.961114776 +0100
@@ -93,7 +93,7 @@
  * bother putting them in a slab cache...
  */
 static struct nfs4_client *
-nfs4_alloc_client(struct in_addr *addr)
+nfs4_alloc_client(struct in6_addr *addr)
 {
 	struct nfs4_client *clp;
 
@@ -142,7 +142,7 @@
 	nfs_callback_down();
 }
 
-static struct nfs4_client *__nfs4_find_client(struct in_addr *addr)
+static struct nfs4_client *__nfs4_find_client(struct in6_addr *addr)
 {
 	struct nfs4_client *clp;
 	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
@@ -154,7 +154,7 @@
 	return NULL;
 }
 
-struct nfs4_client *nfs4_find_client(struct in_addr *addr)
+struct nfs4_client *nfs4_find_client(struct in6_addr *addr)
 {
 	struct nfs4_client *clp;
 	spin_lock(&state_spinlock);
@@ -164,7 +164,7 @@
 }
 
 struct nfs4_client *
-nfs4_get_client(struct in_addr *addr)
+nfs4_get_client(struct in6_addr *addr)
 {
 	struct nfs4_client *clp, *new = NULL;
 
@@ -840,9 +840,12 @@
 	struct reclaimer_args *args = (struct reclaimer_args *)ptr;
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
+	char str[64];
 	int status = 0;
 
-	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
+	sprintf(str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+		  NIP6(clp->cl_addr));
+	daemonize("%s-reclaim", str);
 	allow_signal(SIGKILL);
 
 	atomic_inc(&clp->cl_count);
@@ -884,8 +887,7 @@
 	nfs4_put_client(clp);
 	return 0;
 out_error:
-	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
-				NIPQUAD(clp->cl_addr.s_addr), -status);
+	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s\n", str);
 	goto out;
 }
 
diff -Nru linux-2.6.9-cel5/fs/nfs/nfs4xdr.c linux-2.6.9-cel5-gq-08/fs/nfs/nfs4xdr.c
--- linux-2.6.9-cel5/fs/nfs/nfs4xdr.c	2005-03-04 09:32:40.854846536 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfs/nfs4xdr.c	2005-03-04 09:35:16.963114472 +0100
@@ -99,9 +99,9 @@
 #define decode_renew_maxsz	(op_decode_hdr_maxsz)
 #define encode_setclientid_maxsz \
 				(op_encode_hdr_maxsz + \
-				4 /*server->ip_addr*/ + \
+				16 /*server->ip_addr*/ + \
 				1 /*Netid*/ + \
-				6 /*uaddr*/ + \
+				12 /*uaddr*/ + \
 				6 + (NFS4_VERIFIER_SIZE >> 2))
 #define decode_setclientid_maxsz \
 				(op_decode_hdr_maxsz + \
diff -Nru linux-2.6.9-cel5/fs/nfsd/export.c linux-2.6.9-cel5-gq-08/fs/nfsd/export.c
--- linux-2.6.9-cel5/fs/nfsd/export.c	2005-03-04 09:32:37.077420792 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/export.c	2005-03-04 09:35:30.666031312 +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/fs/nfsd/nfs4callback.c linux-2.6.9-cel5-gq-08/fs/nfsd/nfs4callback.c
--- linux-2.6.9-cel5/fs/nfsd/nfs4callback.c	2005-03-04 09:32:40.887841520 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/nfs4callback.c	2005-03-04 09:49:32.727018584 +0100
@@ -41,6 +41,7 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/state.h>
 #include <linux/sunrpc/sched.h>
@@ -518,7 +519,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),
@@ -543,6 +544,7 @@
                 .rpc_proc       = &nfs4_cb_null_proc,
                 .rpc_argp       = clp,
         };
+	char hostname[40];
 	int status;
 
 	dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n",
@@ -551,10 +553,12 @@
 		return;
 
 	/* 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);
+	map_ipaddr6_to_sockaddr6(&cb->cb_addr, cb->cb_port, &addr);
+
+	// GQ temporary fix for the init of servname, changed in next releases
+	snprintf(hostname, sizeof(hostname),
+		"%x:%x:%x:%x:%x:%x:%x:%x", NIP6(addr.sin6_addr));
+	args.servername = hostname;
 
 	/* Initialize rpc_program */
 	program->name = "nfs4_cb";
@@ -609,7 +613,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 +622,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/fs/nfsd/nfs4state.c linux-2.6.9-cel5-gq-08/fs/nfsd/nfs4state.c
--- linux-2.6.9-cel5/fs/nfsd/nfs4state.c	2005-03-04 09:32:37.134412128 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/nfs4state.c	2005-03-04 09:49:29.368529152 +0100
@@ -44,6 +44,7 @@
 #include <linux/mount.h>
 #include <linux/workqueue.h>
 #include <linux/smp_lock.h>
+#include <linux/nfs_ipv6.h>
 #include <linux/nfs4.h>
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
@@ -499,7 +500,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 +510,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 +520,7 @@
 		if (shift > 0)
 		shift -= 8;
 	}
-	*cbaddrp = cbaddr;
+	map_ipaddr_4to6((struct in_addr *)&cbaddr, cbaddrp);
 
 	/* port */
 	shift = 8;
@@ -534,7 +536,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 +678,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 +733,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 +755,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 +767,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 +808,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 +836,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 +854,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 +880,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 +912,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 +928,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 +940,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 +956,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/fs/nfsd/nfsctl.c linux-2.6.9-cel5-gq-08/fs/nfsd/nfsctl.c
--- linux-2.6.9-cel5/fs/nfsd/nfsctl.c	2004-10-18 23:53:26.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/nfsctl.c	2005-03-04 09:35:30.733021128 +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/fs/nfsd/nfsfh.c linux-2.6.9-cel5-gq-08/fs/nfsd/nfsfh.c
--- linux-2.6.9-cel5/fs/nfsd/nfsfh.c	2005-03-04 09:32:37.139411368 +0100
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/nfsfh.c	2005-03-04 09:35:30.733021128 +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/fs/nfsd/nfsproc.c linux-2.6.9-cel5-gq-08/fs/nfsd/nfsproc.c
--- linux-2.6.9-cel5/fs/nfsd/nfsproc.c	2004-10-18 23:53:46.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/fs/nfsd/nfsproc.c	2005-03-04 09:35:30.799011096 +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/include/linux/lockd/lockd.h linux-2.6.9-cel5-gq-08/include/linux/lockd/lockd.h
--- linux-2.6.9-cel5/include/linux/lockd/lockd.h	2005-03-04 09:32:40.917836960 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/lockd/lockd.h	2005-03-04 09:39:28.869818832 +0100
@@ -38,9 +38,9 @@
  */
 struct nlm_host {
 	struct nlm_host *	h_next;		/* linked list (hash table) */
-	struct sockaddr_in	h_addr;		/* peer address */
+	struct sockaddr_in6	h_addr;		/* peer address */
 	struct rpc_clnt	*	h_rpcclnt;	/* RPC client to talk to peer */
-	char			h_name[20];	/* remote hostname */
+	char			h_name[40];	/* remote hostname */
 	u32			h_version;	/* interface version */
 	rpc_authflavor_t	h_authflavor;	/* RPC authentication type */
 	unsigned short		h_proto;	/* transport proto */
@@ -156,9 +156,9 @@
 /*
  * Host cache
  */
-struct nlm_host * nlmclnt_lookup_host(struct sockaddr_in *, int, int);
+struct nlm_host * nlmclnt_lookup_host(struct sockaddr_in6 *, int, int);
 struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *);
-struct nlm_host * nlm_lookup_host(int server, struct sockaddr_in *, int, int);
+struct nlm_host * nlm_lookup_host(int server, struct sockaddr_in6 *, int, int);
 struct rpc_clnt * nlm_bind_host(struct nlm_host *);
 void		  nlm_rebind_host(struct nlm_host *);
 struct nlm_host * nlm_get_host(struct nlm_host *);
@@ -202,9 +202,9 @@
  * Compare two host addresses (needs modifying for ipv6)
  */
 static __inline__ int
-nlm_cmp_addr(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
+nlm_cmp_addr(struct sockaddr_in6 *sin1, struct sockaddr_in6 *sin2)
 {
-	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
+	return memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof(struct in6_addr));
 }
 
 /*
diff -Nru linux-2.6.9-cel5/include/linux/lockd/sm_inter.h linux-2.6.9-cel5-gq-08/include/linux/lockd/sm_inter.h
--- linux-2.6.9-cel5/include/linux/lockd/sm_inter.h	2004-10-18 23:54:29.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/include/linux/lockd/sm_inter.h	2005-03-04 09:39:28.923810624 +0100
@@ -24,7 +24,7 @@
  * Arguments for all calls to statd
  */
 struct nsm_args {
-	u32		addr;		/* remote address */
+	struct in6_addr	addr;		/* remote address */
 	u32		prog;		/* RPC callback info */
 	u32		vers;
 	u32		proc;
diff -Nru linux-2.6.9-cel5/include/linux/lockd/xdr.h linux-2.6.9-cel5-gq-08/include/linux/lockd/xdr.h
--- linux-2.6.9-cel5/include/linux/lockd/xdr.h	2004-10-18 23:53:06.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/include/linux/lockd/xdr.h	2005-03-04 09:38:39.956254824 +0100
@@ -75,7 +75,7 @@
 	char *		mon;
 	int		len;
 	u32		state;
-	u32		addr;
+	struct in6_addr	addr;
 	u32		vers;
 	u32		proto;
 };
diff -Nru linux-2.6.9-cel5/include/linux/nfsd/cache.h linux-2.6.9-cel5-gq-08/include/linux/nfsd/cache.h
--- linux-2.6.9-cel5/include/linux/nfsd/cache.h	2004-10-18 23:53:07.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/include/linux/nfsd/cache.h	2005-03-04 09:35:30.850003344 +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/include/linux/nfsd/state.h linux-2.6.9-cel5-gq-08/include/linux/nfsd/state.h
--- linux-2.6.9-cel5/include/linux/nfsd/state.h	2005-03-04 09:32:37.163407720 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/nfsd/state.h	2005-03-04 09:35:30.850003344 +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/include/linux/nfsd/syscall.h linux-2.6.9-cel5-gq-08/include/linux/nfsd/syscall.h
--- linux-2.6.9-cel5/include/linux/nfsd/syscall.h	2004-10-18 23:55:29.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/include/linux/nfsd/syscall.h	2005-03-04 09:35:30.851003192 +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;
 };
diff -Nru linux-2.6.9-cel5/include/linux/nfs_fs.h linux-2.6.9-cel5-gq-08/include/linux/nfs_fs.h
--- linux-2.6.9-cel5/include/linux/nfs_fs.h	2005-03-04 09:32:40.918836808 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/nfs_fs.h	2005-03-04 09:35:16.964114320 +0100
@@ -11,6 +11,7 @@
 
 #include <linux/config.h>
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/rwsem.h>
@@ -30,6 +31,7 @@
 #include <linux/nfs_xdr.h>
 #include <linux/rwsem.h>
 #include <linux/workqueue.h>
+#include <linux/spinlock.h>
 #include <linux/mempool.h>
 
 /*
@@ -584,7 +586,7 @@
  */
 struct nfs4_client {
 	struct list_head	cl_servers;	/* Global list of servers */
-	struct in_addr		cl_addr;	/* Server identifier */
+	struct in6_addr		cl_addr;	/* Server identifier */
 	u64			cl_clientid;	/* constant */
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
@@ -623,7 +625,7 @@
 	/* Our own IP address, as a null-terminated string.
 	 * This is used to generate the clientid, and the callback address.
 	 */
-	char			cl_ipaddr[16];
+	char			cl_ipaddr[40];
 };
 
 /*
@@ -737,10 +739,10 @@
 /* nfs4state.c */
 extern void init_nfsv4_state(struct nfs_server *);
 extern void destroy_nfsv4_state(struct nfs_server *);
-extern struct nfs4_client *nfs4_get_client(struct in_addr *);
+extern struct nfs4_client *nfs4_get_client(struct in6_addr *);
 extern void nfs4_put_client(struct nfs4_client *clp);
 extern int nfs4_init_client(struct nfs4_client *clp);
-extern struct nfs4_client *nfs4_find_client(struct in_addr *);
+extern struct nfs4_client *nfs4_find_client(struct in6_addr *);
 extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
diff -Nru linux-2.6.9-cel5/include/linux/nfs_fs_sb.h linux-2.6.9-cel5-gq-08/include/linux/nfs_fs_sb.h
--- linux-2.6.9-cel5/include/linux/nfs_fs_sb.h	2005-03-04 09:32:40.927835440 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/nfs_fs_sb.h	2005-03-04 09:35:16.964114320 +0100
@@ -30,13 +30,13 @@
 	unsigned int		namelen;
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
-	struct sockaddr_in	addr;
+	struct sockaddr_in6	addr;
 	struct nfs_iostats *	io_stats;	/* I/O statistics */
 #ifdef CONFIG_NFS_V4
 	/* Our own IP address, as a null-terminated string.
 	 * This is used to generate the clientid, and the callback address.
 	 */
-	char			ip_addr[16];
+	char			ip_addr[40];
 	char *			mnt_path;
 	struct nfs4_client *	nfs4_state;	/* all NFSv4 state starts here */
 	struct list_head	nfs4_siblings;	/* List of other nfs_server structs
diff -Nru linux-2.6.9-cel5/include/linux/nfs_ipv6.h linux-2.6.9-cel5-gq-08/include/linux/nfs_ipv6.h
--- linux-2.6.9-cel5/include/linux/nfs_ipv6.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/nfs_ipv6.h	2005-03-04 09:44:20.518481496 +0100
@@ -0,0 +1,77 @@
+/*
+ *  include/linux/nfs_ipv6.h
+ *
+ *  Macros used to manipulate IPv6 addreses
+ */
+
+#ifndef _LINUX_NFS_IPV6_H
+#define _LINUX_NFS_IPV6_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+static inline void
+map_ipaddr_4to6(struct in_addr *addr, struct in6_addr *addr6)
+{
+	addr6->s6_addr32[0] = 0;
+	addr6->s6_addr32[1] = 0;
+	addr6->s6_addr32[2] = htonl(0xffff);
+	addr6->s6_addr32[3] = *(uint32_t *)addr;
+}
+
+static inline void
+map_sockaddr_4to6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = sin->sin_port;
+	sin6->sin6_flowinfo = 0;
+	map_ipaddr_4to6(&sin->sin_addr, &sin6->sin6_addr);
+	sin6->sin6_scope_id = 0;
+}
+
+static inline void
+map_ipaddr6_to_sockaddr6(struct in6_addr *addr6, __u16 port,
+			 struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = htons(port);
+	sin6->sin6_flowinfo = 0;
+	memcpy(&sin6->sin6_addr, addr6, sizeof(struct in6_addr));
+	sin6->sin6_scope_id = 0;
+}
+
+static inline void
+init_ipaddr_loopback6(struct in6_addr *addr6)
+{
+	addr6->s6_addr32[0] = 0;
+	addr6->s6_addr32[1] = 0;
+	addr6->s6_addr32[2] = 0;
+	addr6->s6_addr32[3] = htonl(1);
+}
+
+static inline void
+init_sockaddr_loopback6(__u16 port, struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = htons(port);
+	sin6->sin6_flowinfo = 0;
+	init_ipaddr_loopback6(&sin6->sin6_addr);
+	sin6->sin6_scope_id = 0;
+}
+
+#define IS_ADDR6_LOOPBACK(a) \
+	(((__const uint32_t *) (a))[0] == 0		\
+	 && ((__const uint32_t *) (a))[1] == 0		\
+	 && ((__const uint32_t *) (a))[2] == 0		\
+	 && ((__const uint32_t *) (a))[3] == htonl(1))
+
+#define IS_ADDR6_ANY(a) \
+	(((uint32_t *) (a))[0] == 0			\
+	 && ((uint32_t *) (a))[1] == 0			\
+	 && (((uint32_t *) (a))[2] == 0			\
+	     || ((uint32_t *) (a))[2] == htonl(0xffff))	\
+	 && ((uint32_t *) (a))[3] == 0)
+
+#endif /* _LINUX_NFS_IPV6_H */
diff -Nru linux-2.6.9-cel5/include/linux/nfs_mount.h linux-2.6.9-cel5-gq-08/include/linux/nfs_mount.h
--- linux-2.6.9-cel5/include/linux/nfs_mount.h	2004-10-18 23:53:06.000000000 +0200
+++ linux-2.6.9-cel5-gq-08/include/linux/nfs_mount.h	2005-03-04 09:38:58.541429448 +0100
@@ -20,7 +20,7 @@
  * mount-to-kernel version compatibility.  Some of these aren't used yet
  * but here they are anyway.
  */
-#define NFS_MOUNT_VERSION	6
+#define NFS_MOUNT_VERSION	7
 #define NFS_MAX_CONTEXT_LEN	256
 
 struct nfs_mount_data {
@@ -43,6 +43,7 @@
 	struct nfs3_fh	root;			/* 4 */
 	int		pseudoflavor;		/* 5 */
 	char		context[NFS_MAX_CONTEXT_LEN + 1];	/* 6 */
+	struct sockaddr_in6 addr6;		/* 7 */
 };
 
 /* bits in the flags field */
diff -Nru linux-2.6.9-cel5/include/linux/nfs_xdr.h linux-2.6.9-cel5-gq-08/include/linux/nfs_xdr.h
--- linux-2.6.9-cel5/include/linux/nfs_xdr.h	2005-03-04 09:32:40.929835136 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/nfs_xdr.h	2005-03-04 09:35:16.965114168 +0100
@@ -621,12 +621,12 @@
 struct nfs4_setclientid {
 	const nfs4_verifier *		sc_verifier;      /* request */
 	unsigned int			sc_name_len;
-	char				sc_name[32];	  /* request */
+	char				sc_name[80];	  /* request */
 	u32				sc_prog;          /* request */
 	unsigned int			sc_netid_len;
 	char				sc_netid[4];	  /* request */
 	unsigned int			sc_uaddr_len;
-	char				sc_uaddr[24];     /* request */
+	char				sc_uaddr[48];     /* request */
 	u32				sc_cb_ident;      /* request */
 };
 
diff -Nru linux-2.6.9-cel5/include/linux/sunrpc/clnt.h linux-2.6.9-cel5-gq-08/include/linux/sunrpc/clnt.h
--- linux-2.6.9-cel5/include/linux/sunrpc/clnt.h	2005-03-04 09:33:01.213751512 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/sunrpc/clnt.h	2005-03-04 09:45:36.458936792 +0100
@@ -118,7 +118,6 @@
 void		rpc_getport(struct rpc_task *, struct rpc_clnt *);
 void		rpc_getport6(struct rpc_task *, struct rpc_clnt *);
 int		rpc_register(u32, u32, int, unsigned short, int *);
-int		rpc_register6(u32, u32, int, unsigned short, int *);
 
 void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
diff -Nru linux-2.6.9-cel5/include/linux/sunrpc/svcauth.h linux-2.6.9-cel5-gq-08/include/linux/sunrpc/svcauth.h
--- linux-2.6.9-cel5/include/linux/sunrpc/svcauth.h	2005-03-04 09:32:37.195402856 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/sunrpc/svcauth.h	2005-03-04 09:34:57.159125136 +0100
@@ -15,6 +15,8 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/hash.h>
+#include <linux/in.h>
+#include <linux/in6.h>
 
 #define SVC_CRED_NGROUPS	32
 struct svc_cred {
@@ -113,9 +115,11 @@
 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_addr6(struct in6_addr *addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(struct auth_domain *item, int set);
 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_lookup6(struct in6_addr *addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 
diff -Nru linux-2.6.9-cel5/include/linux/sunrpc/svc.h linux-2.6.9-cel5-gq-08/include/linux/sunrpc/svc.h
--- linux-2.6.9-cel5/include/linux/sunrpc/svc.h	2005-03-04 09:32:37.195402856 +0100
+++ linux-2.6.9-cel5-gq-08/include/linux/sunrpc/svc.h	2005-03-04 09:34:32.778831504 +0100
@@ -10,7 +10,7 @@
 #ifndef SUNRPC_SVC_H
 #define SUNRPC_SVC_H
 
-#include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcauth.h>
@@ -111,7 +111,7 @@
 struct svc_rqst {
 	struct list_head	rq_list;	/* idle list */
 	struct svc_sock *	rq_sock;	/* socket */
-	struct sockaddr_in	rq_addr;	/* peer address */
+	struct sockaddr_in6	rq_addr;	/* peer address */
 	int			rq_addrlen;
 
 	struct svc_serv *	rq_server;	/* RPC service definition */
@@ -139,7 +139,7 @@
 				rq_secure  : 1;	/* secure port */
 
 
-	__u32			rq_daddr;	/* dest addr of request - reply from here */
+	struct in6_addr	       	rq_daddr;	/* dest addr of request - reply from here */
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
@@ -232,7 +232,7 @@
 
 struct svc_deferred_req {
 	u32			prot;	/* protocol (UDP or TCP) */
-	struct sockaddr_in	addr;
+	struct sockaddr_in6	addr;
 	struct svc_sock		*svsk;	/* where reply must go */
 	struct cache_deferred_req handle;
 	int			argslen;
diff -Nru linux-2.6.9-cel5/net/sunrpc/Makefile linux-2.6.9-cel5-gq-08/net/sunrpc/Makefile
--- linux-2.6.9-cel5/net/sunrpc/Makefile	2005-03-04 09:32:41.058815528 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/Makefile	2005-03-04 09:39:28.971803328 +0100
@@ -10,7 +10,7 @@
 sunrpc-y := clnt.o xprt.o socklib.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
-	    pmap_clnt.o timer.o xdr.o \
+	    pmap_clnt.o rpcb_clnt.o timer.o xdr.o \
 	    sunrpc_syms.o cache.o rpc_pipe.o
 sunrpc-$(CONFIG_PROC_FS) += stats.o
 sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff -Nru linux-2.6.9-cel5/net/sunrpc/pmap_clnt.c linux-2.6.9-cel5-gq-08/net/sunrpc/pmap_clnt.c
--- linux-2.6.9-cel5/net/sunrpc/pmap_clnt.c	2005-03-04 09:33:01.214751360 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/pmap_clnt.c	2005-03-04 09:48:12.515212632 +0100
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 
+#include <linux/nfs_ipv6.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/xprt.h>
 #include <linux/sunrpc/sched.h>
@@ -29,11 +30,10 @@
 #define PMAP_UNSET		2
 #define PMAP_GETPORT		3
 
-static struct rpc_procinfo	pmap_procedures[];
-static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
-static struct rpc_clnt *	pmap_create6(char *, struct sockaddr_in6 *, int);
-static void			pmap_getport_done(struct rpc_task *);
+struct rpc_clnt *		pmap_create(char *, struct sockaddr_in6 *, int);
+void				pmap_getport_done(struct rpc_task *);
 extern struct rpc_program	pmap_program;
+struct rpc_procinfo		pmap_procedures[];
 
 static inline void __wake_up_portmap_waiters(struct rpc_xprt *xprt)
 {
@@ -51,7 +51,7 @@
 {
 	struct rpc_xprt *xprt = clnt->cl_xprt;
 	struct rpc_portmap *map = &xprt->pmap;
-	struct sockaddr_in addr;
+	struct sockaddr_in6 addr;
 	struct rpc_message msg = {
 		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
 		.rpc_argp	= map,
@@ -102,61 +102,6 @@
 }
 EXPORT_SYMBOL(rpc_getport);
 
-void rpc_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
-{
-	struct rpc_xprt *xprt = clnt->cl_xprt;
-	struct rpc_portmap *map = &xprt->pmap;
-	struct sockaddr_in6 addr;
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
-		.rpc_argp	= map,
-		.rpc_resp	= &map->pm_port,
-		.rpc_cred	= NULL
-	};
-	struct rpc_clnt	*pmap_clnt;
-	struct rpc_task	*child;
-
-	dprintk("RPC: %5u rpc_getport6(%s, %u, %u, %d)\n",
-			task->tk_pid, clnt->cl_server, clnt->cl_prog,
-			clnt->cl_vers, xprt->prot);
-
-	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
-		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
-		return;
-	}
-
-	map->pm_prog = clnt->cl_prog;
-	map->pm_vers = clnt->cl_vers;
-	map->pm_prot = xprt->prot;
-
-	rpc_peeraddr(clnt, &addr, sizeof(addr));
-	pmap_clnt = pmap_create6(clnt->cl_server, &addr, xprt->prot);
-	if (IS_ERR(pmap_clnt)) {
-		task->tk_status = PTR_ERR(pmap_clnt);
-		goto bailout;
-	}
-	task->tk_status = 0;
-
-	/*
-	 * Note: rpc_new_child will release client after a failure.
-	 */
-	if (!(child = rpc_new_child(pmap_clnt, task)))
-		goto bailout;
-
-	/* Setup the call info struct */
-	rpc_call_setup(child, &msg, 0);
-
-	/* ... and run the child task */
-	rpc_run_child(task, child, pmap_getport_done);
-	return;
-
-bailout:
-	__wake_up_portmap_waiters(xprt);
-	task->tk_status = -EIO;
-	task->tk_action = NULL;
-}
-EXPORT_SYMBOL(rpc_getport6);
-
 #ifdef CONFIG_ROOT_NFS
 int
 rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
@@ -167,6 +112,7 @@
 		.pm_prot	= prot,
 		.pm_port	= 0
 	};
+	struct sockaddr_in6 sin6;
 	struct rpc_clnt	*pmap_clnt;
 	char		hostname[32];
 	int		status;
@@ -174,8 +120,8 @@
 	dprintk("RPC:       rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
 			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
-	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-	pmap_clnt = pmap_create(hostname, sin, prot);
+	map_sockaddr_4to6(sin, &sin6);
+	pmap_clnt = pmap_create(hostname, &sin, prot);
 	if (IS_ERR(pmap_clnt))
 		return PTR_ERR(pmap_clnt);
 
@@ -191,7 +137,7 @@
 }
 #endif
 
-static void
+void
 pmap_getport_done(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
@@ -209,8 +155,10 @@
 		/* Program not registered */
 		task->tk_status = -EACCES;
 		task->tk_action = NULL;
-	} else
+	} else {
 		xprt->ops->set_port(xprt, map->pm_port);
+		xprt->need_bind = 0;
+	}
 
 	__wake_up_portmap_waiters(xprt);
 }
@@ -222,16 +170,15 @@
 int
 rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 {
-	struct sockaddr_in	sin;
+	struct sockaddr_in6	sin;
 	struct rpc_portmap	map;
 	struct rpc_clnt		*pmap_clnt;
 	int error = 0;
 
-	dprintk("RPC:       registering (%u, %u, %d, %u) with IPv4 portmapper.\n",
+	dprintk("RPC:       registering (%u, %u, %d, %u) with portmapper.\n",
 			prog, vers, prot, port);
 
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	init_sockaddr_loopback6(0, &sin);
 	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
 	if (IS_ERR(pmap_clnt)) {
 		error = PTR_ERR(pmap_clnt);
@@ -258,67 +205,7 @@
 	return error;
 }
 
-int
-rpc_register6(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
-{
-	struct sockaddr_in6	sin6;
-	struct rpc_portmap	map;
-	struct rpc_clnt		*pmap_clnt;
-	int error = 0;
-
-	dprintk("RPC:       registering (%u, %u, %d, %u) with IPv6 portmapper.\n",
-			prog, vers, prot, port);
-
-	sin6.sin6_family = AF_INET6;
-	sin6.sin6_addr.s6_addr32[0] = 0;
-	sin6.sin6_addr.s6_addr32[1] = 0;
-	sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-	sin6.sin6_addr.s6_addr32[3] = htonl(INADDR_LOOPBACK);
-	pmap_clnt = pmap_create6("localhost", &sin6, IPPROTO_UDP);
-	if (IS_ERR(pmap_clnt)) {
-		error = PTR_ERR(pmap_clnt);
-		dprintk("RPC:       couldn't create pmap client. Error = %d\n", error);
-		return error;
-	}
-
-	map.pm_prog = prog;
-	map.pm_vers = vers;
-	map.pm_prot = prot;
-	map.pm_port = port;
-
-	error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET,
-					&map, okay, 0);
-
-	if (error < 0) {
-		printk(KERN_WARNING
-			"RPC: failed to contact portmap (errno %d).\n",
-			error);
-	}
-	dprintk("RPC:       registration status %d/%d\n", error, *okay);
-
-	/* Client deleted automatically because cl_oneshot == 1 */
-	return error;
-}
-
-static struct rpc_clnt * pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
-{
-	struct rpc_create_args args = {
-		.protocol	= proto,
-		.address	= (struct sockaddr *)srvaddr,
-		.addrsize	= sizeof(*srvaddr),
-		.servername	= hostname,
-		.program	= &pmap_program,
-		.version	= RPC_PMAP_VERSION,
-		.authflavor	= RPC_AUTH_NULL,
-		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
-					RPC_CLNT_ONESHOT,
-	};
-
-	srvaddr->sin_port = htons(RPC_PMAP_PORT);
-	return rpc_create(&args);
-}
-
-static struct rpc_clnt * pmap_create6(char *hostname, struct sockaddr_in6 *srvaddr, int proto)
+struct rpc_clnt * pmap_create(char *hostname, struct sockaddr_in6 *srvaddr, int proto)
 {
 	struct rpc_create_args args = {
 		.protocol	= proto,
@@ -367,7 +254,7 @@
 	return 0;
 }
 
-static struct rpc_procinfo	pmap_procedures[] = {
+struct rpc_procinfo	pmap_procedures[] = {
 [PMAP_SET] = {
 	  .p_proc		= PMAP_SET,
 	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
diff -Nru linux-2.6.9-cel5/net/sunrpc/rpcb_clnt.c linux-2.6.9-cel5-gq-08/net/sunrpc/rpcb_clnt.c
--- linux-2.6.9-cel5/net/sunrpc/rpcb_clnt.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/rpcb_clnt.c	2005-03-04 09:49:22.082636776 +0100
@@ -0,0 +1,303 @@
+/*
+ * linux/net/sunrpc/rpcb_clnt.c
+ *
+ * Rpcbind client.
+ *
+ * FIXME: In a secure environment, we may want to use an authentication
+ * flavor other than AUTH_NULL.
+ *
+ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/xprt.h>
+#include <linux/sunrpc/sched.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_PMAP
+#endif
+
+#define RPCB_SET		1
+#define RPCB_UNSET		2
+#define RPCB_GETADDR		3
+
+#define RPC_RPCB_VERSION	3
+
+static struct rpc_procinfo	rpcb_procedures[];
+static struct rpc_clnt *	rpcb_create6(char *, struct sockaddr_in6 *, int);
+static void			rpcb_getport_done(struct rpc_task *);
+extern struct rpc_program	rpcb_program;
+
+struct rpc_rpcb_req {
+	u32 r_prog;
+	u32 r_vers;
+	char r_addr[40];
+};
+
+static void (*action)(struct rpc_task *);
+
+static inline void __wake_up_portmap_waiters(struct rpc_xprt *xprt)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_BINDING, &xprt->state);
+	smp_mb__after_clear_bit();
+	rpc_wake_up(&xprt->bindwait);
+}
+
+void rpc_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_portmap *map = &xprt->pmap;
+	static struct rpc_rpcb_req rpcb_req;
+	struct rpc_message msg = {
+		.rpc_proc	= &rpcb_procedures[RPCB_GETADDR],
+		.rpc_argp	= &rpcb_req,
+		.rpc_resp	= &map->pm_port,
+		.rpc_cred	= NULL
+	};
+	struct rpc_clnt	*rpcb_clnt;
+	struct rpc_task	*child;
+	struct sockaddr_in6 addr;
+	char str[40];
+
+	dprintk("RPC: %5u rpc_getport6(%s, %u, %u, %d)\n",
+			task->tk_pid, clnt->cl_server, clnt->cl_prog,
+			clnt->cl_vers, xprt->prot);
+
+	action = task->tk_action;
+	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
+		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
+		return;
+	}
+
+	map->pm_prog = rpcb_req.r_prog = clnt->cl_prog;
+	map->pm_vers = rpcb_req.r_vers = clnt->cl_vers;
+	map->pm_prot = xprt->prot;
+	rpc_peeraddr(clnt, &addr, sizeof(addr));
+	snprintf(str, sizeof(str),
+		"%x:%x:%x:%x:%x:%x:%x:%x",
+		NIP6(addr.sin6_addr));
+	memcpy(rpcb_req.r_addr, str, strlen(str));
+	rpcb_req.r_addr[strlen(str)] = '\0';
+
+	rpcb_clnt = rpcb_create6(clnt->cl_server, &addr, xprt->prot);
+	if (IS_ERR(rpcb_clnt)) {
+		task->tk_status = PTR_ERR(rpcb_clnt);
+		goto bailout;
+	}
+	task->tk_status = 0;
+
+	/*
+	 * Note: rpc_new_child will release client after a failure.
+	 */
+	if (!(child = rpc_new_child(rpcb_clnt, task)))
+		goto bailout;
+
+	/* Setup the call info struct */
+	rpc_call_setup(child, &msg, 0);
+
+	/* ... and run the child task */
+	rpc_run_child(task, child, rpcb_getport_done);
+	return;
+
+bailout:
+	__wake_up_portmap_waiters(xprt);
+	task->tk_status = -EIO;
+	task->tk_action = NULL;
+}
+EXPORT_SYMBOL(rpc_getport6);
+
+static void
+rpcb_getport_done(struct rpc_task *task)
+{
+	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_portmap *map = &xprt->pmap;
+
+	dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
+			task->tk_pid, task->tk_status, map->pm_port);
+
+	xprt->ops->set_port(xprt, 0);
+	if (task->tk_status == -EIO) {
+		/* try with portmapper v2 */
+		task->tk_status = 0;
+		task->tk_action = action;
+		smp_mb__before_clear_bit();
+		clear_bit(XPRT_BINDING, &xprt->state);
+		smp_mb__after_clear_bit();
+		rpc_getport(task, clnt);
+		return;
+	} else if (task->tk_status < 0) {
+		/* Make the calling task exit with an error */
+		task->tk_action = NULL;
+	} else if (map->pm_port == 0) {
+		/* Program not registered */
+		task->tk_status = -EACCES;
+		task->tk_action = NULL;
+	} else {
+		xprt->ops->set_port(xprt, map->pm_port);
+		xprt->need_bind = 0;
+	}
+
+	__wake_up_portmap_waiters(xprt);
+}
+
+static struct rpc_clnt * rpcb_create6(char *hostname, struct sockaddr_in6 *srvaddr, int proto)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= (struct sockaddr *)srvaddr,
+		.addrsize	= sizeof(*srvaddr),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= RPC_RPCB_VERSION,
+		.authflavor	= RPC_AUTH_NULL,
+		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
+					RPC_CLNT_ONESHOT,
+	};
+
+	srvaddr->sin6_port = htons(RPC_PMAP_PORT);
+	return rpc_create(&args);
+}
+
+/*
+ * XDR encode/decode functions for PMAP
+ */
+static int
+xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map)
+{
+	dprintk("RPC:       xdr_encode_mapping(%u, %u, %d, %u)\n",
+		map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
+	*p++ = htonl(map->pm_prog);
+	*p++ = htonl(map->pm_vers);
+	*p++ = htonl(map->pm_prot);
+	*p++ = htonl(map->pm_port);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	return 0;
+}
+
+static void
+xdr_addr_len_value(u32 **p, char *val)
+{
+	int len, offset;
+	len = strlen(val);
+	**p = htonl(len);
+	*p += 1;
+	strcpy((char *)*p, val);
+	offset = len / 4;
+	if (len % 4)
+		offset++;
+	*p += offset;
+}
+
+static int
+xdr_encode_getaddr(struct rpc_rqst *req, u32 *p, struct rpc_rpcb_req *rpcb)
+{
+	char netid[] = "tcp6";
+	char owner[] = "rpcb";
+
+	dprintk("RPC:       xdr_encode_getaddr(%u, %u, %s)\n",
+		rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
+	*p++ = htonl(rpcb->r_prog);
+	*p++ = htonl(rpcb->r_vers);
+	xdr_addr_len_value(&p, netid);
+	xdr_addr_len_value(&p, rpcb->r_addr);
+	xdr_addr_len_value(&p, owner);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	return 0;
+}
+
+static int
+xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
+{
+	char *addr;
+	int addr_len, c, i, f, first, val;
+
+	*portp = 0;
+	addr_len = (unsigned int) ntohl(*p++);
+	addr = (char *)p;
+	val = 0;
+	first = 1;
+	f = 1;
+	for (i = addr_len - 1; i > 0; i--) {
+		c = addr[i];
+		if (c >= '0' && c <= '9') {
+			val += (c - '0') * f;
+			f *= 10;
+		} else if (c == '.') {
+			if (first) {
+				*portp = val;
+				val = first = 0;
+				f = 1;
+			} else {
+			         *portp |= (val << 8);
+				 break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int
+xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
+{
+	*boolp = (unsigned int) ntohl(*p++);
+	return 0;
+}
+
+static struct rpc_procinfo	rpcb_procedures[] = {
+[RPCB_SET] = {
+	  .p_proc		= RPCB_SET,
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+[RPCB_UNSET] = {
+	  .p_proc		= RPCB_UNSET,
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+[RPCB_GETADDR] = {
+	  .p_proc		= RPCB_GETADDR,
+	  .p_encode		= (kxdrproc_t) xdr_encode_getaddr,
+	  .p_decode		= (kxdrproc_t) xdr_decode_port,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+};
+
+static struct rpc_version	rpcb_version3 = {
+	.number		= 3,
+	.nrprocs	= 4,
+	.procs		= rpcb_procedures
+};
+
+static struct rpc_version *	rpcb_version[] = {
+	NULL,
+	NULL,
+	NULL,
+	&rpcb_version3
+};
+
+static struct rpc_stat		rpcb_stats;
+
+struct rpc_program	rpcb_program = {
+	.name		= "rpcbind",
+	.number		= RPC_PMAP_PROGRAM,
+	.nrvers		= ARRAY_SIZE(rpcb_version),
+	.version	= rpcb_version,
+	.stats		= &rpcb_stats,
+};
diff -Nru linux-2.6.9-cel5/net/sunrpc/rpc_pipe.c linux-2.6.9-cel5-gq-08/net/sunrpc/rpc_pipe.c
--- linux-2.6.9-cel5/net/sunrpc/rpc_pipe.c	2005-03-04 09:32:41.060815224 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/rpc_pipe.c	2005-03-04 09:47:43.857569256 +0100
@@ -23,6 +23,7 @@
 #include <linux/poll.h>
 #include <linux/wait.h>
 #include <linux/seq_file.h>
+#include <linux/in6.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/workqueue.h>
@@ -296,14 +297,14 @@
 rpc_show_info(struct seq_file *m, void *v)
 {
 	struct rpc_clnt *clnt = m->private;
-	struct sockaddr_in addr;
+	struct sockaddr_in6 addr;
 
 	seq_printf(m, "RPC server: %s\n", clnt->cl_server);
 	seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname,
 			clnt->cl_prog, clnt->cl_vers);
 	rpc_peeraddr(clnt, &addr, sizeof(addr));
-	seq_printf(m, "address: %u.%u.%u.%u\n",
-			NIPQUAD(addr.sin_addr.s_addr));
+	seq_printf(m, "address: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+		   NIP6(addr.sin6_addr));
 	seq_printf(m, "protocol: %s\n",
 			clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
 	return 0;
diff -Nru linux-2.6.9-cel5/net/sunrpc/sunrpc_syms.c linux-2.6.9-cel5-gq-08/net/sunrpc/sunrpc_syms.c
--- linux-2.6.9-cel5/net/sunrpc/sunrpc_syms.c	2005-03-04 09:32:41.066814312 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/sunrpc_syms.c	2005-03-04 09:34:57.159125136 +0100
@@ -101,8 +101,10 @@
 EXPORT_SYMBOL(auth_domain_find);
 EXPORT_SYMBOL(auth_domain_put);
 EXPORT_SYMBOL(auth_unix_add_addr);
+EXPORT_SYMBOL(auth_unix_add_addr6);
 EXPORT_SYMBOL(auth_unix_forget_old);
 EXPORT_SYMBOL(auth_unix_lookup);
+EXPORT_SYMBOL(auth_unix_lookup6);
 EXPORT_SYMBOL(cache_check);
 EXPORT_SYMBOL(cache_clean);
 EXPORT_SYMBOL(cache_flush);
diff -Nru linux-2.6.9-cel5/net/sunrpc/svcauth_unix.c linux-2.6.9-cel5-gq-08/net/sunrpc/svcauth_unix.c
--- linux-2.6.9-cel5/net/sunrpc/svcauth_unix.c	2005-03-04 09:32:37.258393280 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/svcauth_unix.c	2005-03-04 09:49:07.901792592 +0100
@@ -8,6 +8,8 @@
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
+#include <linux/nfs_ipv6.h>
+#include <linux/ipv6.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
@@ -91,7 +93,7 @@
 struct ip_map {
 	struct cache_head	h;
 	char			m_class[8]; /* e.g. "nfsd" */
-	struct in_addr		m_addr;
+	struct in6_addr		m_addr;
 	struct unix_domain	*m_client;
 	int			m_add_change;
 };
@@ -111,17 +113,18 @@
 static inline int ip_map_hash(struct ip_map *item)
 {
 	return hash_str(item->m_class, IP_HASHBITS) ^ 
-		hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
+		hash_long((unsigned long)item->m_addr.s6_addr32[3], IP_HASHBITS);
 }
 static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
 {
-	return strcmp(tmp->m_class, item->m_class) == 0
-		&& tmp->m_addr.s_addr == item->m_addr.s_addr;
+    return strcmp(tmp->m_class, item->m_class) == 0
+	&& !memcmp(&tmp->m_addr.s6_addr, &item->m_addr.s6_addr,
+		  sizeof(struct in6_addr));
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
 	strcpy(new->m_class, item->m_class);
-	new->m_addr.s_addr = item->m_addr.s_addr;
+	memcpy(&new->m_addr, &item->m_addr, sizeof(struct in6_addr));
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
 {
@@ -134,18 +137,13 @@
 				  struct cache_head *h,
 				  char **bpp, int *blen)
 {
-	char text_addr[20];
+	char text_addr[40];
 	struct ip_map *im = container_of(h, struct ip_map, h);
-	__u32 addr = im->m_addr.s_addr;
-	
-	snprintf(text_addr, 20, "%u.%u.%u.%u",
-		 ntohl(addr) >> 24 & 0xff,
-		 ntohl(addr) >> 16 & 0xff,
-		 ntohl(addr) >>  8 & 0xff,
-		 ntohl(addr) >>  0 & 0xff);
 
+	sprintf(text_addr, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+		NIP6(im->m_addr));
 	qword_add(bpp, blen, im->m_class);
-	qword_add(bpp, blen, text_addr);
+	qword_addhex(bpp, blen, text_addr, strlen(text_addr));
 	(*bpp)[-1] = '\n';
 }
 
@@ -156,7 +154,7 @@
 	/* class ipaddress [domainname] */
 	char class[50], buf[50];
 	int len;
-	int b1,b2,b3,b4;
+        int b1,b2,b3,b4,b5,b6,b7,b8;
 	char c;
 	struct ip_map ipm, *ipmp;
 	struct auth_domain *dom;
@@ -176,7 +174,8 @@
 	len = qword_get(&mesg, buf, 50);
 	if (len <= 0) return -EINVAL;
 
-	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+	if (sscanf(buf, "%x:%x:%x:%x:%x:%x:%x:%x%c",
+		   &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) != 8)
 		return -EINVAL;
 	
 	expiry = get_expiry(&mesg);
@@ -195,8 +194,10 @@
 		dom = NULL;
 
 	strcpy(ipm.m_class, class);
-	ipm.m_addr.s_addr =
-		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+	ipm.m_addr.s6_addr32[0] = htonl((b1<<16)|b2);
+	ipm.m_addr.s6_addr32[1] = htonl((b3<<16)|b4);
+	ipm.m_addr.s6_addr32[2] = htonl((b5<<16)|b6);
+	ipm.m_addr.s6_addr32[3] = htonl((b7<<16)|b8);
 	ipm.h.flags = 0;
 	if (dom) {
 		ipm.m_client = container_of(dom, struct unix_domain, h);
@@ -221,7 +222,7 @@
 		       struct cache_head *h)
 {
 	struct ip_map *im;
-	struct in_addr addr;
+	struct in6_addr addr;
 	char *dom = "-no-domain-";
 
 	if (h == NULL) {
@@ -230,20 +231,14 @@
 	}
 	im = container_of(h, struct ip_map, h);
 	/* class addr domain */
-	addr = im->m_addr;
+	memcpy((void *)&addr, (void *)&im->m_addr, sizeof(struct in6_addr));
 
 	if (test_bit(CACHE_VALID, &h->flags) && 
-	    !test_bit(CACHE_NEGATIVE, &h->flags))
+	    !test_bit(CACHE_NEGATIVE, &h->flags)) 
 		dom = im->m_client->h.name;
 
-	seq_printf(m, "%s %d.%d.%d.%d %s\n",
-		   im->m_class,
-		   htonl(addr.s_addr) >> 24 & 0xff,
-		   htonl(addr.s_addr) >> 16 & 0xff,
-		   htonl(addr.s_addr) >>  8 & 0xff,
-		   htonl(addr.s_addr) >>  0 & 0xff,
-		   dom
-		   );
+	seq_printf(m, "%s %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %s\n", im->m_class, NIP6(addr), dom);
+	dprintk("ip_map_show: seq = %s %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %s\n", im->m_class, NIP6(addr), dom);
 	return 0;
 }
 	
@@ -260,8 +255,7 @@
 
 static DefineSimpleCacheLookup(ip_map)
 
-
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr6(struct in6_addr *addr, struct auth_domain *dom)
 {
 	struct unix_domain *udom;
 	struct ip_map ip, *ipmp;
@@ -270,7 +264,7 @@
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
 	strcpy(ip.m_class, "nfsd");
-	ip.m_addr = addr;
+	memcpy((void *)&ip.m_addr, (void *)addr, sizeof(struct in6_addr));
 	ip.m_client = udom;
 	ip.m_add_change = udom->addr_changes+1;
 	ip.h.flags = 0;
@@ -285,6 +279,14 @@
 		return -ENOMEM;
 }
 
+int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+{
+	struct in6_addr addr6;
+
+	map_ipaddr_4to6(&addr, &addr6);
+	return auth_unix_add_addr6(&addr6, dom);
+}
+
 int auth_unix_forget_old(struct auth_domain *dom)
 {
 	struct unix_domain *udom;
@@ -296,13 +298,13 @@
 	return 0;
 }
 
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup6(struct in6_addr *addr)
 {
 	struct ip_map key, *ipm;
 	struct auth_domain *rv;
 
 	strcpy(key.m_class, "nfsd");
-	key.m_addr = addr;
+	memcpy((void *)&key.m_addr, (void *)addr, sizeof(struct in6_addr));
 
 	ipm = ip_map_lookup(&key, 0);
 
@@ -323,6 +325,14 @@
 	return rv;
 }
 
+struct auth_domain *auth_unix_lookup(struct in_addr addr)
+{
+	struct in6_addr addr6;
+
+	map_ipaddr_4to6(&addr, &addr6);
+	return auth_unix_lookup6(&addr6);
+}
+
 void svcauth_unix_purge(void)
 {
 	cache_purge(&ip_map_cache);
@@ -335,7 +345,8 @@
 	struct ip_map key, *ipm;
 
 	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
-	key.m_addr = rqstp->rq_addr.sin_addr;
+	memcpy((void *)&key.m_addr, (void *)&rqstp->rq_addr.sin6_addr,
+		sizeof(struct in6_addr));
 
 	ipm = ip_map_lookup(&key, 0);
 
diff -Nru linux-2.6.9-cel5/net/sunrpc/svc.c linux-2.6.9-cel5-gq-08/net/sunrpc/svc.c
--- linux-2.6.9-cel5/net/sunrpc/svc.c	2005-03-04 09:32:37.264392368 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/svc.c	2005-03-04 09:39:29.073787824 +0100
@@ -452,7 +452,8 @@
 
 err_bad_vers:
 #ifdef RPC_PARANOIA
-	printk("svc: unknown version (%d)\n", vers);
+	printk("svc: unknown version (prog = %d, vers = %d, proc = %d)\n", prog,
+		vers, proc);
 #endif
 	serv->sv_stats->rpcbadfmt++;
 	svc_putu32(resv, rpc_prog_mismatch);
diff -Nru linux-2.6.9-cel5/net/sunrpc/svcsock.c linux-2.6.9-cel5-gq-08/net/sunrpc/svcsock.c
--- linux-2.6.9-cel5/net/sunrpc/svcsock.c	2005-03-04 09:32:41.068814008 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/svcsock.c	2005-03-04 09:39:29.120780680 +0100
@@ -24,6 +24,7 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
+#include <linux/ipv6.h>
 #include <linux/inet.h>
 #include <linux/udp.h>
 #include <linux/tcp.h>
@@ -352,9 +353,9 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	int		slen;
-	char 		buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+	char 		buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
 	struct cmsghdr *cmh = (struct cmsghdr *)buffer;
-	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
+	struct in6_pktinfo *pki = (struct in6_pktinfo *)CMSG_DATA(cmh);
 	int		len = 0;
 	int		result;
 	int		size;
@@ -379,8 +380,8 @@
 		cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
 		cmh->cmsg_level = SOL_IP;
 		cmh->cmsg_type = IP_PKTINFO;
-		pki->ipi_ifindex = 0;
-		pki->ipi_spec_dst.s_addr = rqstp->rq_daddr;
+		pki->ipi6_ifindex = 0;
+		memcpy(&pki->ipi6_addr, &rqstp->rq_daddr, sizeof(struct in6_addr));
 
 		if (sock_sendmsg(sock, &msg, 0) < 0)
 			goto out;
@@ -422,9 +423,9 @@
 			len += result;
 	}
 out:
-	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
-			rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
-		rqstp->rq_addr.sin_addr.s_addr);
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x)\n",
+	       	rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
+		NIP6(rqstp->rq_addr.sin6_addr));
 
 	return len;
 }
@@ -602,10 +603,10 @@
 	rqstp->rq_prot        = IPPROTO_UDP;
 
 	/* Get sender address */
-	rqstp->rq_addr.sin_family = AF_INET;
-	rqstp->rq_addr.sin_port = skb->h.uh->source;
-	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-	rqstp->rq_daddr = skb->nh.iph->daddr;
+	rqstp->rq_addr.sin6_family = AF_INET6;
+	rqstp->rq_addr.sin6_port = skb->h.uh->source;
+	memcpy(&rqstp->rq_addr.sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr));
+	memcpy(&rqstp->rq_daddr, &skb->nh.ipv6h->daddr, sizeof(struct in6_addr));
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
@@ -760,7 +761,7 @@
 static void
 svc_tcp_accept(struct svc_sock *svsk)
 {
-	struct sockaddr_in sin;
+	struct sockaddr_in6 sin;
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
@@ -772,7 +773,7 @@
 	if (!sock)
 		return;
 
-	err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
+	err = sock_create_lite(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &newsock);
 	if (err) {
 		if (err == -ENOMEM)
 			printk(KERN_WARNING "%s: no more sockets!\n",
@@ -806,15 +807,16 @@
 	 * hosts here, but when we get encription, the IP of the host won't
 	 * tell us anything. For now just warn about unpriv connections.
 	 */
-	if (ntohs(sin.sin_port) >= 1024) {
+	if (ntohs(sin.sin6_port) >= 1024) {
 		dprintk(KERN_WARNING
-			"%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
-			serv->sv_name, 
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+			"%s: connect from unprivileged port: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x, port %d (0x%x)\n",
+			serv->sv_name, NIP6(sin.sin6_addr),
+			ntohs(sin.sin6_port), ntohs(sin.sin6_port));
 	}
 
-	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	dprintk("%s: connect from %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x, port %d (0x%x)\n",
+		serv->sv_name, NIP6(sin.sin6_addr),
+	       	ntohs(sin.sin6_port), ntohs(sin.sin6_port));
 
 	/* make sure that a write doesn't block forever when
 	 * low on memory
@@ -847,10 +849,9 @@
 					"number of nfsd threads\n",
 						   serv->sv_name);
 				printk(KERN_NOTICE "%s: last TCP connect from "
-					"%u.%u.%u.%u:%d\n",
-					serv->sv_name,
-					NIPQUAD(sin.sin_addr.s_addr),
-					ntohs(sin.sin_port));
+					"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x, port %d (0x%x)\n",
+					serv->sv_name, NIP6(sin.sin6_addr),
+					ntohs(sin.sin6_port), ntohs(sin.sin6_port));
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
@@ -1259,7 +1260,7 @@
 		spin_unlock_bh(&serv->sv_lock);
 	}
 
-	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin6_port) < 1024;
 	rqstp->rq_chandle.defer = svc_defer;
 
 	if (serv->sv_stats)
@@ -1388,17 +1389,17 @@
  * Create socket for RPC service.
  */
 static int
-svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
+svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in6 *sin)
 {
 	struct svc_sock	*svsk;
 	struct socket	*sock;
 	int		error;
 	int		type;
 
-	dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
+	dprintk("svc: svc_create_socket(%s, %d, %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d)\n",
 				serv->sv_program->pg_name, protocol,
-				NIPQUAD(sin->sin_addr.s_addr),
-				ntohs(sin->sin_port));
+				NIP6(sin->sin6_addr),
+				ntohs(sin->sin6_port));
 
 	if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1407,7 +1408,7 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+	if ((error = sock_create_kern(PF_INET6, type, protocol, &sock)) < 0)
 		return error;
 
 	if (sin != NULL) {
@@ -1476,13 +1477,13 @@
 int
 svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
 {
-	struct sockaddr_in	sin;
+    struct sockaddr_in6	sin;
 
-	dprintk("svc: creating socket proto = %d\n", protocol);
-	sin.sin_family      = AF_INET;
-	sin.sin_addr.s_addr = INADDR_ANY;
-	sin.sin_port        = htons(port);
-	return svc_create_socket(serv, protocol, &sin);
+    dprintk("svc: creating socket proto = %d\n", protocol);
+    sin.sin6_family      = AF_INET6;
+    memset(&sin.sin6_addr, 0, sizeof(struct in6_addr));
+    sin.sin6_port        = htons(port);
+    return svc_create_socket(serv, protocol, &sin);
 }
 
 /*
diff -Nru linux-2.6.9-cel5/net/sunrpc/xprtsock.c linux-2.6.9-cel5-gq-08/net/sunrpc/xprtsock.c
--- linux-2.6.9-cel5/net/sunrpc/xprtsock.c	2005-03-04 09:33:01.216751056 +0100
+++ linux-2.6.9-cel5-gq-08/net/sunrpc/xprtsock.c	2005-03-04 09:49:18.770140352 +0100
@@ -369,7 +369,7 @@
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
 	status = xs_sendpages(sock, (struct sockaddr *) &xprt->addr,
-			sizeof(struct sockaddr), xdr, req->rq_bytes_sent);
+			sizeof(xprt->addr), xdr, req->rq_bytes_sent);
 
 	dprintk("RPC:       xs_udp_send_request(%u) = %d\n",
 			xdr->len - req->rq_bytes_sent, status);
@@ -1153,23 +1153,9 @@
  */
 static void xs_set_port(struct rpc_xprt *xprt, u16 port)
 {
-	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
-	dprintk("RPC:       setting port for xprt %p to %d\n",
-			xprt, sap->sin_port);
-	sap->sin_port = htons(port);
-}
-
-/**
- * xs_set_port6 - reset the port number in the remote endpoint address
- * @xprt: generic transport
- * @port: new port number
- *
- */
-static void xs_set_port6(struct rpc_xprt *xprt, u16 port)
-{
 	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) &xprt->addr;
 	dprintk("RPC:       setting port for xprt %p to %d\n",
-			xprt, sap->sin6_port);
+			xprt, port);
 	sap->sin6_port = htons(port);
 }
 
@@ -1180,11 +1166,11 @@
  */
 static int xs_is_bound(struct rpc_xprt *xprt)
 {
-	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
-	int is_bound = (sap->sin_port != 0) && (xprt->need_bind == 0);
+	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) &xprt->addr;
+	int is_bound = (sap->sin6_port != 0) && (xprt->need_bind == 0);
 	dprintk("RPC:       xprt %p is %sbound: port=%d, need_bind=%d\n",
-			xprt, (is_bound ? "" : "not "), sap->sin_port,
-				xprt->need_bind);
+			xprt, (is_bound ? "" : "not "),
+			htons(sap->sin6_port), xprt->need_bind);
 	return is_bound;
 }
 
@@ -1196,37 +1182,6 @@
  */
 static int xs_bindresvport(struct xs_private *priv, struct socket *sock)
 {
-	struct sockaddr_in myaddr = {
-		.sin_family = AF_INET,
-	};
-	int		err, port;
-
-	/* Were we already bound to a given port? Try to reuse it */
-	port = priv->port;
-	do {
-		myaddr.sin_port = htons(port);
-		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
-						sizeof(myaddr));
-		if (err == 0) {
-			priv->port = port;
-			return 0;
-		}
-		if (--port == 0)
-			port = XS_MAX_RESVPORT;
-	} while (err == -EADDRINUSE && port != priv->port);
-
-	printk(KERN_ERR "RPC: Can't bind to reserved port (%d).\n", -err);
-	return err;
-}
-
-/**
- * xs_bindrevport6 - bind to a reserved IPv6 port number
- * @priv: private transport structure
- * @sock: socket to bind
- *
- */
-static int xs_bindresvport6(struct xs_private *priv, struct socket *sock)
-{
 	struct sockaddr_in6 myaddr = {
 		.sin6_family = AF_INET6,
 	};
@@ -1251,7 +1206,7 @@
 }
 
 /**
- * xs_udp_connect_worker - set up a UDP over IPv4 socket
+ * xs_udp_connect_worker - set up a UDP socket
  * @args: RPC transport to connect
  *
  * Invoked by a work queue tasklet.
@@ -1271,78 +1226,12 @@
 	/* Start by resetting any existing state */
 	xs_close(xprt);
 
-	if ((err = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
-		printk(KERN_ERR "RPC: can't create socket (%d).\n", -err);
-		goto out;
-	}
-
-	if (xprt->resvport && xs_bindresvport(priv, sock) < 0) {
-		printk(KERN_ERR "RPC: can't bind to reserved port.\n");
-		sock_release(sock);
-		goto out;
-	}
-
-	if (!priv->inet) {
-		struct sock     *sk = sock->sk;
-
-		write_lock_bh(&sk->sk_callback_lock);
-
-		sk->sk_user_data = xprt;
-		priv->old_data_ready = sk->sk_data_ready;
-		priv->old_state_change = sk->sk_state_change;
-		priv->old_write_space = sk->sk_write_space;
-		sk->sk_data_ready = xs_udp_data_ready;
-		sk->sk_write_space = xs_udp_write_space;
-		sk->sk_no_check = UDP_CSUM_NORCV;
-
-		xprt_set_connected(xprt);
-
-		/* Reset to new socket */
-		priv->sock = sock;
-		priv->inet = sk;
-
-		write_unlock_bh(&sk->sk_callback_lock);
-	}
-	xs_udp_do_setbufsize(xprt);
-	status = 0;
-out:
-	if (status < 0)
-		rpc_wake_up_status(&xprt->pending, status);
-	else
-		rpc_wake_up(&xprt->pending);
-
-	smp_mb__before_clear_bit();
-	clear_bit(XPRT_CONNECTING, &xprt->state);
-	smp_mb__after_clear_bit();
-}
-
-/**
- * xs_udp6_connect_worker - set up a UDP over IPv6 socket
- * @args: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_udp6_connect_worker(void *args)
-{
-	struct rpc_xprt	*xprt = (struct rpc_xprt *)args;
-	struct xs_private *priv = xs_private_data(xprt);
-	struct socket	*sock = priv->sock;
-	int		err, status = -EIO;
-
-	if (xprt->shutdown || !xprt_is_bound(xprt))
-		goto out;
-
-	dprintk("RPC:       xs_udp6_connect_worker for xprt %p\n", xprt);
-
-	/* Start by resetting any existing state */
-	xs_close(xprt);
-
 	if ((err = sock_create(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
 		printk(KERN_ERR "RPC: can't create socket (%d).\n", -err);
 		goto out;
 	}
 
-	if (xprt->resvport && xs_bindresvport6(priv, sock) < 0) {
+	if (xprt->resvport && xs_bindresvport(priv, sock) < 0) {
 		printk(KERN_ERR "RPC: can't bind to reserved port.\n");
 		sock_release(sock);
 		goto out;
@@ -1383,7 +1272,7 @@
 }
 
 /**
- * xs_tcp_connect_worker - connect a TCP over IPv4 socket to a remote endpoint
+ * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
  * @args: RPC transport to connect
  *
  * Invoked by a work queue tasklet.
@@ -1403,95 +1292,12 @@
 	/* Start by resetting any existing state */
 	xs_close(xprt);
 
-	if ((err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
-		printk(KERN_ERR "RPC: can't create socket (%d).\n", -err);
-		goto out;
-	}
-
-	if (xprt->resvport && xs_bindresvport(priv, sock) < 0) {
-		printk(KERN_ERR "RPC: can't bind to reserved port.\n");
-		sock_release(sock);
-		goto out;
-	}
-
-	if (!priv->inet) {
-		struct sock     *sk = sock->sk;
-
-		write_lock_bh(&sk->sk_callback_lock);
-
-		sk->sk_user_data = xprt;
-		priv->old_data_ready = sk->sk_data_ready;
-		priv->old_state_change = sk->sk_state_change;
-		priv->old_write_space = sk->sk_write_space;
-		sk->sk_data_ready = xs_tcp_data_ready;
-		sk->sk_state_change = xs_tcp_state_change;
-		sk->sk_write_space = xs_tcp_write_space;
-
-		xprt_clear_connected(xprt);
-
-		/* Reset to new socket */
-		priv->sock = sock;
-		priv->inet = sk;
-
-		write_unlock_bh(&sk->sk_callback_lock);
-	}
-
-	/* Tell the socket layer to start connecting... */
-	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
-			sizeof(xprt->addr), O_NONBLOCK);
-	dprintk("RPC:       %p connect status %d connected %d sock state %d\n",
-			xprt, -status, xprt_connected(xprt),
-			sock->sk->sk_state);
-	if (status < 0) {
-		switch (status) {
-			case -EINPROGRESS:
-			case -EALREADY:
-				goto out_clear;
-		}
-	}
-
-out:
-	if (status < 0) {
-		xprt->reestablish_timeout <<= 1;
-		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
-			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
-		rpc_wake_up_status(&xprt->pending, status);
-	} else
-		rpc_wake_up(&xprt->pending);
-
-out_clear:
-	smp_mb__before_clear_bit();
-	clear_bit(XPRT_CONNECTING, &xprt->state);
-	smp_mb__after_clear_bit();
-}
-
-/**
- * xs_tcp6_connect_worker - connect a TCP over IPv6 socket to a remote endpoint
- * @args: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_tcp6_connect_worker(void *args)
-{
-	struct rpc_xprt	*xprt = (struct rpc_xprt *)args;
-	struct xs_private *priv = xs_private_data(xprt);
-	struct socket	*sock = priv->sock;
-	int		err, status = -EIO;
-
-	if (xprt->shutdown || !xprt_is_bound(xprt))
-		goto out;
-
-	dprintk("RPC:       xs_tcp6_connect_worker for xprt %p\n", xprt);
-
-	/* Start by resetting any existing state */
-	xs_close(xprt);
-
 	if ((err = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
 		printk(KERN_ERR "RPC: can't create socket (%d).\n", -err);
 		goto out;
 	}
 
-	if (xprt->resvport && xs_bindresvport6(priv, sock) < 0) {
+	if (xprt->resvport && xs_bindresvport(priv, sock) < 0) {
 		printk(KERN_ERR "RPC: can't bind to reserved port.\n");
 		sock_release(sock);
 		goto out;
@@ -1586,24 +1392,8 @@
 static struct rpc_xprt_ops	xs_udp_ops = {
 	.setbufsize	= xs_udp_setbufsize,
 	.is_bound	= xs_is_bound,
-	.bind		= rpc_getport,
-	.set_port	= xs_set_port,
-	.connect	= xs_connect,
-	.buf_alloc	= rpc_malloc,
-	.buf_free	= rpc_free,
-	.send_request	= xs_udp_send_request,
-	.set_receive_timeout	= xs_udp_set_receive_timeout,
-	.is_congested	= xs_udp_is_congested,
-	.timeout	= xs_udp_timeout,
-	.close		= xs_close,
-	.destroy	= xs_destroy,
-};
-
-static struct rpc_xprt_ops	xs_udp6_ops = {
-	.setbufsize	= xs_udp_setbufsize,
-	.is_bound	= xs_is_bound,
 	.bind		= rpc_getport6,
-	.set_port	= xs_set_port6,
+	.set_port	= xs_set_port,
 	.connect	= xs_connect,
 	.buf_alloc	= rpc_malloc,
 	.buf_free	= rpc_free,
@@ -1618,24 +1408,8 @@
 static struct rpc_xprt_ops	xs_tcp_ops = {
 	.setbufsize	= xs_tcp_setbufsize,
 	.is_bound	= xs_is_bound,
-	.bind		= rpc_getport,
-	.set_port	= xs_set_port,
-	.connect	= xs_connect,
-	.buf_alloc	= rpc_malloc,
-	.buf_free	= rpc_free,
-	.send_request	= xs_tcp_send_request,
-	.set_receive_timeout	= xs_tcp_set_receive_timeout,
-	.is_congested   = xs_tcp_is_congested,
-	.timeout	= xs_tcp_timeout,
-	.close		= xs_close,
-	.destroy	= xs_destroy,
-};
-
-static struct rpc_xprt_ops	xs_tcp6_ops = {
-	.setbufsize	= xs_tcp_setbufsize,
-	.is_bound	= xs_is_bound,
 	.bind		= rpc_getport6,
-	.set_port	= xs_set_port6,
+	.set_port	= xs_set_port,
 	.connect	= xs_connect,
 	.buf_alloc	= rpc_malloc,
 	.buf_free	= rpc_free,
@@ -1660,7 +1434,7 @@
 {
 	struct xs_private *priv;
 
-	dprintk("RPC:       setting up udp-ipv4 transport...\n");
+	dprintk("RPC:       setting up udp transport...\n");
 
 	xprt->max_reqs = xprt_udp_slot_table_entries;
 
@@ -1701,56 +1475,6 @@
 }
 
 /**
- * xs_setup_udp6 - Set up transport to use a UDP over IPv6 socket
- * @xprt: transport to set up
- * @to:   timeout parameters
- *
- */
-static int xs_setup_udp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
-{
-	struct xs_private *priv;
-
-	dprintk("RPC:       setting up udp-ipv6 transport...\n");
-
-	xprt->max_reqs = xprt_udp_slot_table_entries;
-
-	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
-	memset(priv, 0, sizeof(struct xs_private));
-	xprt->transport_data = priv;
-
-	xprt->prot = IPPROTO_UDP;
-	priv->port = XS_MAX_RESVPORT;
-	xprt->tsh_size = 0;
-	xprt->cwnd = RPC_INITCWND;
-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-	/* XXX: header size can vary due to auth type, IPv6, etc.
-	 *      so this is a guess.  */
-	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
-
-	INIT_WORK(&priv->sock_connect, xs_udp6_connect_worker, xprt);
-	xprt->bind_timeout = XS_BIND_TO;
-	xprt->connect_timeout = XS_UDP_CONN_TO;
-	xprt->reestablish_timeout = XS_UDP_REEST_TO;
-	xprt->idle_timeout = XS_IDLE_TO;
-
-	xprt->ops = &xs_udp6_ops;
-
-	if (to)
-		xprt->timeout = *to;
-	else
-		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
-
-	if (try_module_get(THIS_MODULE))
-		return 0;
-
-	kfree(priv);
-	xprt->transport_data = NULL;
-	return -EINVAL;
-}
-
-/**
  * xs_setup_tcp - Set up transport to use a TCP over IPv4 socket
  * @xprt: transport to set up
  * @to: timeout parameters
@@ -1760,7 +1484,7 @@
 {
 	struct xs_private *priv;
 
-	dprintk("RPC:       setting up tcp-ipv4 transport...\n");
+	dprintk("RPC:       setting up tcp transport...\n");
 
 	xprt->max_reqs = xprt_tcp_slot_table_entries;
 
@@ -1798,54 +1522,6 @@
 	return -EINVAL;
 }
 
-/**
- * xs_setup_tcp6 - Set up transport to use a TCP over IPv6 socket
- * @xprt: transport to set up
- * @to: timeout parameters
- *
- */
-static int xs_setup_tcp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
-{
-	struct xs_private *priv;
-
-	dprintk("RPC:       setting up tcp-ipv6 transport...\n");
-
-	xprt->max_reqs = xprt_tcp_slot_table_entries;
-
-	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
-	memset(priv, 0, sizeof(struct xs_private));
-	xprt->transport_data = priv;
-
-	xprt->prot = IPPROTO_TCP;
-	priv->port = XS_MAX_RESVPORT;
-	xprt->tsh_size = sizeof(rpc_fraghdr);
-	xprt->cwnd = RPC_MAXCWND(xprt);
-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
-
-	INIT_WORK(&priv->sock_connect, xs_tcp6_connect_worker, xprt);
-	xprt->bind_timeout = XS_BIND_TO;
-	xprt->connect_timeout = XS_TCP_CONN_TO;
-	xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
-	xprt->idle_timeout = XS_IDLE_TO;
-
-	xprt->ops = &xs_tcp6_ops;
-
-	if (to)
-		xprt->timeout = *to;
-	else
-		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
-
-	if (try_module_get(THIS_MODULE))
-		return 0;
-
-	kfree(priv);
-	xprt->transport_data = NULL;
-	return -EINVAL;
-}
-
 static struct xprt_type	xs_udp_type = {
 	.list		= LIST_HEAD_INIT(xs_udp_type.list),
 	.name		= "udp-ipv4",
@@ -1861,7 +1537,7 @@
 	.owner		= THIS_MODULE,
 	.family		= AF_INET6,
 	.protocol	= IPPROTO_UDP,
-	.setup		= xs_setup_udp6,
+	.setup		= xs_setup_udp,
 };
 
 static struct xprt_type	xs_tcp_type = {
@@ -1879,7 +1555,7 @@
 	.owner		= THIS_MODULE,
 	.family		= AF_INET6,
 	.protocol	= IPPROTO_TCP,
-	.setup		= xs_setup_tcp6,
+	.setup		= xs_setup_tcp,
 };
 
 /**
