Change the address fields in svc_rqst from sockaddr_in to sockaddr_storage to be
transport independant.

NB: this patch is also available in separated smaller patches


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

 fs/lockd/svc.c             |    8 +-
 fs/lockd/svc4proc.c        |   13 +---
 fs/lockd/svclock.c         |    8 +-
 fs/lockd/svcproc.c         |   12 +--
 fs/nfsd/nfs4state.c        |    4 -
 fs/nfsd/nfscache.c         |    2 
 fs/nfsd/nfsfh.c            |    8 +-
 fs/nfsd/nfsproc.c          |    8 +-
 include/linux/sunrpc/svc.h |   77 +++++++++++++++++++++++--
 net/sunrpc/svc.c           |    2 
 net/sunrpc/svcauth_unix.c  |    2 
 net/sunrpc/svcsock.c       |  138 ++++++++++++++++++++++++++++++---------------
 12 files changed, 205 insertions(+), 77 deletions(-)
--------
diff -Nru linux-2.6.11-05/fs/lockd/svc4proc.c linux-2.6.11-06/fs/lockd/svc4proc.c
--- linux-2.6.11-05/fs/lockd/svc4proc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-06/fs/lockd/svc4proc.c	2005-04-04 15:43:37.000000000 +0200
@@ -416,19 +416,18 @@
 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.11-05/fs/lockd/svc.c linux-2.6.11-06/fs/lockd/svc.c
--- linux-2.6.11-05/fs/lockd/svc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-06/fs/lockd/svc.c	2005-04-04 15:43:37.000000000 +0200
@@ -97,7 +97,8 @@
 {
 	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
@@ -169,8 +170,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.11-05/fs/lockd/svclock.c linux-2.6.11-06/fs/lockd/svclock.c
--- linux-2.6.11-05/fs/lockd/svclock.c	2005-04-04 13:37:13.000000000 +0200
+++ linux-2.6.11-06/fs/lockd/svclock.c	2005-04-04 15:43:37.000000000 +0200
@@ -629,10 +629,12 @@
 {
 	struct nlm_block	*block;
 	struct nlm_file		*file;
+	char			addrbuf[MAX_ADDR_BUF];
 
-	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);
+	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.11-05/fs/lockd/svcproc.c linux-2.6.11-06/fs/lockd/svcproc.c
--- linux-2.6.11-05/fs/lockd/svcproc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-06/fs/lockd/svcproc.c	2005-04-04 15:43:37.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.11-05/fs/nfsd/nfs4state.c linux-2.6.11-06/fs/nfsd/nfs4state.c
--- linux-2.6.11-05/fs/nfsd/nfs4state.c	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-06/fs/nfsd/nfs4state.c	2005-04-04 15:43:37.000000000 +0200
@@ -639,7 +639,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,
@@ -820,7 +820,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 *clp, *conf = NULL, *unconf = NULL;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
diff -Nru linux-2.6.11-05/fs/nfsd/nfscache.c linux-2.6.11-06/fs/nfsd/nfscache.c
--- linux-2.6.11-05/fs/nfsd/nfscache.c	2005-03-02 08:38:33.000000000 +0100
+++ linux-2.6.11-06/fs/nfsd/nfscache.c	2005-04-04 15:43:37.000000000 +0200
@@ -233,7 +233,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.11-05/fs/nfsd/nfsfh.c linux-2.6.11-06/fs/nfsd/nfsfh.c
--- linux-2.6.11-05/fs/nfsd/nfsfh.c	2005-03-02 08:38:00.000000000 +0100
+++ linux-2.6.11-06/fs/nfsd/nfsfh.c	2005-04-04 15:43:37.000000000 +0200
@@ -117,6 +117,7 @@
 	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));
 
@@ -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.11-05/fs/nfsd/nfsproc.c linux-2.6.11-06/fs/nfsd/nfsproc.c
--- linux-2.6.11-05/fs/nfsd/nfsproc.c	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-06/fs/nfsd/nfsproc.c	2005-04-04 15:43:37.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.11-05/include/linux/sunrpc/svc.h linux-2.6.11-06/include/linux/sunrpc/svc.h
--- linux-2.6.11-05/include/linux/sunrpc/svc.h	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-06/include/linux/sunrpc/svc.h	2005-04-05 16:38:50.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,8 +139,11 @@
 	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 */
@@ -162,6 +166,9 @@
 
 	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
@@ -230,9 +237,71 @@
 	}
 }
 
+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.11-05/net/sunrpc/svcauth_unix.c linux-2.6.11-06/net/sunrpc/svcauth_unix.c
--- linux-2.6.11-05/net/sunrpc/svcauth_unix.c	2005-03-22 17:02:01.000000000 +0100
+++ linux-2.6.11-06/net/sunrpc/svcauth_unix.c	2005-04-04 15:43:37.000000000 +0200
@@ -339,7 +339,7 @@
 		return SVC_OK;
 
 	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
-	key.m_addr = rqstp->rq_addr.sin_addr;
+	key.m_addr = ((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr;
 
 	ipm = ip_map_lookup(&key, 0);
 
diff -Nru linux-2.6.11-05/net/sunrpc/svc.c linux-2.6.11-06/net/sunrpc/svc.c
--- linux-2.6.11-05/net/sunrpc/svc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-06/net/sunrpc/svc.c	2005-04-04 15:43:37.000000000 +0200
@@ -194,6 +194,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.11-05/net/sunrpc/svcsock.c linux-2.6.11-06/net/sunrpc/svcsock.c
--- linux-2.6.11-05/net/sunrpc/svcsock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-06/net/sunrpc/svcsock.c	2005-04-05 16:36:59.000000000 +0200
@@ -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,6 +382,7 @@
 	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;
 
@@ -368,18 +390,19 @@
 		/* 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 +444,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 +477,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 +495,8 @@
 	 * 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,37 @@
 	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;
+		rqstp->rq_in_daddr = (struct in_addr *)kmalloc(sizeof(struct in_addr), GFP_KERNEL);
+		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,19 +810,21 @@
 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);
+	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",
@@ -805,15 +858,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 +899,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 +1192,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);
@@ -1257,7 +1308,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)
@@ -1386,17 +1438,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)
 {
 	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 "
@@ -1405,14 +1457,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;
 	}
@@ -1480,7 +1532,7 @@
 	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);
 }
 
 /*
@@ -1530,7 +1582,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);
 	}
@@ -1555,7 +1607,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;
 }
 

