From 0eb4188f9ccf186f1a01800fbc3c54724a6c0a2a Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 29 Oct 2010 22:21:01 +0200 Subject: Listing for hash types fixed The listing was incorrect for large sets, when multiple messages were required. I assume that one full hash bucket fills into one message, but that is true for all current hash types. --- kernel/include/linux/netfilter/ip_set_chash.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'kernel/include') diff --git a/kernel/include/linux/netfilter/ip_set_chash.h b/kernel/include/linux/netfilter/ip_set_chash.h index 6fd1d32..9a1e26c 100644 --- a/kernel/include/linux/netfilter/ip_set_chash.h +++ b/kernel/include/linux/netfilter/ip_set_chash.h @@ -567,6 +567,8 @@ type_pf_list(struct ip_set *set, struct slist *n; const struct type_pf_elem *data; u32 first = cb->args[2]; + /* We assume that one hash bucket fills into one page */ + void *incomplete; int i; atd = ipset_nest_start(skb, IPSET_ATTR_ADT); @@ -574,6 +576,7 @@ type_pf_list(struct ip_set *set, return -EFAULT; pr_debug("list hash set %s", set->name); for (; cb->args[2] < jhash_size(h->htable_bits); cb->args[2]++) { + incomplete = skb_tail_pointer(skb); slist_for_each(n, &h->htable[cb->args[2]]) { for (i = 0; i < h->array_size; i++) { data = chash_data(n, i); @@ -602,8 +605,13 @@ type_pf_list(struct ip_set *set, return 0; nla_put_failure: - nla_nest_cancel(skb, nested); + nlmsg_trim(skb, incomplete); ipset_nest_end(skb, atd); + if (unlikely(first == cb->args[2])) { + pr_warn("Can't list set %s: one bucket does not fit into " + "a message. Please report it!\n", set->name); + cb->args[2] = 0; + } return 0; } @@ -993,12 +1001,15 @@ type_pf_tlist(struct ip_set *set, struct slist *n; const struct type_pf_elem *data; u32 first = cb->args[2]; + /* We assume that one hash bucket fills into one page */ + void *incomplete; int i; atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) return -EFAULT; for (; cb->args[2] < jhash_size(h->htable_bits); cb->args[2]++) { + incomplete = skb_tail_pointer(skb); slist_for_each(n, &h->htable[cb->args[2]]) { for (i = 0; i < h->array_size; i++) { data = chash_tdata(n, i); @@ -1029,8 +1040,13 @@ type_pf_tlist(struct ip_set *set, return 0; nla_put_failure: - nla_nest_cancel(skb, nested); + nlmsg_trim(skb, incomplete); ipset_nest_end(skb, atd); + if (unlikely(first == cb->args[2])) { + pr_warn("Can't list set %s: one bucket does not fit into " + "a message. Please report it!\n", set->name); + cb->args[2] = 0; + } return 0; } -- cgit v1.2.3