diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2010-10-29 22:21:01 +0200 |
---|---|---|
committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2010-10-29 22:21:01 +0200 |
commit | 0eb4188f9ccf186f1a01800fbc3c54724a6c0a2a (patch) | |
tree | 1a7ba72453903637c93cfea87b960afca17703f3 /kernel/include/linux | |
parent | 2797afef4fcb1675dcbb64cc2568dc2be5a3a345 (diff) |
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.
Diffstat (limited to 'kernel/include/linux')
-rw-r--r-- | kernel/include/linux/netfilter/ip_set_chash.h | 20 |
1 files changed, 18 insertions, 2 deletions
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; } |