diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2013-04-09 04:57:20 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-09 15:04:16 -0400 |
commit | 6eb4c7e96e19fd2c38a103472048fc0e0e0a3ec3 (patch) | |
tree | b1a7a2ef0b8ec7771722beb75187199c04f31ebe /include | |
parent | 02f815cb6d3f57914228be84df9613ee5a01c2e6 (diff) |
netfilter: ipset: hash:*net*: nomatch flag not excluded on set resize
If a resize is triggered the nomatch flag is not excluded at hashing,
which leads to the element missed at lookup in the resized set.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netfilter/ipset/ip_set_ahash.h | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h index 01d25e6fc792..0214c4c146fa 100644 --- a/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/include/linux/netfilter/ipset/ip_set_ahash.h | |||
@@ -291,6 +291,7 @@ ip_set_hash_destroy(struct ip_set *set) | |||
291 | #define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) | 291 | #define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) |
292 | #define type_pf_data_next TOKEN(TYPE, PF, _data_next) | 292 | #define type_pf_data_next TOKEN(TYPE, PF, _data_next) |
293 | #define type_pf_data_flags TOKEN(TYPE, PF, _data_flags) | 293 | #define type_pf_data_flags TOKEN(TYPE, PF, _data_flags) |
294 | #define type_pf_data_reset_flags TOKEN(TYPE, PF, _data_reset_flags) | ||
294 | #ifdef IP_SET_HASH_WITH_NETS | 295 | #ifdef IP_SET_HASH_WITH_NETS |
295 | #define type_pf_data_match TOKEN(TYPE, PF, _data_match) | 296 | #define type_pf_data_match TOKEN(TYPE, PF, _data_match) |
296 | #else | 297 | #else |
@@ -385,9 +386,9 @@ type_pf_resize(struct ip_set *set, bool retried) | |||
385 | struct ip_set_hash *h = set->data; | 386 | struct ip_set_hash *h = set->data; |
386 | struct htable *t, *orig = h->table; | 387 | struct htable *t, *orig = h->table; |
387 | u8 htable_bits = orig->htable_bits; | 388 | u8 htable_bits = orig->htable_bits; |
388 | const struct type_pf_elem *data; | 389 | struct type_pf_elem *data; |
389 | struct hbucket *n, *m; | 390 | struct hbucket *n, *m; |
390 | u32 i, j; | 391 | u32 i, j, flags = 0; |
391 | int ret; | 392 | int ret; |
392 | 393 | ||
393 | retry: | 394 | retry: |
@@ -412,9 +413,16 @@ retry: | |||
412 | n = hbucket(orig, i); | 413 | n = hbucket(orig, i); |
413 | for (j = 0; j < n->pos; j++) { | 414 | for (j = 0; j < n->pos; j++) { |
414 | data = ahash_data(n, j); | 415 | data = ahash_data(n, j); |
416 | #ifdef IP_SET_HASH_WITH_NETS | ||
417 | flags = 0; | ||
418 | type_pf_data_reset_flags(data, &flags); | ||
419 | #endif | ||
415 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); | 420 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); |
416 | ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0); | 421 | ret = type_pf_elem_add(m, data, AHASH_MAX(h), flags); |
417 | if (ret < 0) { | 422 | if (ret < 0) { |
423 | #ifdef IP_SET_HASH_WITH_NETS | ||
424 | type_pf_data_flags(data, flags); | ||
425 | #endif | ||
418 | read_unlock_bh(&set->lock); | 426 | read_unlock_bh(&set->lock); |
419 | ahash_destroy(t); | 427 | ahash_destroy(t); |
420 | if (ret == -EAGAIN) | 428 | if (ret == -EAGAIN) |
@@ -836,9 +844,9 @@ type_pf_tresize(struct ip_set *set, bool retried) | |||
836 | struct ip_set_hash *h = set->data; | 844 | struct ip_set_hash *h = set->data; |
837 | struct htable *t, *orig = h->table; | 845 | struct htable *t, *orig = h->table; |
838 | u8 htable_bits = orig->htable_bits; | 846 | u8 htable_bits = orig->htable_bits; |
839 | const struct type_pf_elem *data; | 847 | struct type_pf_elem *data; |
840 | struct hbucket *n, *m; | 848 | struct hbucket *n, *m; |
841 | u32 i, j; | 849 | u32 i, j, flags = 0; |
842 | int ret; | 850 | int ret; |
843 | 851 | ||
844 | /* Try to cleanup once */ | 852 | /* Try to cleanup once */ |
@@ -873,10 +881,17 @@ retry: | |||
873 | n = hbucket(orig, i); | 881 | n = hbucket(orig, i); |
874 | for (j = 0; j < n->pos; j++) { | 882 | for (j = 0; j < n->pos; j++) { |
875 | data = ahash_tdata(n, j); | 883 | data = ahash_tdata(n, j); |
884 | #ifdef IP_SET_HASH_WITH_NETS | ||
885 | flags = 0; | ||
886 | type_pf_data_reset_flags(data, &flags); | ||
887 | #endif | ||
876 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); | 888 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); |
877 | ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, | 889 | ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), flags, |
878 | ip_set_timeout_get(type_pf_data_timeout(data))); | 890 | ip_set_timeout_get(type_pf_data_timeout(data))); |
879 | if (ret < 0) { | 891 | if (ret < 0) { |
892 | #ifdef IP_SET_HASH_WITH_NETS | ||
893 | type_pf_data_flags(data, flags); | ||
894 | #endif | ||
880 | read_unlock_bh(&set->lock); | 895 | read_unlock_bh(&set->lock); |
881 | ahash_destroy(t); | 896 | ahash_destroy(t); |
882 | if (ret == -EAGAIN) | 897 | if (ret == -EAGAIN) |
@@ -1187,6 +1202,7 @@ type_pf_gc_init(struct ip_set *set) | |||
1187 | #undef type_pf_data_tlist | 1202 | #undef type_pf_data_tlist |
1188 | #undef type_pf_data_next | 1203 | #undef type_pf_data_next |
1189 | #undef type_pf_data_flags | 1204 | #undef type_pf_data_flags |
1205 | #undef type_pf_data_reset_flags | ||
1190 | #undef type_pf_data_match | 1206 | #undef type_pf_data_match |
1191 | 1207 | ||
1192 | #undef type_pf_elem | 1208 | #undef type_pf_elem |