The complete set of patches combined into one patch, for the support of IPv6
into NFS client.



Signed-off-by: Aurelien Charbon <aurelien.charbon@ext.bull.net>

 fs/lockd/svc.c                 |   10 +-
 fs/lockd/svc4proc.c            |   12 +-
 fs/lockd/svclock.c             |   11 +-
 fs/lockd/svcproc.c             |   12 +-
 fs/nfs/callback.c              |    9 --
 fs/nfs/callback.h              |    4 
 fs/nfs/callback_proc.c         |   10 +-
 fs/nfs/callback_xdr.c          |    4 
 fs/nfs/delegation.c            |    8 +
 fs/nfs/inode.c                 |   58 +++++++-----
 fs/nfs/nfs4_fs.h               |    9 +-
 fs/nfs/nfs4proc.c              |    6 -
 fs/nfs/nfs4state.c             |   34 ++++---
 fs/nfs/nfs4xdr.c               |    9 +-
 fs/nfsd/nfs4state.c            |    4 
 fs/nfsd/nfscache.c             |    2 
 fs/nfsd/nfsfh.c                |   10 +-
 fs/nfsd/nfsproc.c              |    8 -
 include/linux/nfs_fs_sb.h      |    6 -
 include/linux/nfs_ipv6.h       |   83 ++++++++++++++++++
 include/linux/nfs_mount.h      |    6 -
 include/linux/nfs_xdr.h        |    6 -
 include/linux/sunrpc/clnt.h    |   11 ++
 include/linux/sunrpc/svc.h     |   78 ++++++++++++++++-
 include/linux/sunrpc/svcsock.h |    8 +
 net/sunrpc/clnt.c              |    4 
 net/sunrpc/rpcb_clnt.c         |    4 
 net/sunrpc/svc.c               |    2 
 net/sunrpc/svcauth_unix.c      |  102 ++++++++++++++--------
 net/sunrpc/svcsock.c           |  184 +++++++++++++++++++++++++++++------------
 net/sunrpc/xprtsock.c          |   89 +++++++++++++++----
 31 files changed, 593 insertions(+), 210 deletions(-)
--------
diff -Nru linux-2.6.12-CEL/fs/lockd/svc4proc.c linux-2.6.12-08/fs/lockd/svc4proc.c
--- linux-2.6.12-CEL/fs/lockd/svc4proc.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/fs/lockd/svc4proc.c	2005-06-27 16:57:45.000000000 +0200
@@ -416,19 +416,19 @@
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
 
 	struct nlm_host		*host;
+	char			addrbuf[MAX_ADDR_BUF];
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));
+	if (!is_valid_addr((struct sockaddr *)&saddr)) {
+		svc_print_addr((struct sockaddr *)&saddr, addrbuf, sizeof(addrbuf));
 		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 %s\n", addrbuf);
 		return rpc_system_err;
 	}
 
