Harald Welte wrote:
> So if there's now a majority of people who want to delete the ID: Go for
> it :)
Found the patch again. What it does is:
- note entry of next conntrack to be dumped and keep a reference to it
- when continuing, look for the conntrack and continue at it if its
still there
- if not, dump the entire bucket again
In theory we could end up in an endless loop if the conntrack entry
we're keeping the reference to is deleted everytime we want to
continue dumping. It shouldn't be triggerable intentionally because
of the jenkins hash though. If there are no objections I'll port
it to nf_conntrack_netlink and submit it.
-------------- next part --------------
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index e0b5926..5a1769d 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -387,38 +387,52 @@ nfattr_failure:
static int ctnetlink_done(struct netlink_callback *cb)
{
DEBUGP("entered %s\n", __FUNCTION__);
+ if (cb->args[1])
+ ip_conntrack_put(cb->args[1]);
return 0;
}
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct ip_conntrack *ct = NULL;
+ struct ip_conntrack *ct;
struct ip_conntrack_tuple_hash *h;
struct list_head *i;
- u_int32_t *id = (u_int32_t *) &cb->args[1];
DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__,
cb->args[0], *id);
read_lock_bh(&ip_conntrack_lock);
- for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) {
+ for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
+restart:
list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
h = (struct ip_conntrack_tuple_hash *) i;
if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue;
ct = tuplehash_to_ctrack(h);
- if (ct->id <= *id)
- continue;
+ if (cb->args[1]) {
+ if (ct == cb->args[1]) {
+ ip_conntrack_put(cb->args[1]);
+ cb->args[1] = NULL;
+ } else
+ continue;
+ }
if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
IPCTNL_MSG_CT_NEW,
- 1, ct) < 0)
+ 1, ct) < 0) {
+ nf_conntrack_get(&ct->ct_general);
+ cb->args[1] = ct;
goto out;
- *id = ct->id;
+ }
+ }
+ if (cb->args[1]) {
+ ip_conntrack_put(cb->args[1]);
+ cb->args[1] = NULL;
+ goto restart;
}
}
-out:
+out:
read_unlock_bh(&ip_conntrack_lock);
DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);