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/linux | |
| 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/linux')
| -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 |