diff -Nru linux-2.6.12-CEL/fs/lockd/svc.c linux-2.6.12-08/fs/lockd/svc.c
--- linux-2.6.12-CEL/fs/lockd/svc.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/lockd/svc.c	2005-06-27 17:06:05.000000000 +0200
@@ -98,8 +98,9 @@
 {
 	struct svc_serv	*serv = rqstp->rq_server;
 	int		err = 0;
-	unsigned long grace_period_expire;
-
+	unsigned long 	grace_period_expire;
+	char		addrbuf[MAX_ADDR_BUF];
+	
 	/* Lock module and set up kernel thread */
 	/* lockd_up is waiting for us to startup, so will
 	 * be holding a reference to this module, so it
@@ -171,8 +172,9 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08x\n",
-			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+			       addrbuf, sizeof(addrbuf));
+		dprintk("lockd: request from %s\n", addrbuf);
 
 		svc_process(serv, rqstp);
 
diff -Nru linux-2.6.12-CEL/fs/lockd/svclock.c linux-2.6.12-08/fs/lockd/svclock.c
--- linux-2.6.12-CEL/fs/lockd/svclock.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/fs/lockd/svclock.c	2005-06-27 17:04:03.000000000 +0200
@@ -604,10 +604,13 @@
 {
 	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);
+	char			addrbuf[MAX_ADDR_BUF];
+	
+	svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+		       addrbuf, sizeof(addrbuf));
+	dprintk("grant_reply: looking for cookie %x, host (%s), s=%d \n", 
+		*(unsigned int *)(cookie->data), addrbuf, status);
+	
 	if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
 		return;
 	file = block->b_file;
diff -Nru linux-2.6.12-CEL/fs/lockd/svcproc.c linux-2.6.12-08/fs/lockd/svcproc.c
--- linux-2.6.12-CEL/fs/lockd/svcproc.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/fs/lockd/svcproc.c	2005-06-27 17:09:43.000000000 +0200
@@ -444,18 +444,18 @@
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
 	struct nlm_host		*host;
+	char			addrbuf[MAX_ADDR_BUF];
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));
+	if (!is_valid_addr((struct sockaddr *)&saddr)) {
+		svc_print_addr((struct sockaddr *)&saddr, addrbuf, sizeof(addrbuf));
 		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 %s\n", addrbuf);
 		return rpc_system_err;
 	}
 
diff -Nru linux-2.6.12-CEL/fs/nfs/callback.c linux-2.6.12-08/fs/nfs/callback.c
--- linux-2.6.12-CEL/fs/nfs/callback.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/callback.c	2005-07-01 16:42:13.000000000 +0200
@@ -64,8 +64,6 @@
 					__FUNCTION__, -err);
 			break;
 		}
-		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
 		svc_process(serv, rqstp);
 	}
 
@@ -94,7 +92,6 @@
 	ret = -ENOMEM;
 	if (!serv)
 		goto out_err;
-	/* FIXME: We don't want to register this socket with the portmapper */
 	ret = svc_makesock(serv, IPPROTO_TCP, 0);
 	if (ret < 0)
 		goto out_destroy;
@@ -142,14 +139,16 @@
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+	struct sockaddr *addr = (struct sockaddr *)&rqstp->rq_addr;
 	struct nfs4_client *clp;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 
 	/* 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));
+	rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR, addr_buf, sizeof(addr_buf));
+	dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__, addr_buf);
 	nfs4_put_client(clp);
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
diff -Nru linux-2.6.12-CEL/fs/nfs/callback.h linux-2.6.12-08/fs/nfs/callback.h
--- linux-2.6.12-CEL/fs/nfs/callback.h	2005-06-17 21:48:29.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/callback.h	2005-06-29 14:55:19.000000000 +0200
@@ -38,7 +38,7 @@
 };
 
 struct cb_getattrargs {
-	struct sockaddr_in *addr;
+	struct sockaddr *addr;
 	struct nfs_fh fh;
 	uint32_t bitmap[2];
 };
@@ -53,7 +53,7 @@
 };
 
 struct cb_recallargs {
-	struct sockaddr_in *addr;
+	struct sockaddr *addr;
 	struct nfs_fh fh;
 	nfs4_stateid stateid;
 	uint32_t truncate;
diff -Nru linux-2.6.12-CEL/fs/nfs/callback_proc.c linux-2.6.12-08/fs/nfs/callback_proc.c
--- linux-2.6.12-CEL/fs/nfs/callback_proc.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/callback_proc.c	2005-06-27 09:49:09.000000000 +0200
@@ -20,12 +20,15 @@
 	struct nfs_delegation *delegation;
 	struct nfs_inode *nfsi;
 	struct inode *inode;
+	char addr_buf[255];
 	
 	res->bitmap[0] = res->bitmap[1] = 0;
 	res->status = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client((struct sockaddr *)args->addr);
 	if (clp == NULL)
 		goto out;
+	rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR, addr_buf, sizeof(addr_buf));
+	dprintk("%s: request from %s\n", __FUNCTION__, addr_buf);
 	inode = nfs_delegation_find_inode(clp, &args->fh);
 	if (inode == NULL)
 		goto out_putclient;
@@ -57,12 +60,15 @@
 {
 	struct nfs4_client *clp;
 	struct inode *inode;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	unsigned res;
 	
 	res = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client((struct sockaddr *)args->addr);
 	if (clp == NULL)
 		goto out;
+	rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR, addr_buf, sizeof(addr_buf));
+	dprintk("%s: request from %s\n", __FUNCTION__, addr_buf);
 	inode = nfs_delegation_find_inode(clp, &args->fh);
 	if (inode == NULL)
 		goto out_putclient;
diff -Nru linux-2.6.12-CEL/fs/nfs/callback_xdr.c linux-2.6.12-08/fs/nfs/callback_xdr.c
--- linux-2.6.12-CEL/fs/nfs/callback_xdr.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/callback_xdr.c	2005-06-29 14:15:43.000000000 +0200
@@ -177,7 +177,7 @@
 	status = decode_fh(xdr, &args->fh);
 	if (unlikely(status != 0))
 		goto out;
-	args->addr = &rqstp->rq_addr;
+	args->addr = (struct sockaddr *)&rqstp->rq_addr;
 	status = decode_bitmap(xdr, args->bitmap);
 out:
 	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -189,7 +189,7 @@
 	uint32_t *p;
 	unsigned status;
 
-	args->addr = &rqstp->rq_addr;
+	args->addr = (struct sockaddr *)&rqstp->rq_addr;
 	status = decode_stateid(xdr, &args->stateid);
 	if (unlikely(status != 0))
 		goto out;
diff -Nru linux-2.6.12-CEL/fs/nfs/delegation.c linux-2.6.12-08/fs/nfs/delegation.c
--- linux-2.6.12-CEL/fs/nfs/delegation.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/delegation.c	2005-06-27 10:15:12.000000000 +0200
@@ -83,6 +83,7 @@
 	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_delegation *delegation;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int status = 0;
 
 	delegation = nfs_alloc_delegation();
@@ -105,8 +106,11 @@
 		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));
+			
+			rpc_peeraddr2str(clp->cl_rpcclient,RPC_DISPLAY_ADDR, addr_buf,
+					   sizeof(addr_buf));
+			printk("%s: server %s, handed out a duplicate delegation!\n",
+					__FUNCTION__, addr_buf);
 			status = -EIO;
 		}
 	}
diff -Nru linux-2.6.12-CEL/fs/nfs/inode.c linux-2.6.12-08/fs/nfs/inode.c
--- linux-2.6.12-CEL/fs/nfs/inode.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/inode.c	2005-06-29 15:15:21.000000000 +0200
@@ -433,8 +433,8 @@
 	struct rpc_create_args args = {
 		.protocol	= ((data->flags & NFS_MOUNT_TCP) ?
 						IPPROTO_TCP : IPPROTO_UDP),
-		.address	= (struct sockaddr *)&server->addr,
-		.addrsize	= sizeof(server->addr),
+		.address	= server->addr,
+		.addrsize	= server->addrlen,
 		.timeout	= &timeparms,
 		.servername	= server->hostname,
 		.program	= &nfs_program,
@@ -1749,9 +1749,7 @@
 	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)
-		return 0;
-	if (old->addr.sin_port != server->addr.sin_port)
+	if (memcmp((void *)&old->addr, (void *)server->addr, server->addrlen))
 		return 0;
 	return !nfs_compare_fh(&old->fh, &server->fh);
 }
@@ -1797,7 +1795,10 @@
 			}
 		case 5:
 			memset(data->context, 0, sizeof(data->context));
-	}
+		case 6:
+			data->addrlen = sizeof(struct sockaddr_in);
+			memcpy(&data->addr, &data->old_addr, sizeof(struct sockaddr_in));
+		}
 #ifndef CONFIG_NFS_V3
 	/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
 	s = ERR_PTR(-EPROTONOSUPPORT);
@@ -1829,12 +1830,14 @@
 	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) {
-		dprintk("%s: mount program didn't pass remote address!\n",
-				__FUNCTION__);
-		goto out_err;
+	server->addrlen = data->addrlen;
+	server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+	if (!server->addr) {
+		kfree(server->addr);
+		kfree(server);
+		return ERR_PTR(-ENOMEM);
 	}
+	memcpy(server->addr, &data->addr, server->addrlen);
 
 	/* Fire up rpciod if not yet running */
 	s = ERR_PTR(rpciod_up());
@@ -1861,6 +1864,7 @@
 out_rpciod_down:
 	rpciod_down();
 out_err:
+	kfree(server->addr);
 	kfree(server);
 	return s;
 }
@@ -2002,8 +2006,8 @@
 
 	server->retrans_timeo = timeparms.to_initval;
 	server->retrans_count = timeparms.to_retries;
-
-	clp = nfs4_get_client(&server->addr.sin_addr);
+	
+	clp = nfs4_get_client(server->addr, server->addrlen);
 	if (!clp) {
 		dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
 		return -EIO;
@@ -2028,8 +2032,8 @@
 	if (IS_ERR(clp->cl_rpcclient)) {
 		struct rpc_create_args args = {
 			.protocol	= data->proto,
-			.address	= (struct sockaddr *)&server->addr,
-			.addrsize	= sizeof(server->addr),
+			.address	= server->addr,
+			.addrsize	= server->addrlen,
 			.timeout	= &timeparms,
 			.servername	= server->hostname,
 			.program	= &nfs_program,
@@ -2186,19 +2190,18 @@
 		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_storage)) {
 		s = ERR_PTR(-EINVAL);
 		goto out_free;
 	}
-	if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
-		s = ERR_PTR(-EFAULT);
+	server->addrlen = data->host_addrlen;
+	server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+	if (!server->addr) {
+		s = ERR_PTR(-ENOMEM);
 		goto out_free;
 	}
-	if (server->addr.sin_family != AF_INET ||
-	    server->addr.sin_addr.s_addr == INADDR_ANY) {
-		dprintk("%s: mount program didn't pass remote IP address!\n",
-				__FUNCTION__);
-		s = ERR_PTR(-EINVAL);
+	if (copy_from_user(server->addr, data->host_addr, server->addrlen)) {
+		s = ERR_PTR(-EFAULT);
 		goto out_free;
 	}
 
@@ -2228,6 +2231,8 @@
 out_err:
 	s = (struct super_block *)p;
 out_free:
+	if (server->addr)
+		kfree(server->addr);
 	if (server->mnt_path)
 		kfree(server->mnt_path);
 	if (server->hostname)
@@ -2254,6 +2259,8 @@
 
 	if (server->hostname != NULL)
 		kfree(server->hostname);
+	if (server->addr != NULL)
+		kfree(server->addr);
 	kfree(server);
 	nfs_release_automount_timer();
 }
@@ -2374,6 +2381,11 @@
 	if (server->hostname == NULL)
 		goto free_server;
 	memcpy(server->hostname, parent->hostname, len);
+	len = parent->addrlen;
+	server->addr = kmalloc(len, GFP_KERNEL);
+	if (server->addr == NULL)
+		goto free_hostname;
+	memcpy(server->addr, parent->addr, len);
 	server->fsid = data->fattr->fsid;
 	nfs_copy_fh(&server->fh, data->fh);
 	server->io_stats = nfs_alloc_iostats();
diff -Nru linux-2.6.12-CEL/fs/nfs/nfs4_fs.h linux-2.6.12-08/fs/nfs/nfs4_fs.h
--- linux-2.6.12-CEL/fs/nfs/nfs4_fs.h	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/nfs4_fs.h	2005-06-29 14:16:50.000000000 +0200
@@ -48,7 +48,8 @@
  */
 struct nfs4_client {
 	struct list_head	cl_servers;	/* Global list of servers */
-	struct in_addr		cl_addr;	/* Server identifier */
+	struct sockaddr	*	cl_addr;	/* Server identifier */
+	size_t			cl_addrlen;
 	u64			cl_clientid;	/* constant */
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
@@ -90,7 +91,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[80];
 	unsigned char		cl_id_uniquifier;
 };
 
@@ -216,10 +217,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 sockaddr *, int);
 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 sockaddr *);
 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.12-CEL/fs/nfs/nfs4proc.c linux-2.6.12-08/fs/nfs/nfs4proc.c
