Netdev List
 help / color / mirror / Atom feed
* [PATCH 2/2] NFS: handle IPv6 addresses in nfs ctl
From: Aurélien Charbon @ 2007-10-12  9:14 UTC (permalink / raw)
  To: Mailing list NFSv4, netdev ML

[-- Attachment #1: Type: text/plain, Size: 4206 bytes --]

Here is a second missing part of the IPv6 support in NFS server code 
concerning knfd syscall interface.
It updates write_getfd and write_getfd to accept IPv6 addresses.

Applies on a kernel including ip_map cache modifications

Tests: tested with only IPv4 network and basic nfs ops (mount, file creation and modification) 


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

 nfsctl.c |   41 ++++++++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff -p -u -r -N linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c 
linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c
--- linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c    2007-10-11 
15:23:07.000000000 +0200
+++ linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c    2007-10-12 
10:49:31.000000000 +0200
@@ -219,7 +219,7 @@ static ssize_t write_unexport(struct fil
 static ssize_t write_getfs(struct file *file, char *buf, size_t size)
 {
     struct nfsctl_fsparm *data;
-    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin, sin6_storage;
     struct auth_domain *clp;
     int err = 0;
     struct knfsd_fh *res;
@@ -228,9 +228,20 @@ static ssize_t write_getfs(struct file *
         return -EINVAL;
     data = (struct nfsctl_fsparm*)buf;
     err = -EPROTONOSUPPORT;
-    if (data->gd_addr.sa_family != AF_INET)
+    sin = &sin6_storage;
+    switch (data->gd_addr.sa_family) {
+    case AF_INET6:
+        sin = (struct sockaddr_in6 *)&data->gd_addr;
+        in6 = sin->sin6_addr;
+        break;
+    case AF_INET:
+        /* Map v4 address into v6 structure */
+        ipv6_addr_v4map(((struct sockaddr_in 
*)&data->gd_addr)->sin_addr, in6);
+        break;
+    default:
         goto out;
-    sin = (struct sockaddr_in *)&data->gd_addr;
+    }
+
     if (data->gd_maxlen > NFS3_FHSIZE)
         data->gd_maxlen = NFS3_FHSIZE;
 
@@ -238,9 +249,6 @@ static ssize_t write_getfs(struct file *
 
     exp_readlock();
 
-    /* IPv6 address mapping */
-    ipv6_addr_v4map(sin->sin_addr, in6);
-
     if (!(clp = auth_unix_lookup(in6)))
         err = -EPERM;
     else {
@@ -257,7 +265,7 @@ static ssize_t write_getfs(struct file *
 static ssize_t write_getfd(struct file *file, char *buf, size_t size)
 {
     struct nfsctl_fdparm *data;
-    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin, sin6_storage;
     struct in6_addr in6;
     struct auth_domain *clp;
     int err = 0;
@@ -268,18 +276,29 @@ static ssize_t write_getfd(struct file *
         return -EINVAL;
     data = (struct nfsctl_fdparm*)buf;
     err = -EPROTONOSUPPORT;
-    if (data->gd_addr.sa_family != AF_INET)
+    if (data->gd_addr.sa_family != AF_INET &&
+        data->gd_addr.sa_family != AF_INET6)
         goto out;
     err = -EINVAL;
     if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
         goto out;
 
     res = buf;
-    sin = (struct sockaddr_in *)&data->gd_addr;
+    sin = &sin6_storage;
     exp_readlock();
 
-    /* IPv6 address mapping */
-    ipv6_addr_v4map(sin->sin_addr, in6);
+    switch (data->gd_addr.sa_family) {
+    case AF_INET:
+        /* IPv6 address mapping */
+        ipv6_addr_v4map(((struct sockaddr_in 
*)&data->gd_addr)->sin_addr, in6);
+        break;
+    case AF_INET6:
+        sin = (struct sockaddr_in6 *)&data->gd_addr;
+        in6 = sin->sin6_addr;
+        break;
+    default:
+        BUG();
+    }
 
     if (!(clp = auth_unix_lookup(in6)))
         err = -EPERM;
diff -p -u -r -N linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c 
linux-2.6.23-nfsctl/net/sunrpc/svcauth_unix.c
--- linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c    2007-10-12 
10:47:27.000000000 +0200
+++ linux-2.6.23-nfsctl/net/sunrpc/svcauth_unix.c    2007-10-12 
10:03:56.000000000 +0200
@@ -677,7 +677,7 @@ svcauth_unix_set_client(struct svc_rqst
     case AF_INET:
         sin = svc_addr_in(rqstp);
         sin6 = &sin6_storage;
-        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
+        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
                 htonl(0x0000FFFF), sin->sin_addr.s_addr);
         break;
     case AF_INET6:

-- 

********************************
       Aurelien Charbon
           Bull SAS
     Echirolles - France
 http://www.bullopensource.org/
********************************


[-- Attachment #2: linux-2.6.23-nfsctl.diff --]
[-- Type: text/x-patch, Size: 2612 bytes --]

diff -p -u -r -N linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c
--- linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c	2007-10-11 15:23:07.000000000 +0200
+++ linux-2.6.23-nfsctl/fs/nfsd/nfsctl.c	2007-10-12 10:49:31.000000000 +0200
@@ -219,7 +219,7 @@ static ssize_t write_unexport(struct fil
 static ssize_t write_getfs(struct file *file, char *buf, size_t size)
 {
 	struct nfsctl_fsparm *data;
-	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin, sin6_storage;
 	struct auth_domain *clp;
 	int err = 0;
 	struct knfsd_fh *res;
@@ -228,9 +228,20 @@ static ssize_t write_getfs(struct file *
 		return -EINVAL;
 	data = (struct nfsctl_fsparm*)buf;
 	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
+	sin = &sin6_storage;
+	switch (data->gd_addr.sa_family) {
+	case AF_INET6:
+		sin = (struct sockaddr_in6 *)&data->gd_addr;
+		in6 = sin->sin6_addr;
+		break;
+	case AF_INET:
+		/* Map v4 address into v6 structure */
+		ipv6_addr_v4map(((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
+		break;
+	default:
 		goto out;
-	sin = (struct sockaddr_in *)&data->gd_addr;
+	}
+
 	if (data->gd_maxlen > NFS3_FHSIZE)
 		data->gd_maxlen = NFS3_FHSIZE;
 
@@ -238,9 +249,6 @@ static ssize_t write_getfs(struct file *
 
 	exp_readlock();
 
-	/* IPv6 address mapping */
-	ipv6_addr_v4map(sin->sin_addr, in6);
-
 	if (!(clp = auth_unix_lookup(in6)))
 		err = -EPERM;
 	else {
@@ -257,7 +265,7 @@ static ssize_t write_getfs(struct file *
 static ssize_t write_getfd(struct file *file, char *buf, size_t size)
 {
 	struct nfsctl_fdparm *data;
-	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin, sin6_storage;
 	struct in6_addr in6;
 	struct auth_domain *clp;
 	int err = 0;
@@ -268,18 +276,29 @@ static ssize_t write_getfd(struct file *
 		return -EINVAL;
 	data = (struct nfsctl_fdparm*)buf;
 	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
+	if (data->gd_addr.sa_family != AF_INET && 
+		data->gd_addr.sa_family != AF_INET6)
 		goto out;
 	err = -EINVAL;
 	if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
 		goto out;
 
 	res = buf;
-	sin = (struct sockaddr_in *)&data->gd_addr;
+	sin = &sin6_storage;
 	exp_readlock();
 
-	/* IPv6 address mapping */
-	ipv6_addr_v4map(sin->sin_addr, in6);
+	switch (data->gd_addr.sa_family) {
+	case AF_INET:
+		/* IPv6 address mapping */
+		ipv6_addr_v4map(((struct sockaddr_in *)&data->gd_addr)->sin_addr, in6);
+		break;
+	case AF_INET6:
+		sin = (struct sockaddr_in6 *)&data->gd_addr;
+		in6 = sin->sin6_addr;
+		break;
+	default:
+		BUG();
+	}
 
 	if (!(clp = auth_unix_lookup(in6)))
 		err = -EPERM;


^ permalink raw reply

* [PATCH 1/2] NFS: change the ip_map cache code to handle IPv6 addresses
From: Aurélien Charbon @ 2007-10-12  9:14 UTC (permalink / raw)
  To: Mailing list NFSv4, netdev ML

[-- Attachment #1: Type: text/plain, Size: 15085 bytes --]

Here is a patch for the ip_map caching code part in nfs server.
I have updated the code to use Brian 
Haley's ipv6_addr_v4mapped function, and corrected pointed out mistakes.
So the first patch in attachment must be applied on a vanilla kernel 
before to include IPv4 mapping functions that are used.

In case of bad formatting due to my mailer, you can also find the patch 
in attachment.

Tests: tested with only IPv4 network and basic nfs ops (mount, file creation and modification) 


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

 fs/nfsd/export.c               |   10 ++-
 fs/nfsd/nfsctl.c               |   16 ++++-
 include/linux/sunrpc/svcauth.h |    4 -
 include/net/ipv6.h             |   17 +++++
 net/sunrpc/svcauth_unix.c      |  117 
++++++++++++++++++++++++++++-------------
 5 files changed, 118 insertions(+), 46 deletions(-)

diff -p -u -r -N linux-2.6.23-haley/fs/nfsd/export.c 
linux-2.6.23-ipmap-cache/fs/nfsd/export.c
--- linux-2.6.23-haley/fs/nfsd/export.c    2007-10-11 15:15:03.000000000 
+0200
+++ linux-2.6.23-ipmap-cache/fs/nfsd/export.c    2007-10-11 
15:23:07.000000000 +0200
@@ -35,6 +35,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
 
 #define NFSDDBG_FACILITY    NFSDDBG_EXPORT
 
@@ -1559,6 +1560,7 @@ exp_addclient(struct nfsctl_client *ncp)
 {
     struct auth_domain    *dom;
     int            i, err;
+    struct in6_addr addr6;
 
     /* First, consistency check. */
     err = -EINVAL;
@@ -1577,9 +1579,11 @@ exp_addclient(struct nfsctl_client *ncp)
         goto out_unlock;
 
     /* Insert client into hashtable. */
-    for (i = 0; i < ncp->cl_naddr; i++)
-        auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+    for (i = 0; i < ncp->cl_naddr; i++) {
+        /* Mapping address */
+        ipv6_addr_v4map(ncp->cl_addrlist[i], addr6);
+        auth_unix_add_addr(addr6, dom);
+    }
     auth_unix_forget_old(dom);
     auth_domain_put(dom);
 
diff -p -u -r -N linux-2.6.23-haley/fs/nfsd/nfsctl.c 
linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c
--- linux-2.6.23-haley/fs/nfsd/nfsctl.c    2007-10-11 15:15:03.000000000 
+0200
+++ linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c    2007-10-11 
15:23:07.000000000 +0200
@@ -38,6 +38,7 @@
 
 #include <asm/uaccess.h>
 
+#include <net/ipv6.h>
 /*
  *    We have a single directory with 9 nodes in it.
  */
@@ -222,7 +223,7 @@ static ssize_t write_getfs(struct file *
     struct auth_domain *clp;
     int err = 0;
     struct knfsd_fh *res;
-
+    struct in6_addr in6;
     if (size < sizeof(*data))
         return -EINVAL;
     data = (struct nfsctl_fsparm*)buf;
@@ -236,7 +237,11 @@ static ssize_t write_getfs(struct file *
     res = (struct knfsd_fh*)buf;
 
     exp_readlock();
-    if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+    /* IPv6 address mapping */
+    ipv6_addr_v4map(sin->sin_addr, in6);
+
+    if (!(clp = auth_unix_lookup(in6)))
         err = -EPERM;
     else {
         err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -253,6 +258,7 @@ static ssize_t write_getfd(struct file *
 {
     struct nfsctl_fdparm *data;
     struct sockaddr_in *sin;
+    struct in6_addr in6;
     struct auth_domain *clp;
     int err = 0;
     struct knfsd_fh fh;
@@ -271,7 +277,11 @@ static ssize_t write_getfd(struct file *
     res = buf;
     sin = (struct sockaddr_in *)&data->gd_addr;
     exp_readlock();
-    if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+    /* IPv6 address mapping */
+    ipv6_addr_v4map(sin->sin_addr, in6);
+
+    if (!(clp = auth_unix_lookup(in6)))
         err = -EPERM;
     else {
         err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
diff -p -u -r -N linux-2.6.23-haley/include/linux/sunrpc/svcauth.h 
linux-2.6.23-ipmap-cache/include/linux/sunrpc/svcauth.h
--- linux-2.6.23-haley/include/linux/sunrpc/svcauth.h    2007-10-11 
15:15:00.000000000 +0200
+++ linux-2.6.23-ipmap-cache/include/linux/sunrpc/svcauth.h    
2007-10-11 15:23:07.000000000 +0200
@@ -120,10 +120,10 @@ extern void    svc_auth_unregister(rpc_auth
 
 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_addr(struct in6_addr addr, struct auth_domain 
*dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct 
auth_domain *new);
 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_lookup(struct in6_addr addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
diff -p -u -r -N linux-2.6.23-haley/include/net/ipv6.h 
linux-2.6.23-ipmap-cache/include/net/ipv6.h
--- linux-2.6.23-haley/include/net/ipv6.h    2007-10-11 
15:21:23.000000000 +0200
+++ linux-2.6.23-ipmap-cache/include/net/ipv6.h    2007-10-12 
10:46:09.000000000 +0200
@@ -21,6 +21,7 @@
 #include <net/ndisc.h>
 #include <net/flow.h>
 #include <net/snmp.h>
+#include <linux/in.h>
 
 #define SIN6_LEN_RFC2133    24
 
@@ -167,6 +168,12 @@ DECLARE_SNMP_STAT(struct udp_mib, udplit
     if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, 
field);         \
     else        SNMP_INC_STATS_USER(udp_stats_in6, field);    } while(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)))
+
 struct ip6_ra_chain
 {
     struct ip6_ra_chain    *next;
@@ -377,10 +384,18 @@ static inline int ipv6_addr_any(const st
          a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
 }
 
+static inline void ipv6_addr_v4map(const struct in_addr a1, struct 
in6_addr a2)
+{
+    a2.s6_addr32[0] = 0;
+    a2.s6_addr32[1] = 0;
+    a2.s6_addr32[2] = htonl(0xffff);
+    a2.s6_addr32[3] = (uint32_t)a1.s_addr;
+}
+
 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
 {
     return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 &&
-         a->s6_addr32[2] == htonl(0x0000ffff));
+        a->s6_addr32[2] == htonl(0x0000ffff));
 }
 
 /*
diff -p -u -r -N linux-2.6.23-haley/net/sunrpc/svcauth_unix.c 
linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c
--- linux-2.6.23-haley/net/sunrpc/svcauth_unix.c    2007-10-11 
15:15:01.000000000 +0200
+++ linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c    2007-10-12 
10:47:27.000000000 +0200
@@ -11,7 +11,8 @@
 #include <linux/hash.h>
 #include <linux/string.h>
 #include <net/sock.h>
-
+#include <net/ipv6.h>
+#include <linux/kernel.h>
 #define RPCDBG_FACILITY    RPCDBG_AUTH
 
 
@@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(
 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;
 };
@@ -112,12 +113,19 @@ static inline int hash_ip(__be32 ip)
     return (hash ^ (hash>>8)) & 0xff;
 }
 #endif
+static inline int hash_ip6(struct in6_addr ip)
+{
+    return (hash_ip(ip.s6_addr32[0]) ^
+        hash_ip(ip.s6_addr32[1]) ^
+        hash_ip(ip.s6_addr32[2]) ^
+        hash_ip(ip.s6_addr32[3]));
+}
 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
 {
     struct ip_map *orig = container_of(corig, struct ip_map, h);
     struct ip_map *new = container_of(cnew, struct ip_map, h);
     return strcmp(orig->m_class, new->m_class) == 0
-        && orig->m_addr.s_addr == new->m_addr.s_addr;
+        && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
 }
 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -125,7 +133,7 @@ static void ip_map_init(struct cache_hea
     struct ip_map *item = container_of(citem, struct ip_map, h);
 
     strcpy(new->m_class, item->m_class);
-    new->m_addr.s_addr = item->m_addr.s_addr;
+    ipv6_addr_copy(&(new->m_addr), &(item->m_addr));
 }
 static void update(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -149,22 +157,24 @@ static void ip_map_request(struct cache_
                   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);
-    __be32 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 (ipv6_addr_v4mapped(&(im->m_addr))) {
+        snprintf(text_addr, 20, NIPQUAD_FMT,
+                ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
+                ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
+                ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
+                ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
+    } else {
+        snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+    }
     qword_add(bpp, blen, im->m_class);
     qword_add(bpp, blen, text_addr);
     (*bpp)[-1] = '\n';
 }
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr addr);
 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, 
time_t expiry);
 
 static int ip_map_parse(struct cache_detail *cd,
@@ -175,10 +185,10 @@ static int ip_map_parse(struct cache_det
      * for scratch: */
     char *buf = mesg;
     int len;
-    int b1,b2,b3,b4;
+    int b1, b2, b3, b4, b5, b6, b7, b8;
     char c;
     char class[8];
-    struct in_addr addr;
+    struct in6_addr addr;
     int err;
 
     struct ip_map *ipmp;
@@ -197,9 +207,26 @@ static int ip_map_parse(struct cache_det
     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, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+        addr.s6_addr32[0] = 0;
+        addr.s6_addr32[1] = 0;
+        addr.s6_addr32[2] = htonl(0xffff);
+        addr.s6_addr32[3] =
+            htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+       } else if (sscanf(buf, NIP6_FMT "%c",
+            &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+        addr.s6_addr16[0] = htons(b1);
+        addr.s6_addr16[1] = htons(b2);
+        addr.s6_addr16[2] = htons(b3);
+        addr.s6_addr16[3] = htons(b4);
+        addr.s6_addr16[4] = htons(b5);
+        addr.s6_addr16[5] = htons(b6);
+        addr.s6_addr16[6] = htons(b7);
+        addr.s6_addr16[7] = htons(b8);
+       } else
         return -EINVAL;
 
+
     expiry = get_expiry(&mesg);
     if (expiry ==0)
         return -EINVAL;
@@ -215,9 +242,6 @@ static int ip_map_parse(struct cache_det
     } else
         dom = NULL;
 
-    addr.s_addr =
-        htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-
     ipmp = ip_map_lookup(class,addr);
     if (ipmp) {
         err = ip_map_update(ipmp,
@@ -238,7 +262,7 @@ static int ip_map_show(struct seq_file *
                struct cache_head *h)
 {
     struct ip_map *im;
-    struct in_addr addr;
+    struct in6_addr addr;
     char *dom = "-no-domain-";
 
     if (h == NULL) {
@@ -247,20 +271,24 @@ static int ip_map_show(struct seq_file *
     }
     im = container_of(h, struct ip_map, h);
     /* class addr domain */
-    addr = im->m_addr;
+    ipv6_addr_copy(&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,
-           ntohl(addr.s_addr) >> 24 & 0xff,
-           ntohl(addr.s_addr) >> 16 & 0xff,
-           ntohl(addr.s_addr) >>  8 & 0xff,
-           ntohl(addr.s_addr) >>  0 & 0xff,
-           dom
-           );
+    if (ipv6_addr_v4mapped(&addr)) {
+        seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
+            im->m_class,
+            ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
+            ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
+            ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
+            ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
+            dom);
+    } else {
+        seq_printf(m, "%s" NIP6_FMT "%s\n",
+            im->m_class, NIP6(addr), dom);
+    }
     return 0;
 }
 
@@ -280,16 +308,16 @@ struct cache_detail ip_map_cache = {
     .alloc        = ip_map_alloc,
 };
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr addr)
 {
     struct ip_map ip;
     struct cache_head *ch;
 
     strcpy(ip.m_class, class);
-    ip.m_addr = addr;
+    ipv6_addr_copy(&ip.m_addr, &addr);
     ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
                  hash_str(class, IP_HASHBITS) ^
-                 hash_ip(addr.s_addr));
+                 hash_ip6(addr));
 
     if (ch)
         return container_of(ch, struct ip_map, h);
@@ -318,14 +346,14 @@ static int ip_map_update(struct ip_map *
     ch = sunrpc_cache_update(&ip_map_cache,
                  &ip.h, &ipm->h,
                  hash_str(ipm->m_class, IP_HASHBITS) ^
-                 hash_ip(ipm->m_addr.s_addr));
+                 hash_ip6(ipm->m_addr));
     if (!ch)
         return -ENOMEM;
     cache_put(ch, &ip_map_cache);
     return 0;
 }
 
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr(struct in6_addr addr, struct auth_domain *dom)
 {
     struct unix_domain *udom;
     struct ip_map *ipmp;
@@ -352,7 +380,7 @@ int auth_unix_forget_old(struct auth_dom
     return 0;
 }
 
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup(struct in6_addr addr)
 {
     struct ip_map *ipm;
     struct auth_domain *rv;
@@ -641,9 +669,24 @@ static int unix_gid_find(uid_t uid, stru
 int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
-    struct sockaddr_in *sin = svc_addr_in(rqstp);
+    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin6, sin6_storage;
     struct ip_map *ipm;
 
+    switch (rqstp->rq_addr.ss_family) {
+    case AF_INET:
+        sin = svc_addr_in(rqstp);
+        sin6 = &sin6_storage;
+        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
+                htonl(0x0000FFFF), sin->sin_addr.s_addr);
+        break;
+    case AF_INET6:
+        sin6 = svc_addr_in6(rqstp);
+        break;
+    default:
+        BUG();
+    }
+
     rqstp->rq_client = NULL;
     if (rqstp->rq_proc == 0)
         return SVC_OK;
@@ -651,7 +694,7 @@ svcauth_unix_set_client(struct svc_rqst
     ipm = ip_map_cached_get(rqstp);
     if (ipm == NULL)
         ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-                    sin->sin_addr);
+                    sin6->sin6_addr);
 
     if (ipm == NULL)
         return SVC_DENIED;

-- 

********************************
       Aurelien Charbon
           Bull SAS
     Echirolles - France
 http://www.bullopensource.org/
********************************


[-- Attachment #2: linux-2.6.23-ipmap-cache.diff --]
[-- Type: text/x-patch, Size: 12801 bytes --]

diff -p -u -r -N linux-2.6.23-haley/fs/nfsd/export.c linux-2.6.23-ipmap-cache/fs/nfsd/export.c
--- linux-2.6.23-haley/fs/nfsd/export.c	2007-10-11 15:15:03.000000000 +0200
+++ linux-2.6.23-ipmap-cache/fs/nfsd/export.c	2007-10-11 15:23:07.000000000 +0200
@@ -35,6 +35,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
 
@@ -1559,6 +1560,7 @@ exp_addclient(struct nfsctl_client *ncp)
 {
 	struct auth_domain	*dom;
 	int			i, err;
+	struct in6_addr addr6;
 
 	/* First, consistency check. */
 	err = -EINVAL;
@@ -1577,9 +1579,11 @@ exp_addclient(struct nfsctl_client *ncp)
 		goto out_unlock;
 
 	/* Insert client into hashtable. */
-	for (i = 0; i < ncp->cl_naddr; i++)
-		auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+	for (i = 0; i < ncp->cl_naddr; i++) {
+		/* Mapping address */
+		ipv6_addr_v4map(ncp->cl_addrlist[i], addr6);
+		auth_unix_add_addr(addr6, dom);
+	}
 	auth_unix_forget_old(dom);
 	auth_domain_put(dom);
 
diff -p -u -r -N linux-2.6.23-haley/fs/nfsd/nfsctl.c linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c
--- linux-2.6.23-haley/fs/nfsd/nfsctl.c	2007-10-11 15:15:03.000000000 +0200
+++ linux-2.6.23-ipmap-cache/fs/nfsd/nfsctl.c	2007-10-11 15:23:07.000000000 +0200
@@ -38,6 +38,7 @@
 
 #include <asm/uaccess.h>
 
+#include <net/ipv6.h>
 /*
  *	We have a single directory with 9 nodes in it.
  */
@@ -222,7 +223,7 @@ static ssize_t write_getfs(struct file *
 	struct auth_domain *clp;
 	int err = 0;
 	struct knfsd_fh *res;
-
+	struct in6_addr in6;
 	if (size < sizeof(*data))
 		return -EINVAL;
 	data = (struct nfsctl_fsparm*)buf;
@@ -236,7 +237,11 @@ static ssize_t write_getfs(struct file *
 	res = (struct knfsd_fh*)buf;
 
 	exp_readlock();
-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+	/* IPv6 address mapping */
+	ipv6_addr_v4map(sin->sin_addr, in6);
+
+	if (!(clp = auth_unix_lookup(in6)))
 		err = -EPERM;
 	else {
 		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -253,6 +258,7 @@ static ssize_t write_getfd(struct file *
 {
 	struct nfsctl_fdparm *data;
 	struct sockaddr_in *sin;
+	struct in6_addr in6;
 	struct auth_domain *clp;
 	int err = 0;
 	struct knfsd_fh fh;
@@ -271,7 +277,11 @@ static ssize_t write_getfd(struct file *
 	res = buf;
 	sin = (struct sockaddr_in *)&data->gd_addr;
 	exp_readlock();
-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+	/* IPv6 address mapping */
+	ipv6_addr_v4map(sin->sin_addr, in6);
+
+	if (!(clp = auth_unix_lookup(in6)))
 		err = -EPERM;
 	else {
 		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
diff -p -u -r -N linux-2.6.23-haley/include/linux/sunrpc/svcauth.h linux-2.6.23-ipmap-cache/include/linux/sunrpc/svcauth.h
--- linux-2.6.23-haley/include/linux/sunrpc/svcauth.h	2007-10-11 15:15:00.000000000 +0200
+++ linux-2.6.23-ipmap-cache/include/linux/sunrpc/svcauth.h	2007-10-11 15:23:07.000000000 +0200
@@ -120,10 +120,10 @@ extern void	svc_auth_unregister(rpc_auth
 
 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_addr(struct in6_addr addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
 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_lookup(struct in6_addr addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
diff -p -u -r -N linux-2.6.23-haley/include/net/ipv6.h linux-2.6.23-ipmap-cache/include/net/ipv6.h
--- linux-2.6.23-haley/include/net/ipv6.h	2007-10-11 15:21:23.000000000 +0200
+++ linux-2.6.23-ipmap-cache/include/net/ipv6.h	2007-10-12 10:46:09.000000000 +0200
@@ -21,6 +21,7 @@
 #include <net/ndisc.h>
 #include <net/flow.h>
 #include <net/snmp.h>
+#include <linux/in.h>
 
 #define SIN6_LEN_RFC2133	24
 
@@ -167,6 +168,12 @@ DECLARE_SNMP_STAT(struct udp_mib, udplit
 	if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field);         \
 	else		SNMP_INC_STATS_USER(udp_stats_in6, field);    } while(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)))
+
 struct ip6_ra_chain
 {
 	struct ip6_ra_chain	*next;
@@ -377,10 +384,18 @@ static inline int ipv6_addr_any(const st
 		 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
 }
 
+static inline void ipv6_addr_v4map(const struct in_addr a1, struct in6_addr a2)
+{
+	a2.s6_addr32[0] = 0;
+	a2.s6_addr32[1] = 0;
+	a2.s6_addr32[2] = htonl(0xffff);
+	a2.s6_addr32[3] = (uint32_t)a1.s_addr;
+}
+
 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
 {
 	return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 && 
-		 a->s6_addr32[2] == htonl(0x0000ffff)); 
+		a->s6_addr32[2] == htonl(0x0000ffff)); 
 }
 
 /*
diff -p -u -r -N linux-2.6.23-haley/net/sunrpc/svcauth_unix.c linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c
--- linux-2.6.23-haley/net/sunrpc/svcauth_unix.c	2007-10-11 15:15:01.000000000 +0200
+++ linux-2.6.23-ipmap-cache/net/sunrpc/svcauth_unix.c	2007-10-12 10:47:27.000000000 +0200
@@ -11,7 +11,8 @@
 #include <linux/hash.h>
 #include <linux/string.h>
 #include <net/sock.h>
-
+#include <net/ipv6.h>
+#include <linux/kernel.h>
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
 
@@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(
 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;
 };
@@ -112,12 +113,19 @@ static inline int hash_ip(__be32 ip)
 	return (hash ^ (hash>>8)) & 0xff;
 }
 #endif
+static inline int hash_ip6(struct in6_addr ip)
+{
+	return (hash_ip(ip.s6_addr32[0]) ^
+		hash_ip(ip.s6_addr32[1]) ^
+		hash_ip(ip.s6_addr32[2]) ^
+		hash_ip(ip.s6_addr32[3]));
+}
 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
 {
 	struct ip_map *orig = container_of(corig, struct ip_map, h);
 	struct ip_map *new = container_of(cnew, struct ip_map, h);
 	return strcmp(orig->m_class, new->m_class) == 0
-		&& orig->m_addr.s_addr == new->m_addr.s_addr;
+		&& ipv6_addr_equal(&orig->m_addr, &new->m_addr);
 }
 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -125,7 +133,7 @@ static void ip_map_init(struct cache_hea
 	struct ip_map *item = container_of(citem, struct ip_map, h);
 
 	strcpy(new->m_class, item->m_class);
-	new->m_addr.s_addr = item->m_addr.s_addr;
+	ipv6_addr_copy(&(new->m_addr), &(item->m_addr));
 }
 static void update(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -149,22 +157,24 @@ static void ip_map_request(struct cache_
 				  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);
-	__be32 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 (ipv6_addr_v4mapped(&(im->m_addr))) {
+		snprintf(text_addr, 20, NIPQUAD_FMT,
+				ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
+				ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
+				ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
+				ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
+	} else {
+		snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+	}
 	qword_add(bpp, blen, im->m_class);
 	qword_add(bpp, blen, text_addr);
 	(*bpp)[-1] = '\n';
 }
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr addr);
 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
 
 static int ip_map_parse(struct cache_detail *cd,
@@ -175,10 +185,10 @@ static int ip_map_parse(struct cache_det
 	 * for scratch: */
 	char *buf = mesg;
 	int len;
-	int b1,b2,b3,b4;
+	int b1, b2, b3, b4, b5, b6, b7, b8;
 	char c;
 	char class[8];
-	struct in_addr addr;
+	struct in6_addr addr;
 	int err;
 
 	struct ip_map *ipmp;
@@ -197,9 +207,26 @@ static int ip_map_parse(struct cache_det
 	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, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+		addr.s6_addr32[0] = 0;
+		addr.s6_addr32[1] = 0;
+		addr.s6_addr32[2] = htonl(0xffff);
+		addr.s6_addr32[3] =
+			htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+       } else if (sscanf(buf, NIP6_FMT "%c",
+			&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+		addr.s6_addr16[0] = htons(b1);
+		addr.s6_addr16[1] = htons(b2);
+		addr.s6_addr16[2] = htons(b3);
+		addr.s6_addr16[3] = htons(b4);
+		addr.s6_addr16[4] = htons(b5);
+		addr.s6_addr16[5] = htons(b6);
+		addr.s6_addr16[6] = htons(b7);
+		addr.s6_addr16[7] = htons(b8);
+       } else
 		return -EINVAL;
 
+
 	expiry = get_expiry(&mesg);
 	if (expiry ==0)
 		return -EINVAL;
@@ -215,9 +242,6 @@ static int ip_map_parse(struct cache_det
 	} else
 		dom = NULL;
 
-	addr.s_addr =
-		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-
 	ipmp = ip_map_lookup(class,addr);
 	if (ipmp) {
 		err = ip_map_update(ipmp,
@@ -238,7 +262,7 @@ static int ip_map_show(struct seq_file *
 		       struct cache_head *h)
 {
 	struct ip_map *im;
-	struct in_addr addr;
+	struct in6_addr addr;
 	char *dom = "-no-domain-";
 
 	if (h == NULL) {
@@ -247,20 +271,24 @@ static int ip_map_show(struct seq_file *
 	}
 	im = container_of(h, struct ip_map, h);
 	/* class addr domain */
-	addr = im->m_addr;
+	ipv6_addr_copy(&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,
-		   ntohl(addr.s_addr) >> 24 & 0xff,
-		   ntohl(addr.s_addr) >> 16 & 0xff,
-		   ntohl(addr.s_addr) >>  8 & 0xff,
-		   ntohl(addr.s_addr) >>  0 & 0xff,
-		   dom
-		   );
+	if (ipv6_addr_v4mapped(&addr)) {
+		seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
+			im->m_class,
+			ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
+			ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
+			ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
+			ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
+			dom);
+	} else {
+		seq_printf(m, "%s" NIP6_FMT "%s\n",
+			im->m_class, NIP6(addr), dom);
+	}
 	return 0;
 }
 
@@ -280,16 +308,16 @@ struct cache_detail ip_map_cache = {
 	.alloc		= ip_map_alloc,
 };
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr addr)
 {
 	struct ip_map ip;
 	struct cache_head *ch;
 
 	strcpy(ip.m_class, class);
-	ip.m_addr = addr;
+	ipv6_addr_copy(&ip.m_addr, &addr);
 	ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
 				 hash_str(class, IP_HASHBITS) ^
-				 hash_ip(addr.s_addr));
+				 hash_ip6(addr));
 
 	if (ch)
 		return container_of(ch, struct ip_map, h);
@@ -318,14 +346,14 @@ static int ip_map_update(struct ip_map *
 	ch = sunrpc_cache_update(&ip_map_cache,
 				 &ip.h, &ipm->h,
 				 hash_str(ipm->m_class, IP_HASHBITS) ^
-				 hash_ip(ipm->m_addr.s_addr));
+				 hash_ip6(ipm->m_addr));
 	if (!ch)
 		return -ENOMEM;
 	cache_put(ch, &ip_map_cache);
 	return 0;
 }
 
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr(struct in6_addr addr, struct auth_domain *dom)
 {
 	struct unix_domain *udom;
 	struct ip_map *ipmp;
@@ -352,7 +380,7 @@ int auth_unix_forget_old(struct auth_dom
 	return 0;
 }
 
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup(struct in6_addr addr)
 {
 	struct ip_map *ipm;
 	struct auth_domain *rv;
@@ -641,9 +669,24 @@ static int unix_gid_find(uid_t uid, stru
 int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
-	struct sockaddr_in *sin = svc_addr_in(rqstp);
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6, sin6_storage;
 	struct ip_map *ipm;
 
+	switch (rqstp->rq_addr.ss_family) {
+	case AF_INET:
+		sin = svc_addr_in(rqstp);
+		sin6 = &sin6_storage;
+		ipv6_addr_set(&sin6->sin6_addr, 0, 0,
+				htonl(0x0000FFFF), sin->sin_addr.s_addr); 
+		break;
+	case AF_INET6:
+		sin6 = svc_addr_in6(rqstp);
+		break;
+	default:
+		BUG();
+	}
+
 	rqstp->rq_client = NULL;
 	if (rqstp->rq_proc == 0)
 		return SVC_OK;
@@ -651,7 +694,7 @@ svcauth_unix_set_client(struct svc_rqst 
 	ipm = ip_map_cached_get(rqstp);
 	if (ipm == NULL)
 		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-				    sin->sin_addr);
+				    sin6->sin6_addr);
 
 	if (ipm == NULL)
 		return SVC_DENIED;

[-- Attachment #3: linux-2.6.23-haley.diff --]
[-- Type: text/x-patch, Size: 3700 bytes --]

diff -p -u -r -N linux-2.6.23/include/net/ipv6.h linux-2.6.23-haley/include/net/ipv6.h
--- linux-2.6.23/include/net/ipv6.h	2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23-haley/include/net/ipv6.h	2007-10-11 15:21:23.000000000 +0200
@@ -377,6 +377,12 @@ static inline int ipv6_addr_any(const st
 		 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
 }
 
+static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+	return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 && 
+		 a->s6_addr32[2] == htonl(0x0000ffff)); 
+}
+
 /*
  * find the first different bit between two addresses
  * length of address must be a multiple of 32bits
diff -p -u -r -N linux-2.6.23/net/ipv6/ipv6_sockglue.c linux-2.6.23-haley/net/ipv6/ipv6_sockglue.c
--- linux-2.6.23/net/ipv6/ipv6_sockglue.c	2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23-haley/net/ipv6/ipv6_sockglue.c	2007-10-11 15:21:23.000000000 +0200
@@ -249,7 +249,7 @@ static int do_ipv6_setsockopt(struct soc
 			}
 
 			if (ipv6_only_sock(sk) ||
-			    !(ipv6_addr_type(&np->daddr) & IPV6_ADDR_MAPPED)) {
+			    !ipv6_addr_v4mapped(&np->daddr)) {
 				retv = -EADDRNOTAVAIL;
 				break;
 			}
diff -p -u -r -N linux-2.6.23/net/ipv6/tcp_ipv6.c linux-2.6.23-haley/net/ipv6/tcp_ipv6.c
--- linux-2.6.23/net/ipv6/tcp_ipv6.c	2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23-haley/net/ipv6/tcp_ipv6.c	2007-10-11 15:21:23.000000000 +0200
@@ -697,7 +697,7 @@ static int tcp_v6_parse_md5_keys (struct
 	if (!cmd.tcpm_keylen) {
 		if (!tcp_sk(sk)->md5sig_info)
 			return -ENOENT;
-		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED)
+		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
 			return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]);
 		return tcp_v6_md5_do_del(sk, &sin6->sin6_addr);
 	}
@@ -720,7 +720,7 @@ static int tcp_v6_parse_md5_keys (struct
 	newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
 	if (!newkey)
 		return -ENOMEM;
-	if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) {
+	if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
 		return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3],
 					 newkey, cmd.tcpm_keylen);
 	}
diff -p -u -r -N linux-2.6.23/net/ipv6/udp.c linux-2.6.23-haley/net/ipv6/udp.c
--- linux-2.6.23/net/ipv6/udp.c	2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23-haley/net/ipv6/udp.c	2007-10-11 15:21:23.000000000 +0200
@@ -612,7 +612,7 @@ int udpv6_sendmsg(struct kiocb *iocb, st
 		daddr = NULL;
 
 	if (daddr) {
-		if (ipv6_addr_type(daddr) == IPV6_ADDR_MAPPED) {
+		if (ipv6_addr_v4mapped(daddr)) {
 			struct sockaddr_in sin;
 			sin.sin_family = AF_INET;
 			sin.sin_port = sin6 ? sin6->sin6_port : inet->dport;
diff -p -u -r -N linux-2.6.23/net/sctp/ipv6.c linux-2.6.23-haley/net/sctp/ipv6.c
--- linux-2.6.23/net/sctp/ipv6.c	2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23-haley/net/sctp/ipv6.c	2007-10-11 15:21:23.000000000 +0200
@@ -493,7 +493,7 @@ static int sctp_v6_cmp_addr(const union 
 	if (addr1->sa.sa_family != addr2->sa.sa_family) {
 		if (addr1->sa.sa_family == AF_INET &&
 		    addr2->sa.sa_family == AF_INET6 &&
-		    IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) {
+		    ipv6_addr_v4mapped(&addr2->v6.sin6_addr)) {
 			if (addr2->v6.sin6_port == addr1->v4.sin_port &&
 			    addr2->v6.sin6_addr.s6_addr32[3] ==
 			    addr1->v4.sin_addr.s_addr)
@@ -501,7 +501,7 @@ static int sctp_v6_cmp_addr(const union 
 		}
 		if (addr2->sa.sa_family == AF_INET &&
 		    addr1->sa.sa_family == AF_INET6 &&
-		    IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) {
+		    ipv6_addr_v4mapped(&addr1->v6.sin6_addr)) {
 			if (addr1->v6.sin6_port == addr2->v4.sin_port &&
 			    addr1->v6.sin6_addr.s6_addr32[3] ==
 			    addr2->v4.sin_addr.s_addr)

^ permalink raw reply

* [TC]: Add NAT action
From: Herbert Xu @ 2007-10-12  9:08 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

Hi Stephen:

Here's a patch to add support for the nat action which is now
in the kernel.

Thanks,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/tc/Makefile b/tc/Makefile
index 22cd437..cd5a69e 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -26,6 +26,7 @@ TCMODULES += q_htb.o
 TCMODULES += m_gact.o
 TCMODULES += m_mirred.o
 TCMODULES += m_ipt.o
+TCMODULES += m_nat.o
 TCMODULES += m_pedit.o
 TCMODULES += p_ip.o
 TCMODULES += p_icmp.o
diff --git a/tc/m_nat.c b/tc/m_nat.c
new file mode 100644
index 0000000..6e7fd05
--- /dev/null
+++ b/tc/m_nat.c
@@ -0,0 +1,213 @@
+/*
+ * m_nat.c		NAT module
+ *
+ *		This program is free software; you can distribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <dlfcn.h>
+#include "utils.h"
+#include "tc_util.h"
+#include <linux/tc_act/tc_nat.h>
+
+static void
+explain(void)
+{
+	fprintf(stderr, "Usage: ... nat NAT\n"
+			"NAT := DIRECTION OLD NEW\n"
+			"DIRECTION := { ingress | egress }\n"
+			"OLD := PREFIX\n"
+			"NEW := ADDRESS\n");
+}
+
+static void
+usage(void)
+{
+	explain();
+	exit(-1);
+}
+
+static int
+parse_nat_args(int *argc_p, char ***argv_p,struct tc_nat *sel)
+{
+	int argc = *argc_p;
+	char **argv = *argv_p;
+	inet_prefix addr;
+
+	if (argc <= 0)
+		return -1;
+
+	if (matches(*argv, "egress") == 0)
+		sel->flags |= TCA_NAT_FLAG_EGRESS;
+	else if (matches(*argv, "ingress") != 0)
+		goto bad_val;
+
+	NEXT_ARG();
+
+	if (get_prefix_1(&addr, *argv, AF_INET))
+		goto bad_val;
+
+	sel->old_addr = addr.data[0];
+	sel->mask = htonl(~0u << (32 - addr.bitlen));
+
+	NEXT_ARG();
+
+	if (get_prefix_1(&addr, *argv, AF_INET))
+		goto bad_val;
+
+	sel->new_addr = addr.data[0];
+
+	argc--;
+	argv++;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+
+bad_val:
+	return -1;
+}
+
+static int
+parse_nat(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
+{
+	struct tc_nat sel;
+
+	int argc = *argc_p;
+	char **argv = *argv_p;
+	int ok = 0;
+	struct rtattr *tail;
+
+	memset(&sel, 0, sizeof(sel));
+
+	while (argc > 0) {
+		if (matches(*argv, "nat") == 0) {
+			NEXT_ARG();
+			if (parse_nat_args(&argc, &argv, &sel)) {
+				fprintf(stderr, "Illegal nat construct (%s) \n",
+					*argv);
+				explain();
+				return -1;
+			}
+			ok++;
+			continue;
+		} else if (matches(*argv, "help") == 0) {
+			usage();
+		} else {
+			break;
+		}
+
+	}
+
+	if (!ok) {
+		explain();
+		return -1;
+	}
+
+	if (argc) {
+		if (matches(*argv, "reclassify") == 0) {
+			sel.action = TC_ACT_RECLASSIFY;
+			argc--;
+			argv++;
+		} else if (matches(*argv, "pipe") == 0) {
+			sel.action = TC_ACT_PIPE;
+			argc--;
+			argv++;
+		} else if (matches(*argv, "drop") == 0 ||
+			matches(*argv, "shot") == 0) {
+			sel.action = TC_ACT_SHOT;
+			argc--;
+			argv++;
+		} else if (matches(*argv, "continue") == 0) {
+			sel.action = TC_ACT_UNSPEC;
+			argc--;
+			argv++;
+		} else if (matches(*argv, "pass") == 0) {
+			sel.action = TC_ACT_OK;
+			argc--;
+			argv++;
+		}
+	}
+
+	if (argc) {
+		if (matches(*argv, "index") == 0) {
+			NEXT_ARG();
+			if (get_u32(&sel.index, *argv, 10)) {
+				fprintf(stderr, "Pedit: Illegal \"index\"\n");
+				return -1;
+			}
+			argc--;
+			argv++;
+		}
+	}
+
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+	addattr_l(n, MAX_MSG, TCA_NAT_PARMS, &sel, sizeof(sel));
+	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int
+print_nat(struct action_util *au,FILE * f, struct rtattr *arg)
+{
+	struct tc_nat *sel;
+	struct rtattr *tb[TCA_NAT_MAX + 1];
+	char buf1[256];
+	char buf2[256];
+	SPRINT_BUF(buf3);
+	int len;
+
+	if (arg == NULL)
+		return -1;
+
+	parse_rtattr_nested(tb, TCA_NAT_MAX, arg);
+
+	if (tb[TCA_NAT_PARMS] == NULL) {
+		fprintf(f, "[NULL nat parameters]");
+		return -1;
+	}
+	sel = RTA_DATA(tb[TCA_NAT_PARMS]);
+
+	len = ffs(sel->mask);
+	len = len ? 33 - len : 0;
+
+	fprintf(f, " nat %s %s/%d %s %s", sel->flags & TCA_NAT_FLAG_EGRESS ?
+					  "egress" : "ingress",
+		format_host(AF_INET, 4, &sel->old_addr, buf1, sizeof(buf1)),
+		len,
+		format_host(AF_INET, 4, &sel->new_addr, buf2, sizeof(buf2)),
+		action_n2a(sel->action, buf3, sizeof (buf3)));
+
+	if (show_stats) {
+		if (tb[TCA_NAT_TM]) {
+			struct tcf_t *tm = RTA_DATA(tb[TCA_NAT_TM]);
+			print_tm(f,tm);
+		}
+	}
+
+	return 0;
+}
+
+struct action_util nat_action_util = {
+	.id = "nat",
+	.parse_aopt = parse_nat,
+	.print_aopt = print_nat,
+};

^ permalink raw reply related

* [PATCH 12/12] Drop bogus reference to tc-filters and add lartc.org link to manpage.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Alexander Wirt, Andreas Henriksson
In-Reply-To: <1192179407-22461-11-git-send-email-andreas@fatal.se>

From: Alexander Wirt <formorer@debian.org>


Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 man/man8/ip.8 |    2 ++
 man/man8/tc.8 |    3 ++-
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 153123a..8fd6d52 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -1830,6 +1830,8 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2.
 .RB "IP Command reference " ip-cref.ps
 .br
 .RB "IP tunnels " ip-cref.ps
+.br
+.RB "User documentation at " http://lartc.org/ ", but please direct bugreports and patches to: " <netdev@vger.kernel.org>
 
 .SH AUTHOR
 Original Manpage  by Michail Litvak <mci@owl.openwall.com>
diff --git a/man/man8/tc.8 b/man/man8/tc.8
index 6acd572..53a866f 100644
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -339,7 +339,8 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2.
 .BR tc-pfifo (8),
 .BR tc-bfifo (8),
 .BR tc-pfifo_fast (8),
-.BR tc-filters (8)
+.br
+.RB "User documentation at " http://lartc.org/ ", but please direct bugreports and patches to: " <netdev@vger.kernel.org>
 
 .SH AUTHOR
 Manpage maintained by bert hubert (ahu@ds9a.nl)
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 11/12] Fix overflow in time2tick / tick2time.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Andreas Henriksson
In-Reply-To: <1192179407-22461-10-git-send-email-andreas@fatal.se>

The helper functions gets passed an unsigned int, which gets cast to long
and overflows. See http://bugs.debian.org/175462

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 tc/tc_core.c |    4 ++--
 tc/tc_core.h |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tc/tc_core.c b/tc/tc_core.c
index 58155fb..fb89876 100644
--- a/tc/tc_core.c
+++ b/tc/tc_core.c
@@ -35,12 +35,12 @@ int tc_core_time2big(long time)
 }
 
 
-long tc_core_time2tick(long time)
+unsigned tc_core_time2tick(unsigned time)
 {
 	return time*tick_in_usec;
 }
 
-long tc_core_tick2time(long tick)
+unsigned tc_core_tick2time(unsigned tick)
 {
 	return tick/tick_in_usec;
 }
diff --git a/tc/tc_core.h b/tc/tc_core.h
index a139da6..b2a16bc 100644
--- a/tc/tc_core.h
+++ b/tc/tc_core.h
@@ -7,8 +7,8 @@
 #define TIME_UNITS_PER_SEC	1000000
 
 int  tc_core_time2big(long time);
-long tc_core_time2tick(long time);
-long tc_core_tick2time(long tick);
+unsigned tc_core_time2tick(unsigned time);
+unsigned tc_core_tick2time(unsigned tick);
 long tc_core_time2ktime(long time);
 long tc_core_ktime2time(long ktime);
 unsigned tc_calc_xmittime(unsigned rate, unsigned size);
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 02/12] Add parameters to usage help text.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Alexander Wirt, Andreas Henriksson
In-Reply-To: <1192179407-22461-1-git-send-email-andreas@fatal.se>

From: Alexander Wirt <formorer@debian.org>

Add src option to route help text (http://bugs.debian.org/226142).
Add prio option to rule prio help text (http://bugs.debian.org/213673).

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 ip/iproute.c |    2 +-
 ip/iprule.c  |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index 77bdf83..d3a3243 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -74,7 +74,7 @@ static void usage(void)
 	fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
 	fprintf(stderr, "           [ rtt TIME ] [ rttvar TIME ]\n");
 	fprintf(stderr, "           [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");
-	fprintf(stderr, "           [ ssthresh NUMBER ] [ realms REALM ]\n");
+	fprintf(stderr, "           [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n");
 	fprintf(stderr, "           [ rto_min TIME ]\n");
 	fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n");
 	fprintf(stderr, "          unreachable | prohibit | blackhole | nat ]\n");
diff --git a/ip/iprule.c b/ip/iprule.c
index e1a943a..0f7c223 100644
--- a/ip/iprule.c
+++ b/ip/iprule.c
@@ -38,7 +38,7 @@ static void usage(void)
 {
 	fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n");
 	fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n");
-	fprintf(stderr, "            [ dev STRING ] [ pref NUMBER ]\n");
+	fprintf(stderr, "            [ dev STRING ] [ pref NUMBER ] [ prio NUMBER ]\n");
 	fprintf(stderr, "ACTION := [ table TABLE_ID ]\n");
 	fprintf(stderr, "          [ prohibit | reject | unreachable ]\n");
 	fprintf(stderr, "          [ realms [SRCREALM/]DSTREALM ]\n");
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 01/12] Fix various typos and nitpicks
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Alexander Wirt, Andreas Henriksson

From: Alexander Wirt <formorer@debian.org>

Fix typo in ss manpage.
Make the backslash visible in ip manpage (http://bugs.debian.org/285507).
Strict syntax for ip addr advice in error message.
Fix typo in libnetlink(3) manpage (writen -> written).
Fix typos in tc-prio(8) manpage.
Fix typo in tc-htb(8) manpage (mininum -> minimum).
Fix typo in tc-cbq-details(8) manpage (occured -> occurred).

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 ip/ipaddress.c            |    2 +-
 man/man3/libnetlink.3     |    2 +-
 man/man8/ip.8             |    2 +-
 man/man8/ss.8             |    2 +-
 man/man8/tc-cbq-details.8 |    2 +-
 man/man8/tc-htb.8         |    2 +-
 man/man8/tc-prio.8        |    8 ++++----
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 518d8cd..d1c6620 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1019,7 +1019,7 @@ int do_ipaddr(int argc, char **argv)
 		return ipaddr_list_or_flush(argc-1, argv+1, 1);
 	if (matches(*argv, "help") == 0)
 		usage();
-	fprintf(stderr, "Command \"%s\" is unknown, try \"ip address help\".\n", *argv);
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv);
 	exit(-1);
 }
 
diff --git a/man/man3/libnetlink.3 b/man/man3/libnetlink.3
index 145f38d..15a478a 100644
--- a/man/man3/libnetlink.3
+++ b/man/man3/libnetlink.3
@@ -187,7 +187,7 @@ The functions sometimes use fprintf and exit when a fatal error occurs.
 This library should be named librtnetlink.
 
 .SH AUTHORS
-netlink/rtnetlink was designed and writen by Alexey Kuznetsov.
+netlink/rtnetlink was designed and written by Alexey Kuznetsov.
 Andi Kleen wrote the man page.
 
 .SH SEE ALSO
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 7181054..153123a 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -379,7 +379,7 @@ shortcut for
 .BR "\-o" , " \-oneline"
 output each record on a single line, replacing line feeds
 with the
-.B '\'
+.B '\e\'
 character. This is convenient when you want to count records 
 with
 .BR wc (1)
diff --git a/man/man8/ss.8 b/man/man8/ss.8
index f732319..19f341e 100644
--- a/man/man8/ss.8
+++ b/man/man8/ss.8
@@ -9,7 +9,7 @@ ss \- another utility to investigate sockets
 is used to dump socket statistics. It allows showing information similar
 to
 .IR netstat .
-It can display more TCP information than state than other tools.
+It can display more TCP and state informations than other tools.
 
 .SH OPTIONS
 These programs follow the usual GNU command line syntax, with long
diff --git a/man/man8/tc-cbq-details.8 b/man/man8/tc-cbq-details.8
index e47da62..09badb9 100644
--- a/man/man8/tc-cbq-details.8
+++ b/man/man8/tc-cbq-details.8
@@ -210,7 +210,7 @@ Consult the map for a class for the
 priority. If found, choose it, and terminate.
 .TP
 (iii)
-Choose the class at which break out to the fallback algorithm occured. Terminate.
+Choose the class at which break out to the fallback algorithm occurred. Terminate.
 .P
 The packet is enqueued to the class which was chosen when either algorithm 
 terminated. It is therefore possible for a packet to be enqueued *not* at a
diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8
index f61b818..d196ecd 100644
--- a/man/man8/tc-htb.8
+++ b/man/man8/tc-htb.8
@@ -137,7 +137,7 @@ packet. Should be at least as high as the highest cburst of all children.
 .SH NOTES
 Due to Unix timing constraints, the maximum ceil rate is not infinite and may in fact be quite low. On Intel, 
 there are 100 timer events per second, the maximum rate is that rate at which 'burst' bytes are sent each timer tick.
-From this, the mininum burst size for a specified rate can be calculated. For i386, a 10mbit rate requires a 12 kilobyte 
+From this, the minimum burst size for a specified rate can be calculated. For i386, a 10mbit rate requires a 12 kilobyte 
 burst as 100*12kb*8 equals 10mbit.
 
 .SH SEE ALSO
diff --git a/man/man8/tc-prio.8 b/man/man8/tc-prio.8
index e942e62..780bcd5 100644
--- a/man/man8/tc-prio.8
+++ b/man/man8/tc-prio.8
@@ -30,7 +30,7 @@ traffic.
 On creation with 'tc qdisc add', a fixed number of bands is created. Each
 band is a class, although is not possible to add classes with 'tc qdisc
 add', the number of bands to be created must instead be specified on the
-commandline attaching PRIO to its root.
+command line attaching PRIO to its root.
 
 When dequeueing, band 0 is tried first and only if it did not deliver a
 packet does PRIO try band 1, and so onwards. Maximum reliability packets
@@ -88,7 +88,7 @@ this:
 The four TOS bits (the 'TOS field') are defined as:
 
 .nf
-Binary Decimcal  Meaning
+Binary Decimal  Meaning
 -----------------------------------------
 1000   8         Minimize delay (md)
 0100   4         Maximize throughput (mt)
@@ -125,13 +125,13 @@ TOS     Bits  Means                    Linux Priority    Band
 
 The second column contains the value of the relevant
 four TOS bits, followed by their translated meaning. For example, 15 stands
-for a packet wanting Minimal Montetary Cost, Maximum Reliability, Maximum
+for a packet wanting Minimal Monetary Cost, Maximum Reliability, Maximum
 Throughput AND Minimum Delay. 
 
 The fourth column lists the way the Linux kernel interprets the TOS bits, by
 showing to which Priority they are mapped.
 
-The last column shows the result of the default priomap. On the commandline,
+The last column shows the result of the default priomap. On the command line,
 the default priomap looks like this:
 
     1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 08/12] Fix ematch cmp and nbyte syntax help text.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Lionel Elie Mamane, Andreas Henriksson
In-Reply-To: <1192179407-22461-7-git-send-email-andreas@fatal.se>

From: Lionel Elie Mamane <lionel@mamane.lu>

The help/usage screen of ematch cmp and nbyte say recognised symbolic
values for "layer FOO" are link, header and next-header, but the code
does _not_ implement that: it will recognise "next-header" as what is
supposed to be "header" and will not recognise "header". The right
symbolic values seem to be link, network, transport. Here is a patch
that changes the help/usage screen to match the code.
(http://bugs.debian.org/438653)

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 tc/em_cmp.c   |    4 ++--
 tc/em_nbyte.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tc/em_cmp.c b/tc/em_cmp.c
index b8f9b46..ce72a42 100644
--- a/tc/em_cmp.c
+++ b/tc/em_cmp.c
@@ -1,5 +1,5 @@
 /*
- * em_cmp.c		Simle coparison Ematch
+ * em_cmp.c		Simple comparison Ematch
  *
  *		This program is free software; you can distribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -32,7 +32,7 @@ static void cmp_print_usage(FILE *fd)
 	    "Usage: cmp(ALIGN at OFFSET [ ATTRS ] { eq | lt | gt } VALUE)\n" \
 	    "where: ALIGN  := { u8 | u16 | u32 }\n" \
 	    "       ATTRS  := [ layer LAYER ] [ mask MASK ] [ trans ]\n" \
-	    "       LAYER  := { link | header | next-header | 0..%d }\n" \
+	    "       LAYER  := { link | network | transport | 0..%d }\n" \
 	    "\n" \
 	    "Example: cmp(u16 at 3 layer 2 mask 0xff00 gt 20)\n",
 	    TCF_LAYER_MAX);
diff --git a/tc/em_nbyte.c b/tc/em_nbyte.c
index 98f9883..242c361 100644
--- a/tc/em_nbyte.c
+++ b/tc/em_nbyte.c
@@ -32,7 +32,7 @@ static void nbyte_print_usage(FILE *fd)
 	    "Usage: nbyte(NEEDLE at OFFSET [layer LAYER])\n" \
 	    "where: NEEDLE := { string | \"c-escape-sequence\" }\n" \
 	    "       OFFSET := int\n" \
-	    "       LAYER  := { link | header | next-header | 0..%d }\n" \
+	    "       LAYER  := { link | network | transport | 0..%d }\n" \
 	    "\n" \
 	    "Example: nbyte(\"ababa\" at 12 layer 1)\n",
 	    TCF_LAYER_MAX);
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 10/12] Fix off-by-one in print of wrandom algo.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Norbert Buchmuller, Andreas Henriksson
In-Reply-To: <1192179407-22461-9-git-send-email-andreas@fatal.se>

From: Norbert Buchmuller <norbi@nix.hu>

The 'wrandom' multipath algo is recognised when adding the route, but
not resolved when it is printed (prints 'unknown'):

ianus:~# ip ro add 1.2.3.4 mpath wrandom nexthop dev ppp0 weight 1 nexthop dev ppp1 weight 2
ianus:~# ip ro get to 1.2.3.4
1.2.3.4 mpath unknown dev ppp0  src 62.77.192.67
    cache  mtu 1492 advmss 1452 hoplimit 64
ianus:~# ip ro del 1.2.3.4 mpath wrandom nexthop dev ppp0 weight 1 nexthop dev ppp1 weight 2

See http://bugs.debian.org/428440 for more information.

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 ip/iproute.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index d3a3243..3b5c4b1 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -365,7 +365,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		__u32 mp_alg = *(__u32*) RTA_DATA(tb[RTA_MP_ALGO]);
 		if (mp_alg > IP_MP_ALG_NONE) {
 			fprintf(fp, "mpath %s ",
-			    mp_alg < IP_MP_ALG_MAX ? mp_alg_names[mp_alg] : "unknown");
+			    mp_alg <= IP_MP_ALG_MAX ? mp_alg_names[mp_alg] : "unknown");
 		}
 	}
 
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 05/12] Fix typo in tunnel code (o_key vs. i_key).
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Herbert Xu, Andreas Henriksson
In-Reply-To: <1192179407-22461-4-git-send-email-andreas@fatal.se>

From: Herbert Xu <herbert@gondor.apana.org.au>

If a dotted quad ikey is specified for GRE tunnels, it gets set as the
okey instead.  This patch fixes it. (http://bugs.debian.org/200714)

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 ip/iptunnel.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index 828d80a..aee526b 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -113,7 +113,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
 			NEXT_ARG();
 			p->i_flags |= GRE_KEY;
 			if (strchr(*argv, '.'))
-				p->o_key = get_addr32(*argv);
+				p->i_key = get_addr32(*argv);
 			else {
 				if (get_unsigned(&uval, *argv, 0)<0) {
 					fprintf(stderr, "invalid value of \"ikey\"\n");
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 07/12] Fix corruption when using batch files with comments and broken lines.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Andreas Henriksson
In-Reply-To: <1192179407-22461-6-git-send-email-andreas@fatal.se>

I could only reproduce on some old pentium machine, don't know why.
Anyway, the patch fixes a problem resulting in a double free
that occurs when using batch files that contains a special combination
of broken up lines and comments as reported in:
http://bugs.debian.org/398912

Thanks to Michal Pokrywka <mpokrywka@hoga.pl> for testcase and information
on which conditions problem could be reproduced under.

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 include/utils.h |    2 +-
 lib/utils.c     |    8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/utils.h b/include/utils.h
index 7da2b29..9ee55fd 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -144,7 +144,7 @@ int print_timestamp(FILE *fp);
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 extern int cmdlineno;
-extern size_t getcmdline(char **line, size_t *len, FILE *in);
+extern ssize_t getcmdline(char **line, size_t *len, FILE *in);
 extern int makeargs(char *line, char *argv[], int maxargs);
 
 #endif /* __UTILS_H__ */
diff --git a/lib/utils.c b/lib/utils.c
index 4c42dfd..ffef6fe 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -642,9 +642,9 @@ int print_timestamp(FILE *fp)
 int cmdlineno;
 
 /* Like glibc getline but handle continuation lines and comments */
-size_t getcmdline(char **linep, size_t *lenp, FILE *in)
+ssize_t getcmdline(char **linep, size_t *lenp, FILE *in)
 {
-	size_t cc;
+	ssize_t cc;
 	char *cp;
 
 	if ((cc = getline(linep, lenp, in)) < 0)
@@ -672,9 +672,11 @@ size_t getcmdline(char **linep, size_t *lenp, FILE *in)
 		if (cp)
 			*cp = '\0';
 
-		*linep = realloc(*linep, strlen(*linep) + strlen(line1) + 1);
+		*lenp = strlen(*linep) + strlen(line1) + 1;
+		*linep = realloc(*linep, *lenp);
 		if (!*linep) {
 			fprintf(stderr, "Out of memory\n");
+			*lenp = 0;
 			return -1;
 		}
 		cc += cc1 - 2;
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 04/12] Fix up various problems in netbug script.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger
  Cc: netdev, Javier Fernández-Sanguino Peña,
	Andreas Henriksson
In-Reply-To: <1192179407-22461-3-git-send-email-andreas@fatal.se>

From: Javier Fernández-Sanguino Peña <jfs@computer.org>

Fix race conditions and temporary file symlink attacks.
See http://bugs.debian.org/289541

Additional improvements by Allard Hoeve <allard@byte.nl> and others.
See http://bugs.debian.org/313540, http://bugs.debian.org/313541,
and http://bugs.debian.org/313544.

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 misc/netbug |   24 ++++++++----------------
 1 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/misc/netbug b/misc/netbug
index 6d13c8e..7b6ecea 100644
--- a/misc/netbug
+++ b/misc/netbug
@@ -1,23 +1,16 @@
 #! /bin/bash
 
+set -e
+
 echo -n "Send network configuration summary to [ENTER means kuznet@ms2.inr.ac.ru] "
 IFS="" read mail || exit 1
 [ -z "$mail" ] && mail=kuznet@ms2.inr.ac.ru
 
+netbug=`mktemp -d -t netbug.XXXXXX` || (echo "$0: Cannot create temporary directory" >&2; exit 1; )
+netbugtar=`tempfile -d $netbug --suffix=tar.gz` || (echo "$0: Cannot create temporary file" >&2; exit 1; )
+tmppath=$netbug
+trap "/bin/rm -rf $netbug $netbugtar" 0 1 2 3 13 15
 
-netbug=""
-while [ "$netbug" = "" ]; do
-	netbug=`echo netbug.$$.$RANDOM`
-	if [ -e /tmp/$netbug ]; then
-		netbug=""
-	fi
-done
-
-tmppath=/tmp/$netbug
-
-trap "rm -rf $tmppath $tmppath.tar.gz" 0 SIGINT
-
-mkdir $tmppath
 mkdir $tmppath/net
 
 cat /proc/slabinfo > $tmppath/slabinfo
@@ -44,9 +37,8 @@ if [ -e /proc/net/tcp6 ]; then
 fi
 
 cd /tmp
-tar c $netbug | gzip -9c > $netbug.tar.gz
-
-uuencode $netbug.tar.gz $netbug.tar.gz | mail -s $netbug "$mail"
+tar c $tmppath | gzip -9c > $netbugtar
+uuencode $netbugtar $netbugtar | mail -s $netbug "$mail"
 
 echo "Sending to <$mail>; subject is $netbug"
 
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 06/12] Remove bogus reference to tc-filters(8) from tc(8) manpage.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Andreas Barth, Andreas Henriksson
In-Reply-To: <1192179407-22461-5-git-send-email-andreas@fatal.se>

From: Andreas Barth <aba@not.so.argh.org>

Spotted by Aleš Kozumplík <al_es@seznam.cz>
(http://bugs.debian.org/289225)

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 man/man8/tc.8 |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/man/man8/tc.8 b/man/man8/tc.8
index b9b8039..6acd572 100644
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -202,8 +202,7 @@ qdiscs will use all three:
 tc filters
 If tc filters are attached to a class, they are consulted first 
 for relevant instructions. Filters can match on all fields of a packet header, 
-as well as on the firewall mark applied by ipchains or iptables. See 
-.BR tc-filters (8).
+as well as on the firewall mark applied by ipchains or iptables. 
 .TP
 Type of Service
 Some qdiscs have built in rules for classifying packets based on the TOS field.
@@ -242,8 +241,7 @@ qdiscs applies.
 .TP 
 FILTERS
 Filters have a three part ID, which is only needed when using a hashed
-filter hierarchy, for which see
-.BR tc-filters (8).
+filter hierarchy.
 .SH UNITS
 All parameters accept a floating point number, possibly followed by a unit.
 .P
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 03/12] Prevent renaming interfaces to empty string.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Alexander Wirt, Andreas Henriksson
In-Reply-To: <1192179407-22461-2-git-send-email-andreas@fatal.se>

From: Alexander Wirt <formorer@debian.org>


Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 ip/iplink.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index 4060845..da1f64e 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -670,6 +670,10 @@ static int do_set(int argc, char **argv)
 	}
 
 	if (newname && strcmp(dev, newname)) {
+		if (strlen(newname) == 0) {
+		    printf("\"\" is not valid device identifier\n");
+		    return -1;
+		}
 		if (do_changename(dev, newname) < 0)
 			return -1;
 		dev = newname;
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH 09/12] Add new rtacct/nstat manpages and additional symlinks.
From: Andreas Henriksson @ 2007-10-12  8:56 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Andreas Henriksson
In-Reply-To: <1192179407-22461-8-git-send-email-andreas@fatal.se>

Symlink rtstat(8) and ctstat(8) to lnstat(8).
Add rtacct/nstat manpage based on doc/nstat.sgml as rtacct(8).
Symlink nstat(8) to rtacct(8).
Add arpd(8) symlink based on doc/arpd.sgml.

Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
 Makefile          |    3 ++
 man/man8/arpd.8   |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 man/man8/rtacct.8 |   48 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 0 deletions(-)
 create mode 100644 man/man8/arpd.8
 create mode 100644 man/man8/rtacct.8

diff --git a/Makefile b/Makefile
index af0d5e4..6c976dd 100644
--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,9 @@ install: all
 	install -m 0755 -d $(DESTDIR)$(MANDIR)/man8
 	install -m 0644 $(shell find man/man8 -maxdepth 1 -type f) $(DESTDIR)$(MANDIR)/man8
 	ln -sf tc-bfifo.8  $(DESTDIR)$(MANDIR)/man8/tc-pfifo.8
+	ln -sf lnstat.8  $(DESTDIR)$(MANDIR)/man8/rtstat.8
+	ln -sf lnstat.8  $(DESTDIR)$(MANDIR)/man8/ctstat.8
+	ln -sf rtacct.8  $(DESTDIR)$(MANDIR)/man8/nstat.8
 	install -m 0755 -d $(DESTDIR)$(MANDIR)/man3
 	install -m 0644 $(shell find man/man3 -maxdepth 1 -type f) $(DESTDIR)$(MANDIR)/man3
 
diff --git a/man/man8/arpd.8 b/man/man8/arpd.8
new file mode 100644
index 0000000..d172600
--- /dev/null
+++ b/man/man8/arpd.8
@@ -0,0 +1,66 @@
+.TH ARPD 8 "28 June, 2007"
+
+.SH NAME
+arpd \- userspace arp daemon.
+
+.SH SYNOPSIS
+Usage: arpd [ -lk ] [ -a N ] [ -b dbase ] [ -f file ] [ interfaces ]
+
+.SH DESCRIPTION
+The
+.B arpd
+daemon collects gratuitous ARP information, saving it on local disk and feeding it to kernel on demand to avoid redundant broadcasting due to limited size of kernel ARP cache.
+
+.SH OPTIONS
+.TP
+-h -?
+Print help
+.TP
+-l
+Dump arpd database to stdout and exit. Output consists of three columns: interface index, IP address and MAC address. Negative entries for dead hosts are also shown, in this case MAC address is replaced by word FAILED followed by colon and time when the fact that host is dead was proven the last time.
+.TP
+-f <FILE>
+Read and load arpd database from FILE in text format similar dumped by option -l. Exit after load, probably listing resulting database, if option -l is also given. If FILE is -, stdin is read to get ARP table.
+.TP
+-b <DATABASE>
+location of database file. Default location is /var/lib/arpd/arpd.db
+.TP
+-a <NUMBER>
+arpd not only passively listens ARP on wire, but also send brodcast queries itself. NUMBER is number of such queries to make before destination is considered as dead. When arpd is started as kernel helper (i.e. with app_solicit enabled in sysctl or even with option -k) without this option and still did not learn enough information, you can observe 1 second gaps in service. Not fatal, but not good.
+.TP
+-k
+Suppress sending broadcast queries by kernel. It takes sense together with option -a.
+.TP
+-n <TIME>
+Timeout of negative cache. When resolution fails arpd suppresses further attempts to resolve for this period. It makes sense only together with option -k This timeout should not be too much longer than boot time of a typical host not supporting gratuitous ARP. Default value is 60 seconds.
+.TP
+-r <RATE>
+Maximal steady rate of broadcasts sent by arpd in packets per second. Default value is 1.
+.TP
+-B <NUMBER>
+Number of broadcasts sent by <tt/arpd/ back to back. Default value is 3. Together with option <tt/-R/ this option allows to police broadcasting not to exceed B+R*T over any interval of time T.
+.P
+<INTERFACE> is the name of networking interface to watch. If no interfaces given, arpd monitors all the interfaces. In this case arpd does not adjust sysctl parameters, it is supposed user does this himself after arpd is started.
+.P
+Signals
+.br
+arpd exits gracefully syncing database and restoring adjusted sysctl parameters, when receives SIGINT or SIGTERM. SIGHUP syncs database to disk. SIGUSR1 sends some statistics to syslog. Effect of another signals is undefined, they may corrupt database and leave sysctl praameters in an unpredictable state.
+.P
+Note
+.br
+In order for arpd to be able to serve as ARP resolver, kernel must be compiled with the option CONFIG_ARPD and, in the case when interface list in not given on command line, variable app_solicit on interfaces of interest should be in /proc/sys/net/ipv4/neigh/*. If this is not made arpd still collects gratuitous ARP information in its database.
+.SH EXAMPLES
+.TP
+arpd -b /var/tmp/arpd.db
+Start arpd to collect gratuitous ARP, but not messing with kernel functionality.
+.TP
+killall arpd ; arpd -l -b /var/tmp/arpd.db
+Look at result after some time.
+.TP
+arpd -b /var/tmp/arpd.db -a 1 eth0 eth1
+Enable kernel helper, leaving leading role to kernel.
+.TP
+arpd -b /var/tmp/arpd.db -a 3 -k eth0 eth1
+Completely replace kernel resolution on interfaces eth0 and eth1. In this case kernel still does unicast probing to validate entries, but all the broadcast activity is suppressed and made under authority of arpd.
+.PP
+This is mode which arpd is supposed to work normally. It is not default just to prevent occasional enabling of too aggressive mode occasionally.
diff --git a/man/man8/rtacct.8 b/man/man8/rtacct.8
new file mode 100644
index 0000000..fb9afe8
--- /dev/null
+++ b/man/man8/rtacct.8
@@ -0,0 +1,48 @@
+.TH RTACCT 8 "27 June, 2007"
+
+.SH NAME
+nstat, rtacct - network statistics tools.
+
+.SH SYNOPSIS
+Usage: nstat [ -h?vVzrnasd:t: ] [ PATTERN [ PATTERN ] ]
+.br
+Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]
+
+.SH DESCRIPTION
+.B nstat
+and
+.B rtacct
+are simple tools to monitor kernel snmp counters and network interface statistics.
+
+.SH OPTIONS
+.TP
+-h -?
+Print help
+.TP
+-v -V
+Print version
+.TP
+-z
+Dump zero counters too. By default they are not shown.
+.TP
+-r
+Reset history.
+.TP
+-n
+Do not display anything, only update history.
+.TP
+-a
+Dump absolute values of counters. The default is to calculate increments since the previous use.
+.TP
+-s
+Do not update history, so that the next time you will see counters including values accumulated to the moment of this measurement too.
+.TP
+-d <INTERVAL>
+Run in daemon mode collecting statistics. <INTERVAL> is interval between measurements in seconds.
+.TP
+-t <INTERVAL>
+Time interval to average rates. Default value is 60 seconds.
+
+.SH SEE ALSO
+lnstat(8)
+
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH]race between open and disconnect in irda-usb
From: Oliver Neukum @ 2007-10-12  8:53 UTC (permalink / raw)
  To: Jean Tourrilhes, Nick Fedchik, netdev, USB development list,
	Samuel Ortiz

Hi,

it seems to me that irda_usb_net_open() must set self->netopen
under spinlock or disconnect() may fail to kill all URBs, if it is called
while an interface is opened.

Signed-off-by: Oliver Neukum <oneukum@suse.de>

	Regards
		Oliver

----

--- a/drivers/net/irda/irda-usb.c	2007-10-11 17:24:35.000000000 +0200
+++ b/drivers/net/irda/irda-usb.c	2007-10-11 17:30:30.000000000 +0200
@@ -1168,6 +1168,7 @@ static int stir421x_patch_device(struct 
 static int irda_usb_net_open(struct net_device *netdev)
 {
 	struct irda_usb_cb *self;
+	unsigned long flags;
 	char	hwname[16];
 	int i;
 	
@@ -1177,13 +1178,16 @@ static int irda_usb_net_open(struct net_
 	self = (struct irda_usb_cb *) netdev->priv;
 	IRDA_ASSERT(self != NULL, return -1;);
 
+	spin_lock_irqsave(&self->lock, flags);
 	/* Can only open the device if it's there */
 	if(!self->present) {
+		spin_unlock_irqrestore(&self->lock, flags);
 		IRDA_WARNING("%s(), device not present!\n", __FUNCTION__);
 		return -1;
 	}
 
 	if(self->needspatch) {
+		spin_unlock_irqrestore(&self->lock, flags);
 		IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
 		return -EIO ;
 	}
@@ -1198,6 +1202,7 @@ static int irda_usb_net_open(struct net_
 	/* To do *before* submitting Rx urbs and starting net Tx queue
 	 * Jean II */
 	self->netopen = 1;
+	spin_unlock_irqrestore(&self->lock, flags);
 
 	/* 
 	 * Now that everything should be initialized properly,


^ permalink raw reply

* Re: Regression in net-2.6.24?
From: David Miller @ 2007-10-12  8:39 UTC (permalink / raw)
  To: mchan; +Cc: shemminger, takano, netdev, ilpo.jarvinen
In-Reply-To: <1192179253.4788.14.camel@dell>

From: "Michael Chan" <mchan@broadcom.com>
Date: Fri, 12 Oct 2007 01:54:13 -0700

> On Thu, 2007-10-11 at 19:40 -0700, David Miller wrote:
> > Hmmm, the old code didn't do that and seemingly has the same
> > problem.  Also, if you look at the before-patch code and think
> > about what it does if we ->poll() multiple times for a single
> > interrupt the side-effects are essentially the same.
> > 
> 
> No, the old code before tonight's patch did this:
> 
> if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
> 	tp->last_tag = sblk->status_tag;
> 	rmb();
> }
> 
> before checking for more work.  The rmb() is there to make sure that the
> status tag is read and stored before we check for more work.

No I understand, thanks!

> [TG3]: Refine napi poll loop.
> 
> Need to read and store sblk->status_tag before checking for more work.
> The status tag is later written back to the hardware when enabling
> interrupts to acknowledge how much work has been processed.  If the
> order is reversed, we can end up acknowledging work we haven't
> processed.
> 
> When we detect tx error, it is more correct to return the rx
> work_done so far instead of 0.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>

I'll apply this, thanks a lot!

^ permalink raw reply

* Re: iproute2: resend of patches from Debian.
From: David Miller @ 2007-10-12  8:34 UTC (permalink / raw)
  To: formorer; +Cc: andreas, netdev
In-Reply-To: <20071012055053.GE30784@ned.snow-crash.org>

From: Alexander Wirt <formorer@formorer.de>
Date: Fri, 12 Oct 2007 07:50:54 +0200

> I took over the iproute package when it was in a pretty bad shape, most of
> the patches submitted were still applied at that time. I ever planed a
> carefull review of the patches and to submit them later, but due to real life
> reasons I never got so far. Thanks to Andreas (who will be on of the new
> maintainers of the package) for doing that for me. 
> 
> Some of the patches also need some reworking before applying them outside of
> a distribution. But you are right, it was my fault not to send in the patches
> and I promise to give more patches back in the future (moving package
> development to git in the near future will help with that too).

Thanks for explaining the situation, hopefully we'll starighten
this all out.

^ permalink raw reply

* Re: Regression in net-2.6.24?
From: Michael Chan @ 2007-10-12  8:54 UTC (permalink / raw)
  To: David Miller; +Cc: shemminger, takano, netdev, ilpo.jarvinen
In-Reply-To: <20071011.194009.48528774.davem@davemloft.net>

On Thu, 2007-10-11 at 19:40 -0700, David Miller wrote:
> From: "Michael Chan" <mchan@broadcom.com>
> Date: Thu, 11 Oct 2007 20:17:16 -0700
>
> > > +               if (likely(!tg3_has_work(tp))) {
> > > +                       struct tg3_hw_status *sblk = tp->hw_status;
> > > +
> > 
> > --> new status block DMA
> > 
> > > +                       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
> > > +                               tp->last_tag = sblk->status_tag;
> > > +                               rmb();
> > > +                       } else
> > > +                               sblk->status &= ~SD_STATUS_UPDATED;
> > 
> > We need to read the sblk->status_tag before calling tg3_has_work().  If
> > a new status block DMA happens in between (shown above), tp->last_tag
> > will get the new tag and we will end up acknowledging work that we
> > haven't processed.
> 
> Hmmm, the old code didn't do that and seemingly has the same
> problem.  Also, if you look at the before-patch code and think
> about what it does if we ->poll() multiple times for a single
> interrupt the side-effects are essentially the same.
> 

No, the old code before tonight's patch did this:

if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
	tp->last_tag = sblk->status_tag;
	rmb();
}

before checking for more work.  The rmb() is there to make sure that the
status tag is read and stored before we check for more work.

> What's the crucial difference?
> 

This sequence only matters when we eventually terminate and tell the
hardware the last tag we've processed and turn on the interrupt.  If
there's a status block race condition, the hw will know when the tag
written back does not match the latest one and it will generate an
interrupt right away.  The sequence guarantees that the hw will see the
proper tag corresponding to the work processed by the driver.

[TG3]: Refine napi poll loop.

Need to read and store sblk->status_tag before checking for more work.
The status tag is later written back to the hardware when enabling
interrupts to acknowledge how much work has been processed.  If the
order is reversed, we can end up acknowledging work we haven't
processed.

When we detect tx error, it is more correct to return the rx
work_done so far instead of 0.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 417641a..055cc68 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3576,7 +3576,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
 	if (sblk->idx[0].tx_consumer != tp->tx_cons) {
 		tg3_tx(tp);
 		if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
-			return 0;
+			return work_done;
 	}
 
 	/* run RX thread, within the bounds set by NAPI.
@@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 {
 	struct tg3 *tp = container_of(napi, struct tg3, napi);
 	int work_done = 0;
+	struct tg3_hw_status *sblk = tp->hw_status;
 
 	while (1) {
 		work_done = tg3_poll_work(tp, work_done, budget);
@@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 		if (unlikely(work_done >= budget))
 			break;
 
-		if (likely(!tg3_has_work(tp))) {
-			struct tg3_hw_status *sblk = tp->hw_status;
-
-			if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
-				tp->last_tag = sblk->status_tag;
-				rmb();
-			} else
-				sblk->status &= ~SD_STATUS_UPDATED;
+		if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+			/* tp->last_tag is used in tg3_restart_ints() below
+			 * to tell the hw how much work has been processed,
+			 * so we must read it before checking for more work.
+			 */
+			tp->last_tag = sblk->status_tag;
+			rmb();
+		} else
+			sblk->status &= ~SD_STATUS_UPDATED;
 
+		if (likely(!tg3_has_work(tp))) {
 			netif_rx_complete(tp->dev, napi);
 			tg3_restart_ints(tp);
 			break;
@@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 	return work_done;
 
 tx_recovery:
+	/* work_done is guaranteed to be less than budget. */
 	netif_rx_complete(tp->dev, napi);
 	schedule_work(&tp->reset_task);
-	return 0;
+	return work_done;
 }
 
 static void tg3_irq_quiesce(struct tg3 *tp)





^ permalink raw reply related

* [PATCH] IPROUTE2: Support IPv4/IPv6 Tunnel
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2007-10-12  7:51 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, yoshfuji, yasuyuki.kozakai

Based on patch from Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

--- 
diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c
index 6468d99..cbbdf9d 100644
--- a/ip/ip6tunnel.c
+++ b/ip/ip6tunnel.c
@@ -52,6 +52,7 @@ static void usage(void) __attribute__((noreturn));
 static void usage(void)
 {
 	fprintf(stderr, "Usage: ip -f inet6 tunnel { add | change | del | show } [ NAME ]\n");
+	fprintf(stderr, "          [ mode { ip6ip6 | ipip6 | any } ]\n");
 	fprintf(stderr, "          [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n");
 	fprintf(stderr, "          [ encaplimit ELIM ]\n");
 	fprintf(stderr ,"          [ hoplimit HLIM ] [ tc TC ] [ fl FL ]\n");
@@ -116,7 +117,24 @@ static int parse_args(int argc, char **argv, struct ip6_tnl_parm *p)
 	memset(medium, 0, sizeof(medium));
 
 	while (argc > 0) {
-		if (strcmp(*argv, "remote") == 0) {
+		if (strcmp(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "ipv6/ipv6") == 0 ||
+			    strcmp(*argv, "ip6ip6") == 0)
+				p->proto = IPPROTO_IPV6;
+			else if (strcmp(*argv, "ip/ipv6") == 0 ||
+				 strcmp(*argv, "ipv4/ipv6") == 0 ||
+				 strcmp(*argv, "ipip6") == 0 ||
+				 strcmp(*argv, "ip4ip6") == 0)
+				p->proto = IPPROTO_IPIP;
+			else if (strcmp(*argv, "any/ipv6") == 0 ||
+				 strcmp(*argv, "any") == 0)
+				p->proto = 0;
+			else {
+                                fprintf(stderr,"Cannot guess tunnel mode.\n");
+                                exit(-1);
+                        }
+                } else if (strcmp(*argv, "remote") == 0) {
 			inet_prefix raddr;
 			NEXT_ARG();
 			get_prefix(&raddr, *argv, preferred_family);
diff --git a/ip/tunnel.c b/ip/tunnel.c
index 5fede2c..104340d 100644
--- a/ip/tunnel.c
+++ b/ip/tunnel.c
@@ -51,6 +51,9 @@ const char *tnl_strproto(__u8 proto)
 	case IPPROTO_IPV6:
 		strcpy(buf, "ipv6");
 		break;
+	case 0:
+		strcpy(buf, "any");
+		break;
 	default:
 		strcpy(buf, "unknown");
 		break;

-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

^ permalink raw reply related

* Re: 2.6.23-mm1
From: Andrew Morton @ 2007-10-12  7:13 UTC (permalink / raw)
  To: Al Viro; +Cc: KAMEZAWA Hiroyuki, linux-kernel, Sam Ravnborg, netdev
In-Reply-To: <20071012064658.GA8181@ftp.linux.org.uk>

On Fri, 12 Oct 2007 07:46:58 +0100 Al Viro <viro@ftp.linux.org.uk> wrote:

> On Thu, Oct 11, 2007 at 11:42:02PM -0700, Andrew Morton wrote:
> > On Fri, 12 Oct 2007 14:03:28 +0900 KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:
> > 
> > > On Thu, 11 Oct 2007 21:31:26 -0700
> > > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > 
> > > > 
> > > > ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.23/2.6.23-mm1/
> > > > 
> > > > - I've been largely avoiding applying anything since rc8-mm2 in an attempt
> > > >   to stabilise things for the 2.6.23 merge.
> > > > 
> > > On RHEL5/x86_64 environment,
> > > 
> > > ==
> > > [kamezawa@hannibal ref-2.6.23-mm1]$ make menuconfig
> > > Makefile:456: /home/kamezawa/ref-2.6.23-mm1/arch//Makefile: No such file or directory
> > > make: *** No rule to make target `/home/kamezawa/ref-2.6.23-mm1/arch//Makefile'.  Stop.
> > > ==
> > > 
> > > $(ARCH) cannot be detected automatically...
> > 
> > So you need to set $ARCH by hand?  I always do that so I didn't notice this.
> > 
> > > What information is useful for fixing this ?
> > 
> > Sam's email address ;)
> 
> More serious breakage happened to UML - include/asm-um/arch went straight
> to hell; I'll look into fixing that tomorrow...

I always forget to test uml.  But a quick test build seems to work until
it hits this:

arch/um/drivers/slip_kern.c: In function 'slip_init':
arch/um/drivers/slip_kern.c:34: error: 'struct net_device' has no member named 'header_cache_update'
arch/um/drivers/slip_kern.c:35: error: 'struct net_device' has no member named 'hard_header_cache'
arch/um/drivers/slip_kern.c:36: error: 'struct net_device' has no member named 'hard_header'

<looks at networking people>

^ permalink raw reply

* Re: iproute2: resend of patches from Debian.
From: Alexander Wirt @ 2007-10-12  5:50 UTC (permalink / raw)
  To: David Miller; +Cc: andreas, netdev
In-Reply-To: <20071011.153859.45731232.davem@davemloft.net>

David Miller schrieb am Donnerstag, den 11. Oktober 2007:

Hi David, 

> > If you want me to STFU please just say so and I'll give you all my
> > sincere appologies and go back to the status quo of no fixes shared
> > with others.
> 
> I applaud your efforts, it's not what the problem is.
> 
> I just wonder, therefore, when Alexander planned on submitting
> this sizable backlog of local iproute2 patches.
I took over the iproute package when it was in a pretty bad shape, most of
the patches submitted were still applied at that time. I ever planed a
carefull review of the patches and to submit them later, but due to real life
reasons I never got so far. Thanks to Andreas (who will be on of the new
maintainers of the package) for doing that for me. 

Some of the patches also need some reworking before applying them outside of
a distribution. But you are right, it was my fault not to send in the patches
and I promise to give more patches back in the future (moving package
development to git in the near future will help with that too).

Alex


^ permalink raw reply

* Re: iproute2: resend of patches from Debian.
From: Alexander Wirt @ 2007-10-12  5:55 UTC (permalink / raw)
  To: Lennart Sorensen; +Cc: Andreas Henriksson, netdev
In-Reply-To: <20071011192509.GA4004@csclub.uwaterloo.ca>

Lennart Sorensen schrieb am Donnerstag, den 11. Oktober 2007:

> On Thu, Oct 11, 2007 at 08:25:32PM +0200, Andreas Henriksson wrote:
> > Patch from debian iproute package.
> > 
> > diff -urNad iproute-20060323~/ip/iplink.c iproute-20060323/ip/iplink.c
> > --- iproute-20060323~/ip/iplink.c	2006-03-22 00:57:50.000000000 +0100
> > +++ iproute-20060323/ip/iplink.c	2006-09-08 21:07:14.000000000 +0200
> > @@ -384,6 +384,10 @@
> >  	}
> >  
> >  	if (newname && strcmp(dev, newname)) {
> > +		if (strlen(newname) == 0) {
> > +		    printf("\"\" is not valid device identifier\n",dev);
> > +		    return -1;
> > +		}
> >  		if (do_changename(dev, newname) < 0)
> >  			return -1;
> >  		dev = newname;
> 
> Isn't that printf missing somewhere for the 'dev' argument to go?
Uhm, yes you are right. It don't hurts but its useless, so the 'dev' argument
should be removed. 

Thanks
Alex


^ permalink raw reply

* Re: authenc compile warnings in current net-2.6.24
From: Oliver Hartkopp @ 2007-10-12  6:15 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, netdev

Hi Dave,

this compile fix seems not to be applied (maybe my compiler is the only 
one who complains ;-)

Acked-by: Oliver Hartkopp <oliver@hartkopp.net>

Thanks!


On Thu, Oct 11, 2007 at 11:23:30AM +0800, Herbert Xu wrote:
>
> Yeah I've added a fix in the cryptodev tree.

Oh and here's the actual patch.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
1cd6038ce42447f9a32e6d138af0b69ad56ea627
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 0b29a6a..126a529 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -84,8 +84,8 @@ static int crypto_authenc_hash(struct aead_request *req)
 		.tfm = auth,
 	};
 	u8 *hash = aead_request_ctx(req);
-	struct scatterlist *dst;
-	unsigned int cryptlen;
+	struct scatterlist *dst = req->dst;
+	unsigned int cryptlen = req->cryptlen;
 	int err;
 
 	hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), 
@@ -100,8 +100,6 @@ static int crypto_authenc_hash(struct aead_request *req)
 	if (err)
 		goto auth_unlock;
 
-	cryptlen = req->cryptlen;
-	dst = req->dst;
 	err = crypto_hash_update(&desc, dst, cryptlen);
 	if (err)
 		goto auth_unlock;
@@ -159,8 +157,8 @@ static int crypto_authenc_verify(struct aead_request *req)
 	};
 	u8 *ohash = aead_request_ctx(req);
 	u8 *ihash;
-	struct scatterlist *src;
-	unsigned int cryptlen;
+	struct scatterlist *src = req->src;
+	unsigned int cryptlen = req->cryptlen;
 	unsigned int authsize;
 	int err;
 
@@ -177,8 +175,6 @@ static int crypto_authenc_verify(struct aead_request *req)
 	if (err)
 		goto auth_unlock;
 
-	cryptlen = req->cryptlen;
-	src = req->src;
 	err = crypto_hash_update(&desc, src, cryptlen);
 	if (err)
 		goto auth_unlock;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply related

* Re: net-2.6.24 breaks powerpc mysteriously
From: Paul Mackerras @ 2007-10-12  5:47 UTC (permalink / raw)
  To: David Miller; +Cc: akpm, netdev, sam, benh
In-Reply-To: <20071011.221845.63126874.davem@davemloft.net>

David Miller writes:

> Here is the patch I'm putting through some paces, let me know if
> it solves the powerpc problem.

Looks fine to me.

Acked-by: Paul Mackerras <paulus@samba.org>

Thanks!

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox