summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-10-29 22:21:01 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-10-29 22:21:01 +0200
commit0eb4188f9ccf186f1a01800fbc3c54724a6c0a2a (patch)
tree1a7ba72453903637c93cfea87b960afca17703f3 /kernel
parent2797afef4fcb1675dcbb64cc2568dc2be5a3a345 (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')
-rw-r--r--kernel/include/linux/netfilter/ip_set_chash.h20
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;
}