--- linux-2.6.12-CEL/fs/nfs/nfs4proc.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/nfs4proc.c	2005-06-27 10:36:50.000000000 +0200
@@ -2460,6 +2460,7 @@
 		.rpc_cred = clp->cl_cred,
 	};
 	u32 *p;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int loop = 0;
 	int status;
 
@@ -2468,9 +2469,10 @@
 	*p = htonl((u32)clp->cl_boot_time.tv_nsec);
 
 	for(;;) {
+		rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR|RPC_DISPLAY_RAW, addr_buf, sizeof(addr_buf));
 		setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-				sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
-				clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+				sizeof(setclientid.sc_name), "%s/%s %s %u",
+				clp->cl_ipaddr, addr_buf,
 				clp->cl_cred->cr_ops->cr_name,
 				clp->cl_id_uniquifier);
 		setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
diff -Nru linux-2.6.12-CEL/fs/nfs/nfs4state.c linux-2.6.12-08/fs/nfs/nfs4state.c
--- linux-2.6.12-CEL/fs/nfs/nfs4state.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/nfs4state.c	2005-06-27 10:36:08.000000000 +0200
@@ -87,7 +87,7 @@
  * bother putting them in a slab cache...
  */
 static struct nfs4_client *
-nfs4_alloc_client(struct in_addr *addr)
+nfs4_alloc_client(struct sockaddr *addr, int addrlen)
 {
 	struct nfs4_client *clp;
 
@@ -98,7 +98,13 @@
 		return NULL;
 	}
 	memset(clp, 0, sizeof(*clp));
-	memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+	clp->cl_addrlen = addrlen;
+	if ((clp->cl_addr = kmalloc(clp->cl_addrlen, GFP_KERNEL)) == NULL) {
+		kfree(clp);
+		nfs_callback_down();
+		return NULL;
+	}
+	memcpy(clp->cl_addr, addr, clp->cl_addrlen);
 	init_rwsem(&clp->cl_sem);
 	INIT_LIST_HEAD(&clp->cl_delegations);
 	INIT_LIST_HEAD(&clp->cl_state_owners);
@@ -134,11 +140,13 @@
 	nfs_idmap_delete(clp);
 	if (!IS_ERR(clp->cl_rpcclient))
 		rpc_shutdown_client(clp->cl_rpcclient);
+	if (clp->cl_addr)
+		kfree(clp->cl_addr);
 	kfree(clp);
 	nfs_callback_down();
 }
 
-static struct nfs4_client *__nfs4_find_client(struct in_addr *addr)
+static struct nfs4_client *__nfs4_find_client(struct sockaddr *addr)
 {
 	struct nfs4_client *clp;
 	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
@@ -150,7 +158,7 @@
 	return NULL;
 }
 
-struct nfs4_client *nfs4_find_client(struct in_addr *addr)
+struct nfs4_client *nfs4_find_client(struct sockaddr *addr)
 {
 	struct nfs4_client *clp;
 	spin_lock(&state_spinlock);
@@ -160,7 +168,7 @@
 }
 
 struct nfs4_client *
-nfs4_get_client(struct in_addr *addr)
+nfs4_get_client(struct sockaddr *addr, int addrlen)
 {
 	struct nfs4_client *clp, *new = NULL;
 
@@ -176,7 +184,7 @@
 			break;
 		}
 		spin_unlock(&state_spinlock);
-		new = nfs4_alloc_client(addr);
+		new = nfs4_alloc_client(addr, addrlen);
 		spin_lock(&state_spinlock);
 		if (new == NULL)
 			break;
@@ -880,9 +888,11 @@
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
 	struct nfs4_state_recovery_ops *ops;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int status = 0;
 
-	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
+	rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR, addr_buf, sizeof(addr_buf));
+	daemonize("%s-reclaim", addr_buf);
 	allow_signal(SIGKILL);
 
 	atomic_inc(&clp->cl_count);
@@ -940,13 +950,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 with error %d\n",
+			addr_buf, -status);
 	goto out;
 }
