(usagi-users 03599) [PATCH] bug in neighbour.c ?
Olivier MATZ <[email protected]>
| Newsgroups | gmane.linux.ipv6.usagi.users |
|---|---|
| Message-ID | <[email protected]> |
Hi, I think there is a bug in net/core/neighbour.c, if we dump the neighbour table using 'ip neigh show', I think it will loop infinitely if there is some neighbours in the tables. Can you please have a look at my patch ? Regards, Olivier
net_core_neighbour__don_t_loop.diff
(text/plain, 1.8 KB)
Index: neighbour.c
===================================================================
RCS file: /usr/cvs/USAGI26/net/core/neighbour.c,v
retrieving revision 1.3
diff -u -r1.3 neighbour.c
--- neighbour.c 24 Nov 2005 15:12:52 -0000 1.3
+++ neighbour.c 6 Feb 2006 11:00:08 -0000
@@ -2124,6 +2124,8 @@
}
rc = skb->len;
+ h = 0;
+ idx = 0;
out:
cb->args[1] = h;
cb->args[2] = idx;
@@ -2158,6 +2160,8 @@
read_unlock_bh(&tbl->lock);
}
rc = skb->len;
+ h = 0;
+ idx = 0;
out:
cb->args[1] = h;
cb->args[2] = idx;
@@ -2168,44 +2172,34 @@
{
struct neigh_table *tbl;
int t, family, s_t;
- long a1, a2, pa1, pa2;
+ long is_pneigh = 0;
read_lock(&neigh_tbl_lock);
family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
s_t = cb->args[0];
- a1 = cb->args[1];
- a2 = cb->args[2];
- pa1 = cb->args[1];
- pa2 = cb->args[2];
-
+
for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) {
if (t < s_t || (family && tbl->family != family))
continue;
if (t > s_t)
- memset(&cb->args[1], 0, sizeof(cb->args) -
- sizeof(cb->args[0]));
- cb->args[1] = a1;
- cb->args[2] = a2;
- if (neigh_dump_table(tbl, skb, cb) < 0)
- break;
- a1 = cb->args[1];
- a2 = cb->args[2];
-
- cb->args[1] = pa1;
- cb->args[2] = pa2;
- if (pneigh_dump_table(tbl, skb, cb) < 0)
- break;
- pa1 = cb->args[1];
- pa2 = cb->args[2];
+ cb->args[3] = 0;
+
+ for ( is_pneigh = cb->args[3]; is_pneigh < 2 ; is_pneigh++ ) {
+ if ( !is_pneigh && neigh_dump_table(tbl, skb, cb) < 0 )
+ goto out;
+
+ else if ( is_pneigh && pneigh_dump_table(tbl, skb, cb) < 0 )
+ goto out;
+ }
}
- read_unlock(&neigh_tbl_lock);
+ out:
cb->args[0] = t;
+ cb->args[3] = is_pneigh;
/*
* XXX: Fix me! currently only neigh's status is reported.
*/
- cb->args[1] = a1;
- cb->args[2] = a2;
+ read_unlock(&neigh_tbl_lock);
return skb->len;
}