Add the support of IPv6 in the authentication part of the sunrpc.

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

diff -Nru linux-2.6.9-cel5-gq-01/include/linux/sunrpc/svcauth.h linux-2.6.9-cel5-gq-02/include/linux/sunrpc/svcauth.h
--- linux-2.6.9-cel5-gq-01/include/linux/sunrpc/svcauth.h	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-02/include/linux/sunrpc/svcauth.h	2005-01-21 17:05:29.000000000 +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-gq-01/net/sunrpc/sunrpc_syms.c linux-2.6.9-cel5-gq-02/net/sunrpc/sunrpc_syms.c
--- linux-2.6.9-cel5-gq-01/net/sunrpc/sunrpc_syms.c	2004-12-13 14:36:38.000000000 +0100
+++ linux-2.6.9-cel5-gq-02/net/sunrpc/sunrpc_syms.c	2005-01-21 17:05:29.000000000 +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-gq-01/net/sunrpc/svcauth_unix.c linux-2.6.9-cel5-gq-02/net/sunrpc/svcauth_unix.c
--- linux-2.6.9-cel5-gq-01/net/sunrpc/svcauth_unix.c	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-02/net/sunrpc/svcauth_unix.c	2005-01-24 14:01:50.000000000 +0100
@@ -8,6 +8,8 @@
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
+#include <linux/in6.h>
+#include <linux/ipv6.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
@@ -41,10 +43,13 @@
 
 	ud.name = name;
 	
+	dprintk("unix_domain_find: name = %s\n", name);
 	rv = auth_domain_lookup(&ud, 0);
+	dprintk("unix_domain_find: return from auth_domain_lookup = %x, domain %s found\n", rv, rv ? "" : "not");
 
  foundit:
 	if (rv && rv->flavour != RPC_AUTH_UNIX) {
+		dprintk("unix_domain_find: rv->flavour (%d) != RPC_AUTH_UNIX)\n", rv->flavour);
 		auth_domain_put(rv);
 		return NULL;
 	}
@@ -61,9 +66,12 @@
 	new->h.h.expiry_time = NEVER;
 
 	rv = auth_domain_lookup(&new->h, 2);
+	dprintk("unix_domain_find: return from auth_domain_lookup (2) = %x, domain %s found\n", rv, rv ? "" : "not");
 	if (rv == &new->h) {
+		dprintk("unix_domain_find: call atomic_dec_and_test()\n");
 		if (atomic_dec_and_test(&new->h.h.refcnt)) BUG();
 	} else {
+		dprintk("unix_domain_find: call auth_domain_put()\n");
 		auth_domain_put(&new->h);
 		goto foundit;
 	}
@@ -91,7 +99,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;
 };
@@ -103,6 +111,7 @@
 	if (cache_put(item, cd)) {
 		if (test_bit(CACHE_VALID, &item->flags) &&
 		    !test_bit(CACHE_NEGATIVE, &item->flags))
+			dprintk("ip_map_put: call auth_domain_put()\n");
 			auth_domain_put(&im->m_client->h);
 		kfree(im);
 	}
@@ -111,17 +120,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 +144,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 +161,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 +181,9 @@
 	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)
+	dprintk("ip_map_parse: addr buf = %s\n", buf);
+	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);
@@ -185,27 +192,34 @@
 
 	/* domainname, or empty for NEGATIVE */
 	len = qword_get(&mesg, buf, 50);
+	dprintk("ip_map_parse: domain buf = %s\n", buf);
 	if (len < 0) return -EINVAL;
 
 	if (len) {
 		dom = unix_domain_find(buf);
+		dprintk("ip_map_parse: call unix_domain_find() , dom = %x\n", dom);
 		if (dom == NULL)
 			return -ENOENT;
 	} else
 		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);
 		ipm.m_add_change = ipm.m_client->addr_changes;
-	} else
+	} else {
+	    	dprintk("ip_map_parse: dom NULL !!!!\n");
 		set_bit(CACHE_NEGATIVE, &ipm.h.flags);
+	}
 	ipm.h.expiry_time = expiry;
 
 	ipmp = ip_map_lookup(&ipm, 1);
+	dprintk("ip_map_parse: call ip_map_lookup(), ipmp = %x => ipmap %s found\n", ipmp, ipmp ? "" : "not");
 	if (ipmp)
 		ip_map_put(&ipmp->h, &ip_map_cache);
 	if (dom)
@@ -221,7 +235,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 +244,15 @@
 	}
 	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;
+	dprintk("ip_map_show: dom = %s\n", dom);
 
-	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 +269,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 +278,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 +293,18 @@
 		return -ENOMEM;
 }
 
+int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+{
+	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;
+
+	return auth_unix_add_addr6(&addr6, dom);
+}
+
 int auth_unix_forget_old(struct auth_domain *dom)
 {
 	struct unix_domain *udom;
@@ -296,13 +316,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 +343,18 @@
 	return rv;
 }
 
+struct auth_domain *auth_unix_lookup(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;
+
+	return auth_unix_lookup6(&addr6);
+}
+
 void svcauth_unix_purge(void)
 {
 	cache_purge(&ip_map_cache);
@@ -335,7 +367,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);
 
@@ -370,6 +403,7 @@
 	cred->cr_group_info = NULL;
 	rqstp->rq_client = NULL;
 
+	dprintk("svcauth_null_accept:\n");
 	if (argv->iov_len < 3*4)
 		return SVC_GARBAGE;
 
@@ -448,6 +482,7 @@
 	svc_getu32(argv);			/* length */
 	svc_getu32(argv);			/* time stamp */
 	slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));	/* machname length */
+	dprintk("svcauth_unix_accept: svc slen = %d\n", slen);
 	if (slen > 64 || (len -= (slen + 3)*4) < 0)
 		goto badcred;
 	argv->iov_base = (void*)((u32*)argv->iov_base + slen);	/* skip machname */
@@ -456,6 +491,7 @@
 	cred->cr_uid = ntohl(svc_getu32(argv));		/* uid */
 	cred->cr_gid = ntohl(svc_getu32(argv));		/* gid */
 	slen = ntohl(svc_getu32(argv));			/* gids length */
+	dprintk("svcauth_unix_accept: cred slen = %d\n", slen);
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
 	cred->cr_group_info = groups_alloc(slen);