-
-/*
- * Local variables:
- *  c-basic-offset: 8
- * End:
- */
diff -Nru linux-2.6.12-CEL/fs/nfs/nfs4xdr.c linux-2.6.12-08/fs/nfs/nfs4xdr.c
--- linux-2.6.12-CEL/fs/nfs/nfs4xdr.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/fs/nfs/nfs4xdr.c	2005-06-29 14:18:04.000000000 +0200
@@ -101,10 +101,11 @@
 #define decode_renew_maxsz	(op_decode_hdr_maxsz)
 #define encode_setclientid_maxsz \
 				(op_encode_hdr_maxsz + \
-				4 /*server->ip_addr*/ + \
-				1 /*Netid*/ + \
-				6 /*uaddr*/ + \
-				6 + (NFS4_VERIFIER_SIZE >> 2))
+				192 /*sc_name*/ + \
+				4 /*Netid*/ + \
+				22 /*uaddr*/ + \
+				2 /*cb_program + cb_ident*/ + \
+				(NFS4_VERIFIER_SIZE >> 2))
 #define decode_setclientid_maxsz \
 				(op_decode_hdr_maxsz + \
 				2 + \
diff -Nru linux-2.6.12-CEL/fs/nfsd/nfs4state.c linux-2.6.12-08/fs/nfsd/nfs4state.c
--- linux-2.6.12-CEL/fs/nfsd/nfs4state.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfsd/nfs4state.c	2005-06-27 17:13:41.000000000 +0200
@@ -666,7 +666,7 @@
 int
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
 {
-	u32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	u32 			ip_addr = ((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr.s_addr;
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -832,7 +832,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;
+	u32 ip_addr = ((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr.s_addr;
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
diff -Nru linux-2.6.12-CEL/fs/nfsd/nfscache.c linux-2.6.12-08/fs/nfsd/nfscache.c
--- linux-2.6.12-CEL/fs/nfsd/nfscache.c	2005-06-17 21:48:29.000000000 +0200
+++ linux-2.6.12-08/fs/nfsd/nfscache.c	2005-06-27 17:24:06.000000000 +0200
@@ -188,7 +188,7 @@
 	rp->c_state = RC_INPROG;
 	rp->c_xid = xid;
 	rp->c_proc = proc;
-	rp->c_addr = rqstp->rq_addr;
+	memcpy(&rp->c_addr, &rqstp->rq_addr, sizeof(struct sockaddr_in));
 	rp->c_prot = proto;
 	rp->c_vers = vers;
 	rp->c_timestamp = jiffies;
diff -Nru linux-2.6.12-CEL/fs/nfsd/nfsfh.c linux-2.6.12-08/fs/nfsd/nfsfh.c
--- linux-2.6.12-CEL/fs/nfsd/nfsfh.c	2005-06-17 21:48:29.000000000 +0200
+++ linux-2.6.12-08/fs/nfsd/nfsfh.c	2005-06-27 17:29:32.000000000 +0200
@@ -117,7 +117,8 @@
 	struct svc_export *exp = NULL;
 	struct dentry	*dentry;
 	u32		error = 0;
-
+	char		addrbuf[MAX_ADDR_BUF];
+	
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
 	/* keep this filehandle for possible reference  when encoding attributes */
@@ -180,10 +181,11 @@
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
+			svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+				       addrbuf, sizeof(addrbuf));
 			printk(KERN_WARNING
-			       "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
-			       NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-			       ntohs(rqstp->rq_addr.sin_port));
+				"nfsd: request from insecure port (%s)!\n",
+			       	addrbuf);
 			goto out;
 		}
 
diff -Nru linux-2.6.12-CEL/fs/nfsd/nfsproc.c linux-2.6.12-08/fs/nfsd/nfsproc.c
--- linux-2.6.12-CEL/fs/nfsd/nfsproc.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/fs/nfsd/nfsproc.c	2005-06-27 17:29:29.000000000 +0200
@@ -117,6 +117,7 @@
 				       struct nfsd_readres  *resp)
 {
 	int	nfserr;
+	char	addrbuf[MAX_ADDR_BUF];
 
 	dprintk("nfsd: READ    %s %d bytes at %d\n",
 		SVCFH_fmt(&argp->fh),
@@ -127,11 +128,10 @@
 	 */
 
 	if (NFSSVC_MAXBLKSIZE < argp->count) {
+		svc_print_addr((struct sockaddr *)&rqstp->rq_addr, addrbuf, sizeof(addrbuf));
 		printk(KERN_NOTICE
-			"oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-				ntohs(rqstp->rq_addr.sin_port),
-				argp->count);
+			"oversized read request from %s (%d bytes)\n",
+				addrbuf, argp->count);
 		argp->count = NFSSVC_MAXBLKSIZE;
 	}
 	svc_reserve(rqstp, (19<<2) + argp->count + 4);
diff -Nru linux-2.6.12-CEL/include/linux/nfs_fs_sb.h linux-2.6.12-08/include/linux/nfs_fs_sb.h
--- linux-2.6.12-CEL/include/linux/nfs_fs_sb.h	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/include/linux/nfs_fs_sb.h	2005-06-29 14:22:15.000000000 +0200
@@ -3,6 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/backing-dev.h>
+#include <linux/types.h>
 
 struct nfs_iostats;
 
@@ -34,14 +35,15 @@
 	unsigned int		namelen;
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
-	struct sockaddr_in	addr;
+	struct sockaddr *	addr;
+	size_t		        addrlen;
 	struct nfs_fsid		fsid;
 	uint32_t		generation;
 #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[80];
 	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.12-CEL/include/linux/nfs_ipv6.h linux-2.6.12-08/include/linux/nfs_ipv6.h
--- linux-2.6.12-CEL/include/linux/nfs_ipv6.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-08/include/linux/nfs_ipv6.h	2005-06-29 13:50:04.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ *  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)
+
+#define IS_ADDR_MAPPED(a) \
+       (((uint32_t *) (a))[0] == 0			\
+	&& ((uint32_t *) (a))[1] == 0			\
+	&& (((uint32_t *) (a))[2] == 0			\
+	    || ((uint32_t *) (a))[2] == htonl(0xffff)))
+
+#endif /* _LINUX_NFS_IPV6_H */
diff -Nru linux-2.6.12-CEL/include/linux/nfs_mount.h linux-2.6.12-08/include/linux/nfs_mount.h
--- linux-2.6.12-CEL/include/linux/nfs_mount.h	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/include/linux/nfs_mount.h	2005-06-27 13:21:54.000000000 +0200
@@ -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 {
@@ -36,13 +36,15 @@
 	int		acregmax;		/* 1 */
 	int		acdirmin;		/* 1 */
 	int		acdirmax;		/* 1 */
-	struct sockaddr_in addr;		/* 1 */
+	struct sockaddr_in old_addr;		/* 1 */
 	char		hostname[256];		/* 1 */
 	int		namlen;			/* 2 */
 	unsigned int	bsize;			/* 3 */
 	struct nfs3_fh	root;			/* 4 */
 	int		pseudoflavor;		/* 5 */
 	char		context[NFS_MAX_CONTEXT_LEN + 1];	/* 6 */
+	unsigned int	addrlen; 		/* 7 */
+	struct sockaddr_storage	addr;		/* 7 */
 };
 
 /* bits in the flags field */
diff -Nru linux-2.6.12-CEL/include/linux/nfs_xdr.h linux-2.6.12-08/include/linux/nfs_xdr.h
--- linux-2.6.12-CEL/include/linux/nfs_xdr.h	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/include/linux/nfs_xdr.h	2005-06-29 14:23:54.000000000 +0200
@@ -640,12 +640,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 */
+	char				sc_netid[12];	  /* request */
 	unsigned int			sc_uaddr_len;
-	char				sc_uaddr[24];     /* request */
+	char				sc_uaddr[80];     /* request */
 	u32				sc_cb_ident;      /* request */
 };
 
diff -Nru linux-2.6.12-CEL/include/linux/sunrpc/clnt.h linux-2.6.12-08/include/linux/sunrpc/clnt.h
--- linux-2.6.12-CEL/include/linux/sunrpc/clnt.h	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/include/linux/sunrpc/clnt.h	2005-06-24 13:34:27.000000000 +0200
@@ -138,6 +138,15 @@
 void		rpc_put_xprt(struct rpc_xprt *xprt);
 
 /*
+ * Values used by rpc_peeraddr2str() to determine the output string format
+ */
+#define RPC_BUF_ADDR_MAX_SIZE	255
+#define ADDR_FMT		0x1
+#define PORT_FMT		0x2
+#define PROTO_FMT		0x4
+#define RAW_FMT			0x80
+
+/*
  * Standard buffer size for converting transport peer addresses to a string.  This
  * shouldn't be too large, as most often this is allocated on the stack.
  */
@@ -152,6 +161,8 @@
 
 #define RPC_DISPLAY_ALL		(RPC_DISPLAY_ADDR|RPC_DISPLAY_PORT|RPC_DISPLAY_PROTO)
 
+#define RPC_DISPLAY_RAW		0x80
+
 static __inline__
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
diff -Nru linux-2.6.12-CEL/include/linux/sunrpc/svc.h linux-2.6.12-08/include/linux/sunrpc/svc.h
--- linux-2.6.12-CEL/include/linux/sunrpc/svc.h	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/include/linux/sunrpc/svc.h	2005-06-28 11:06:29.000000000 +0200
@@ -11,6 +11,7 @@
 #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 +112,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_storage	rq_addr;	/* peer address */
 	int			rq_addrlen;
 
 	struct svc_serv *	rq_server;	/* RPC service definition */
@@ -138,9 +139,12 @@
 	unsigned short
 				rq_secure  : 1;	/* secure port */
 
-
-	__u32			rq_daddr;	/* dest addr of request - reply from here */
-
+	union {
+	    struct in_addr *	in_daddr;
+	    struct in6_addr *	in6_daddr;
+	    void *		daddr;
+	} rq_u_daddr;				/* dest addr of request - reply from here */
+	
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
 	void *			rq_auth_data;	/* flavor-specific data */
@@ -163,6 +167,10 @@
 	wait_queue_head_t	rq_wait;	/* synchronization */
 };
 
+#define rq_in_daddr	rq_u_daddr.in_daddr
+#define rq_in6_daddr	rq_u_daddr.in6_daddr
+#define rq_daddr	rq_u_daddr.daddr
+
 /*
  * Check buffer bounds after decoding arguments
  */
@@ -241,9 +249,69 @@
 	}
 }
 
+static inline u_short svc_get_port(struct sockaddr *sin)
+{
+	u_short port;
+	if (sin->sa_family == AF_INET)
+		port = ((struct sockaddr_in *)sin)->sin_port;
+	else if (sin->sa_family == AF_INET6)
+		port = ((struct sockaddr_in6 *)sin)->sin6_port;
+	else
+		port = 0;
+	return htons(port);
+}
+
+static inline u_short svc_get_addrlen(struct sockaddr *sin)
+{
+	u_short len;
+	if (sin->sa_family == AF_INET)
+		len = sizeof(struct sockaddr_in);
+	else if (sin->sa_family == AF_INET6)
+		len = sizeof(struct sockaddr_in6);
+	else
+		len = 0;
+	return len;
+}
+
+#define MAX_ADDR_BUF		255
+
+static inline void svc_print_addr(struct sockaddr *addr, char *str, size_t len)
+{
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+		snprintf(str, len, "ip = %u.%u.%u.%u port = %d",
+			 NIPQUAD(((struct sockaddr_in *)sin)->sin_addr),
+			 htons(sin->sin_port));
+	} else if (addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr;
+		snprintf(str, len, "ip = %x:%x:%x:%x:%x:%x:%x:%x port = %d",
+			 NIP6(((struct sockaddr_in6 *)sin)->sin6_addr),
+			 htons(sin->sin6_port));
+	}
+}
+
+static inline int is_valid_addr(struct sockaddr *addr)
+{
+	int	valid = 0;
+
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+		valid = (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
+			 ntohs(sin->sin_port) < 1024);
+	} else if (addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr;
+		valid = (sin->sin6_addr.s6_addr32[0] == 0 &&
+			 sin->sin6_addr.s6_addr32[1] == 0 &&
+			 sin->sin6_addr.s6_addr32[2] == 0 &&
+			 sin->sin6_addr.s6_addr32[3] == 1 &&
+			 ntohs(sin->sin6_port) < 1024);
+	}
+	return valid;
+}
+
 struct svc_deferred_req {
 	u32			prot;	/* protocol (UDP or TCP) */
-	struct sockaddr_in	addr;
+	struct sockaddr_storage	addr;
 	struct svc_sock		*svsk;	/* where reply must go */
 	struct cache_deferred_req handle;
 	int			argslen;
diff -Nru linux-2.6.12-CEL/include/linux/sunrpc/svcsock.h linux-2.6.12-08/include/linux/sunrpc/svcsock.h
--- linux-2.6.12-CEL/include/linux/sunrpc/svcsock.h	2005-06-17 21:48:29.000000000 +0200
+++ linux-2.6.12-08/include/linux/sunrpc/svcsock.h	2005-06-29 16:25:03.000000000 +0200
@@ -52,10 +52,18 @@
 	time_t			sk_lastrecv;	/* time of last received request */
 };
 
+ /*
+ * SOCK_PERM flag has been introduced to avoid callback connections to be registered in rpcbind
+ * SOCK_PMAP_REG replaces the pmap_register flag of previous versions
+ */
+#define SOCK_PMAP_REG	0x1
+#define SOCK_PERM	0x2
+
 /*
  * Function prototypes.
  */
 int		svc_makesock(struct svc_serv *, int, unsigned short);
+int		svc_makesock2(struct svc_serv *serv, int protocol, unsigned short port, int pmap_reg);
 void		svc_delete_socket(struct svc_sock *);
 int		svc_recv(struct svc_serv *, struct svc_rqst *, long);
 int		svc_send(struct svc_rqst *);
diff -Nru linux-2.6.12-CEL/net/sunrpc/clnt.c linux-2.6.12-08/net/sunrpc/clnt.c
--- linux-2.6.12-CEL/net/sunrpc/clnt.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/clnt.c	2005-06-29 15:51:14.000000000 +0200
@@ -1022,6 +1022,10 @@
 		/* shutdown or soft timeout */
 		rpc_exit(task, status);
 		break;
+	case -ENOSYS:
+	  	task->tk_action = call_bind;
+	  	task->tk_xprt->bind_index++;
+	  	break;
 	default:
 		printk("%s: RPC call returned error %d\n",
 			       clnt->cl_protname, -status);
diff -Nru linux-2.6.12-CEL/net/sunrpc/rpcb_clnt.c linux-2.6.12-08/net/sunrpc/rpcb_clnt.c
--- linux-2.6.12-CEL/net/sunrpc/rpcb_clnt.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/rpcb_clnt.c	2005-06-29 15:22:13.000000000 +0200
@@ -108,7 +108,7 @@
 	struct rpc_clnt *rpcb_clnt;
 	int error = 0;
 
-	dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local rpcbind\n",
+	printk("RPC:       %sregistering (%u, %u, %d, %u) with local rpcbind\n",
 			(port ? "" : "un"), prog, vers, prot, port);
 
 	sin.sin_family = AF_INET;
@@ -124,7 +124,7 @@
 	if (error < 0)
 		printk(KERN_WARNING "RPC: failed to contact local rpcbind server (errno %d).\n",
 				-error);
-	dprintk("RPC:       registration status %d/%d\n", error, *okay);
+	printk("RPC:       registration status %d/%d\n", error, *okay);
 
 	return error;
 }
diff -Nru linux-2.6.12-CEL/net/sunrpc/svcauth_unix.c linux-2.6.12-08/net/sunrpc/svcauth_unix.c
--- linux-2.6.12-CEL/net/sunrpc/svcauth_unix.c	2005-06-28 16:12:24.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/svcauth_unix.c	2005-06-29 13:50:04.000000000 +0200
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
+#include <linux/nfs_ipv6.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
@@ -91,7 +92,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 +112,20 @@
 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[0] ^
+			    item->m_addr.s6_addr32[1] ^
+			    item->m_addr.s6_addr32[2] ^
+			    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) &&
+	       !memcmp(&tmp->m_addr, &item->m_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,16 +138,16 @@
 				  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);
 
+	if (IS_ADDR_MAPPED(&im->m_addr)) {
+		snprintf(text_addr, 20, "%d.%d.%d.%d",
+			 NIPQUAD(im->m_addr.s6_addr32[3]));
+	} else {
+		snprintf(text_addr, 40, "%x:%x:%x:%x:%x:%x:%x:%x",
+			 NIP6(im->m_addr));
+	}
 	qword_add(bpp, blen, im->m_class);
 	qword_add(bpp, blen, text_addr);
 	(*bpp)[-1] = '\n';
@@ -159,7 +163,7 @@
 	 * for scratch: */
 	char *buf = mesg;
 	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;
@@ -177,9 +181,21 @@
 	len = qword_get(&mesg, buf, mlen);
 	if (len <= 0) return -EINVAL;
 
-	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+	if (sscanf(buf, "%d.%d.%d.%d%c", &b1, &b2, &b3, &b4, &c) == 4) {
+		ipm.m_addr.s6_addr32[0] = 0;
+		ipm.m_addr.s6_addr32[1] = 0;
+		ipm.m_addr.s6_addr32[2] = htonl(0xffff);
+		ipm.m_addr.s6_addr32[3] =
+				htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+	} else if (sscanf(buf, "%x:%x:%x:%x:%x:%x:%x:%x%c",
+			  &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+		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);
+	} else
 		return -EINVAL;
-	
+
 	expiry = get_expiry(&mesg);
 	if (expiry ==0)
 		return -EINVAL;
@@ -195,8 +211,6 @@
 	} else
 		dom = NULL;
 
-	ipm.m_addr.s_addr =
-		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
 	ipm.h.flags = 0;
 	if (dom) {
 		ipm.m_client = container_of(dom, struct unix_domain, h);
@@ -221,7 +235,6 @@
 		       struct cache_head *h)
 {
 	struct ip_map *im;
-	struct in_addr addr;
 	char *dom = "-no-domain-";
 
 	if (h == NULL) {
@@ -230,20 +243,17 @@
 	}
 	im = container_of(h, struct ip_map, h);
 	/* class addr domain */
-	addr = im->m_addr;
-
 	if (test_bit(CACHE_VALID, &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
-		   );
+	if (IS_ADDR_MAPPED(&im->m_addr)) {
+		seq_printf(m, "%s %d.%d.%d.%d %s\n",
+			   im->m_class, NIPQUAD(im->m_addr.s6_addr32[3]), dom);
+	} else {
+		seq_printf(m, "%s %x:%x:%x:%x:%x:%x:%x:%x %s\n",
+			   im->m_class, NIP6(im->m_addr), dom);
+	}
 	return 0;
 }
 	
@@ -260,8 +270,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 +279,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 +294,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 +313,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 +340,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);
@@ -339,7 +364,14 @@
 		return SVC_OK;
 
 	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
-	key.m_addr = rqstp->rq_addr.sin_addr;
+	if (rqstp->rq_addr.ss_family == AF_INET) {
+		map_ipaddr_4to6(&((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr,
+				&key.m_addr);
+	} else if (rqstp->rq_addr.ss_family == AF_INET6) {
+		memcpy(&key.m_addr,
+		       &((struct sockaddr_in6 *)&rqstp->rq_addr)->sin6_addr,
+		       sizeof(struct in6_addr));
+	}
 
 	ipm = ip_map_lookup(&key, 0);
 
diff -Nru linux-2.6.12-CEL/net/sunrpc/svc.c linux-2.6.12-08/net/sunrpc/svc.c
--- linux-2.6.12-CEL/net/sunrpc/svc.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/svc.c	2005-06-27 18:11:00.000000000 +0200
@@ -196,6 +196,8 @@
 	struct svc_serv	*serv = rqstp->rq_server;
 
 	svc_release_buffer(rqstp);
+	if (rqstp->rq_daddr)
+		kfree(rqstp->rq_daddr);
 	if (rqstp->rq_resp)
 		kfree(rqstp->rq_resp);
 	if (rqstp->rq_argp)
diff -Nru linux-2.6.12-CEL/net/sunrpc/svcsock.c linux-2.6.12-08/net/sunrpc/svcsock.c
--- linux-2.6.12-CEL/net/sunrpc/svcsock.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/svcsock.c	2005-06-29 15:35:25.000000000 +0200
@@ -64,7 +64,7 @@
 
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
-					 int *errp, int pmap_reg);
+					 int *errp, int flags);
 static void		svc_udp_data_ready(struct sock *, int);
 static int		svc_udp_recvfrom(struct svc_rqst *);
 static int		svc_udp_sendto(struct svc_rqst *);
@@ -342,6 +342,28 @@
 	spin_unlock_bh(&serv->sv_lock);
 }
 
+static void
+set_ipv4_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
+	cmh->cmsg_level = SOL_IP;
+	cmh->cmsg_type = IP_PKTINFO;
+	pki->ipi_ifindex = 0;
+	pki->ipi_spec_dst.s_addr = rqstp->rq_in_daddr->s_addr;
+	cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+}
+
+static void
+set_ipv6_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	struct in6_pktinfo *pki = (struct in6_pktinfo *)CMSG_DATA(cmh);
+	cmh->cmsg_level = SOL_IPV6;
+	cmh->cmsg_type = IPV6_PKTINFO;
+	pki->ipi6_ifindex = 0;
+	memcpy(&pki->ipi6_addr, rqstp->rq_in6_daddr, sizeof(struct in6_addr));
+	cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+}
+
 /*
  * Generic sendto routine
  */
@@ -351,9 +373,8 @@
 	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);
 	int		len = 0;
 	int		result;
 	int		size;
@@ -361,25 +382,26 @@
 	size_t		base = xdr->page_base;
 	unsigned int	pglen = xdr->page_len;
 	unsigned int	flags = MSG_MORE;
-
+	char		addrbuf[MAX_ADDR_BUF];
 	slen = xdr->len;
 
 	if (rqstp->rq_prot == IPPROTO_UDP) {
 		/* set the source and destination */
 		struct msghdr	msg;
 		msg.msg_name    = &rqstp->rq_addr;
-		msg.msg_namelen = sizeof(rqstp->rq_addr);
+		msg.msg_namelen = rqstp->rq_addrlen;
 		msg.msg_iov     = NULL;
 		msg.msg_iovlen  = 0;
 		msg.msg_flags	= MSG_MORE;
 
 		msg.msg_control = cmh;
 		msg.msg_controllen = sizeof(buffer);
-		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;
+		if (svsk->sk_sk->sk_family == AF_INET)
+			set_ipv4_cmsg_data(rqstp, cmh);
+		else if (svsk->sk_sk->sk_family == AF_INET6)
+			set_ipv6_cmsg_data(rqstp, cmh);
+		else
+			goto out;
 
 		if (sock_sendmsg(sock, &msg, 0) < 0)
 			goto out;
@@ -421,9 +443,10 @@
 			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);
+	svc_print_addr((struct sockaddr *)&rqstp->rq_addr, addrbuf, sizeof(addrbuf));
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (%s)\n",
+			rqstp->rq_sock, xdr->head[0].iov_base,
+			xdr->head[0].iov_len, xdr->len, len, addrbuf);
 
 	return len;
 }
@@ -453,7 +476,7 @@
 {
 	struct msghdr	msg;
 	struct socket	*sock;
-	int		len, alen;
+	int		len;
 
 	rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
 	sock = rqstp->rq_sock->sk_sock;
@@ -471,8 +494,9 @@
 	 * possibly we should cache this in the svc_sock structure
 	 * at accept time. FIXME
 	 */
-	alen = sizeof(rqstp->rq_addr);
-	sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1);
+
+	sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr,
+		&rqstp->rq_addrlen, 1);
 
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
 		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
@@ -601,10 +625,38 @@
 	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;
+
+#define IP6VERSION	6
+	if (*skb->nh.raw == IPVERSION) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)&rqstp->rq_addr;
+		sin->sin_family = AF_INET;
+		sin->sin_port = skb->h.uh->source;
+		sin->sin_addr.s_addr = skb->nh.iph->saddr;
+		if (rqstp->rq_in_daddr == NULL) {
+			skb_free_datagram(svsk->sk_sk, skb);
+			return 0;
+		}
+		rqstp->rq_in_daddr->s_addr = skb->nh.iph->daddr;
+		memcpy(&rqstp->rq_daddr, &skb->nh.iph->daddr,
+		       sizeof(struct in_addr));
+
+	} else if (*skb->nh.raw == IP6VERSION) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&rqstp->rq_addr;
+		sin->sin6_family = AF_INET6;
+		sin->sin6_port = skb->h.uh->source;
+		memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr,
+		       sizeof(struct in6_addr));
+		rqstp->rq_in6_daddr = (struct in6_addr *)kmalloc(sizeof(struct in6_addr), GFP_KERNEL);
+		if (rqstp->rq_in6_daddr == NULL) {
+			skb_free_datagram(svsk->sk_sk, skb);
+			return 0;
+		}
+		memcpy(rqstp->rq_in6_daddr, &skb->nh.ipv6h->daddr,
+		       sizeof(struct in6_addr));
+	} else {
+		skb_free_datagram(svsk->sk_sk, skb);
+		return 0;
+	}
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
@@ -759,20 +811,22 @@
 static void
 svc_tcp_accept(struct svc_sock *svsk)
 {
-	struct sockaddr_in sin;
+	struct sockaddr_storage sin;
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
 	struct proto_ops *ops;
 	struct svc_sock	*newsvsk;
-	int		err, slen;
+	int		err, slen, port;
+	char		addrbuf[MAX_ADDR_BUF];
 
 	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
 	if (!sock)
 		return;
 
-	err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
-	if (err) {
+	err = sock_create_lite(svsk->sk_sk->sk_family, SOCK_STREAM, IPPROTO_TCP,
+			       &newsock);
+		if (err) {
 		if (err == -ENOMEM)
 			printk(KERN_WARNING "%s: no more sockets!\n",
 			       serv->sv_name);
@@ -805,15 +859,15 @@
 	 * 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) {
+	port = svc_get_port((struct sockaddr *)&sin);
+	if (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: %d\n",
+		serv->sv_name, port);
 	}
 
-	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	svc_print_addr((struct sockaddr*)&sin, addrbuf, sizeof(addrbuf));
+	dprintk("%s: connect from %s\n", serv->sv_name, addrbuf);
 
 	/* make sure that a write doesn't block forever when
 	 * low on memory
@@ -846,10 +900,7 @@
 					"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));
+					"%s\n", serv->sv_name, addrbuf);
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
@@ -1142,6 +1193,7 @@
 	int 			pages;
 	struct xdr_buf		*arg;
 	DECLARE_WAITQUEUE(wait, current);
+	unsigned short		port;
 
 	dprintk("svc: server %p waiting for data (to = %ld)\n",
 		rqstp, timeout);
@@ -1258,7 +1310,8 @@
 		spin_unlock_bh(&serv->sv_lock);
 	}
 
-	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+	port = svc_get_port((struct sockaddr *)&rqstp->rq_addr);
+	rqstp->rq_secure = port < 1024;
 	rqstp->rq_chandle.defer = svc_defer;
 
 	if (serv->sv_stats)
@@ -1321,7 +1374,7 @@
  */
 static struct svc_sock *
 svc_setup_socket(struct svc_serv *serv, struct socket *sock,
-					int *errp, int pmap_register)
+					int *errp, int flags)
 {
 	struct svc_sock	*svsk;
 	struct sock	*inet;
@@ -1336,7 +1389,7 @@
 	inet = sock->sk;
 
 	/* Register socket with portmapper */
-	if (*errp >= 0 && pmap_register)
+	if (*errp >= 0 && (flags & SOCK_PMAP_REG))
 		*errp = svc_register(serv, inet->sk_protocol,
 				     ntohs(inet_sk(inet)->sport));
 
@@ -1365,7 +1418,7 @@
 		svc_tcp_init(svsk);
 
 	spin_lock_bh(&serv->sv_lock);
-	if (!pmap_register) {
+	if (!(flags & SOCK_PERM)) {
 		set_bit(SK_TEMP, &svsk->sk_flags);
 		list_add(&svsk->sk_list, &serv->sv_tempsocks);
 		serv->sv_tmpcnt++;
@@ -1387,17 +1440,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 *sin, int pmap_reg)
 {
 	struct svc_sock	*svsk;
 	struct socket	*sock;
 	int		error;
 	int		type;
+	char		addrbuf[MAX_ADDR_BUF];
 
-	dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
-				serv->sv_program->pg_name, protocol,
-				NIPQUAD(sin->sin_addr.s_addr),
-				ntohs(sin->sin_port));
+	svc_print_addr(sin, addrbuf, sizeof(addrbuf));
+	dprintk("svc: svc_create_socket(%s, %d, %s)\n",
+		serv->sv_program->pg_name, protocol, addrbuf);
 
 	if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1406,14 +1459,14 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+	if ((error = sock_create_kern(sin->sa_family, type, protocol,
+			&sock)) < 0)
 		return error;
 
 	if (sin != NULL) {
 		if (type == SOCK_STREAM)
 			sock->sk->sk_reuse = 1; /* allow address reuse */
-		error = sock->ops->bind(sock, (struct sockaddr *) sin,
-						sizeof(*sin));
+		error = sock->ops->bind(sock, sin, svc_get_addrlen(sin));
 		if (error < 0)
 			goto bummer;
 	}
@@ -1422,8 +1475,8 @@
 		if ((error = sock->ops->listen(sock, 64)) < 0)
 			goto bummer;
 	}
-
-	if ((svsk = svc_setup_socket(serv, sock, &error, 1)) != NULL)
+	
+	if ((svsk = svc_setup_socket(serv, sock, &error, pmap_reg | SOCK_PERM)) != NULL)
 		return 0;
 
 bummer:
@@ -1481,8 +1534,37 @@
 	sin.sin_family      = AF_INET;
 	sin.sin_addr.s_addr = INADDR_ANY;
 	sin.sin_port        = htons(port);
-	return svc_create_socket(serv, protocol, &sin);
+	return svc_create_socket(serv, protocol, (struct sockaddr *)&sin, 1);
+}
+
+ /*
+ * Make a socket for nfs callback (will be then used by nfsd and lockd)
+ */
+int
+svc_makesock2(struct svc_serv *serv, int protocol, unsigned short port,
+	      int pmap_reg)
+{
+	struct sockaddr_in6     sin6;
+	struct sockaddr_in	sin;
+	int ret;
+
+	dprintk("svc: creating socket proto = %d\n", protocol);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	memset(&sin6, '\0', sizeof(struct sockaddr_in6));
+	sin6.sin6_family    = AF_INET6;
+	sin6.sin6_port      = htons(port);
+	ret = svc_create_socket(serv, protocol, (struct sockaddr *)&sin6,
+				pmap_reg);
+	if (ret)
+		return ret;
+#endif
+	sin.sin_family      = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port        = htons(port);
+	return svc_create_socket(serv, protocol, (struct sockaddr *)&sin,
+				 pmap_reg);
 }
+EXPORT_SYMBOL(svc_makesock2);
 
 /*
  * Handle defer and revisit of requests 
@@ -1531,7 +1613,7 @@
 
 		dr->handle.owner = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
-		dr->addr = rqstp->rq_addr;
+		memcpy(&dr->addr, &rqstp->rq_addr, sizeof(struct sockaddr_storage));
 		dr->argslen = rqstp->rq_arg.len >> 2;
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
 	}
@@ -1556,7 +1638,7 @@
 	rqstp->rq_arg.page_len = 0;
 	rqstp->rq_arg.len = dr->argslen<<2;
 	rqstp->rq_prot        = dr->prot;
-	rqstp->rq_addr        = dr->addr;
+	memcpy(&rqstp->rq_addr, &dr->addr, sizeof(struct sockaddr_storage));
 	return dr->argslen<<2;
 }
 
diff -Nru linux-2.6.12-CEL/net/sunrpc/xprtsock.c linux-2.6.12-08/net/sunrpc/xprtsock.c
--- linux-2.6.12-CEL/net/sunrpc/xprtsock.c	2005-06-28 16:12:36.000000000 +0200
+++ linux-2.6.12-08/net/sunrpc/xprtsock.c	2005-06-27 13:41:04.000000000 +0200
@@ -1046,17 +1046,32 @@
 	size_t result;
 
 	if (format & RPC_DISPLAY_ADDR) {
-		result = snprintf(buffer, size, "ip=\"%u.%u.%u.%u\"",
-					NIPQUAD(addr->sin_addr.s_addr));
-		buffer += result;
-		size -= result;
+		if (format & RPC_DISPLAY_RAW) {
+			result = snprintf(buffer, size, "ip=\"%u.%u.%u.%u\"",
+						NIPQUAD(addr->sin_addr.s_addr));
+			buffer += result;
+			size -= result;
+		} else {
+			result = snprintf(buffer, size, "%u.%u.%u.%u",
+						NIPQUAD(addr->sin_addr.s_addr));
+			buffer += result;
+			size -= result;
+			}
 	}
 	if (format & RPC_DISPLAY_PORT) {
-		result = snprintf(buffer, size, " port=\"%u\"",
+		if (format & RPC_DISPLAY_RAW) {
+			result = snprintf(buffer, size, " port=\"%u\"",
+						ntohs(addr->sin_port));
+			buffer += result;
+			size -= result;
+		} else {
+			result = snprintf(buffer, size, "%u",
 					ntohs(addr->sin_port));
-		buffer += result;
-		size -= result;
+			buffer += result;
+			size -= result;
+			}
 	}
+	
 	if (format & RPC_DISPLAY_PROTO)
 		result = snprintf(buffer, size, " proto=\"%s\"",
 					xprt->prot == IPPROTO_TCP ? "tcp" : "udp");
@@ -1077,20 +1092,40 @@
 	size_t result;
 
 	if (format & RPC_DISPLAY_ADDR) {
-		result = snprintf(buffer, size, "ip=\"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\"",
-					NIP6(addr->sin6_addr));
-		buffer += result;
-		size -= result;
+		if (format & RPC_DISPLAY_RAW) {
+			result = snprintf(buffer, size, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+						NIP6(addr->sin6_addr));
+			buffer += result;
+			size -= result;
+		} else {
+			result = snprintf(buffer, size, "ip=\"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\"",
+						NIP6(addr->sin6_addr));
+			buffer += result;
+			size -= result;
+		}
 	}
 	if (format & RPC_DISPLAY_PORT) {
-		result = snprintf(buffer, size, " port=\"%u\"",
-					ntohs(addr->sin6_port));
-		buffer += result;
-		size -= result;
+		if (format & RPC_DISPLAY_RAW) {
+			result = snprintf(buffer, size, " port=\"%u\"",
+						ntohs(addr->sin6_port));
+			buffer += result;
+			size -= result;
+		} else {
+			result = snprintf(buffer, size, "%u",
+						ntohs(addr->sin6_port));
+			buffer += result;
+			size -= result;
+		}
+	}
+	if (format & RPC_DISPLAY_PROTO) {
+		if (format & RPC_DISPLAY_RAW) {
+			result = snprintf(buffer, size, "%s",
+						xprt->prot == IPPROTO_TCP ? "tcp" : "udp");
+		} else {
+			result = snprintf(buffer, size, " proto=\"%s\"",
+						xprt->prot == IPPROTO_TCP ? "tcp" : "udp");
+		}
 	}
-	if (format & RPC_DISPLAY_PROTO)
-		result = snprintf(buffer, size, " proto=\"%s\"",
-					xprt->prot == IPPROTO_TCP ? "tcp" : "udp");
 }
 #endif
 
@@ -1665,12 +1700,16 @@
  */
 static int xs_setup_udp4(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
 	struct xs_private *priv;
 	char buf[RPC_MAX_ADDRBUFLEN];
 
 	xs_print_ipv4_address(xprt, RPC_DISPLAY_ALL, buf, sizeof(buf));
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (sap->sin_addr.s_addr == INADDR_ANY)
+		return -EINVAL;
+
   	priv = xs_alloc_private();
   	if (priv == NULL)
   		return -ENOMEM;
@@ -1696,12 +1735,17 @@
  */
 static int xs_setup_udp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct in6_addr *addr = &((struct sockaddr_in6 *)&xprt->addr)->sin6_addr;
 	struct xs_private *priv;
 	char buf[RPC_MAX_ADDRBUFLEN];
 
 	xs_print_ipv6_address(xprt, RPC_DISPLAY_ALL, buf, sizeof(buf));
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (addr->s6_addr32[0] == 0 && addr->s6_addr32[1] == 0 &&
+	    addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0)
+		return -EINVAL;
+
   	priv = xs_alloc_private();
   	if (priv == NULL)
   		return -ENOMEM;
@@ -1749,12 +1793,16 @@
  */
 static int xs_setup_tcp4(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
 	struct xs_private *priv;
 	char buf[RPC_MAX_ADDRBUFLEN];
 
 	xs_print_ipv4_address(xprt, RPC_DISPLAY_ALL, buf, sizeof(buf));
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (sap->sin_addr.s_addr == INADDR_ANY)
+		return -EINVAL;
+
   	priv = xs_alloc_private();
   	if (priv == NULL)
   		return -ENOMEM;
@@ -1780,12 +1828,17 @@
  */
 static int xs_setup_tcp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct in6_addr *addr = &((struct sockaddr_in6 *)&xprt->addr)->sin6_addr;
 	struct xs_private *priv;
 	char buf[RPC_MAX_ADDRBUFLEN];
 
 	xs_print_ipv6_address(xprt, RPC_DISPLAY_ALL, buf, sizeof(buf));
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (addr->s6_addr32[0] == 0 && addr->s6_addr32[1] == 0 &&
+	    addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0)
+		return -EINVAL;
+
   	priv = xs_alloc_private();
   	if (priv == NULL)
   		return -ENOMEM;

