diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2011-06-16 12:40:55 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-06-16 12:40:55 -0400 |
commit | 5416219e5ca4504ea80d662fdda7337e52e86ee5 (patch) | |
tree | b98c31ccbcb1d36fadac61e4862655749998af43 | |
parent | 619c15171f6f58681013cdd439632505fd563ba6 (diff) |
netfilter: ipset: timeout can be modified for already added elements
When an element to a set with timeout added, one can change the timeout
by "readding" the element with the "-exist" flag. That means the timeout
value is reset to the specified one (or to the default from the set
specification if the "timeout n" option is not used). Example
ipset add foo 1.2.3.4 timeout 10
ipset add foo 1.2.3.4 timeout 600 -exist
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter/ipset/ip_set.h | 3 | ||||
-rw-r--r-- | include/linux/netfilter/ipset/ip_set_ahash.h | 15 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_bitmap_ip.c | 20 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_bitmap_ipmac.c | 21 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_bitmap_port.c | 20 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ip.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipport.c | 12 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipportip.c | 12 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipportnet.c | 12 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_net.c | 8 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_netport.c | 12 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_list_set.c | 92 |
12 files changed, 136 insertions, 101 deletions
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 5a262e3ae715..277b7fbc7fb2 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h | |||
@@ -214,7 +214,8 @@ enum ip_set_feature { | |||
214 | 214 | ||
215 | struct ip_set; | 215 | struct ip_set; |
216 | 216 | ||
217 | typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout); | 217 | typedef int (*ipset_adtfn)(struct ip_set *set, void *value, |
218 | u32 timeout, u32 flags); | ||
218 | 219 | ||
219 | /* Set type, variant-specific part */ | 220 | /* Set type, variant-specific part */ |
220 | struct ip_set_type_variant { | 221 | struct ip_set_type_variant { |
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h index ac3c822eb39a..36cf4dc703bb 100644 --- a/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/include/linux/netfilter/ipset/ip_set_ahash.h | |||
@@ -349,7 +349,7 @@ retry: | |||
349 | /* Add an element to a hash and update the internal counters when succeeded, | 349 | /* Add an element to a hash and update the internal counters when succeeded, |
350 | * otherwise report the proper error code. */ | 350 | * otherwise report the proper error code. */ |
351 | static int | 351 | static int |
352 | type_pf_add(struct ip_set *set, void *value, u32 timeout) | 352 | type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags) |
353 | { | 353 | { |
354 | struct ip_set_hash *h = set->data; | 354 | struct ip_set_hash *h = set->data; |
355 | struct htable *t; | 355 | struct htable *t; |
@@ -388,7 +388,7 @@ out: | |||
388 | * and free up space if possible. | 388 | * and free up space if possible. |
389 | */ | 389 | */ |
390 | static int | 390 | static int |
391 | type_pf_del(struct ip_set *set, void *value, u32 timeout) | 391 | type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags) |
392 | { | 392 | { |
393 | struct ip_set_hash *h = set->data; | 393 | struct ip_set_hash *h = set->data; |
394 | struct htable *t = h->table; | 394 | struct htable *t = h->table; |
@@ -463,7 +463,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) | |||
463 | 463 | ||
464 | /* Test whether the element is added to the set */ | 464 | /* Test whether the element is added to the set */ |
465 | static int | 465 | static int |
466 | type_pf_test(struct ip_set *set, void *value, u32 timeout) | 466 | type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags) |
467 | { | 467 | { |
468 | struct ip_set_hash *h = set->data; | 468 | struct ip_set_hash *h = set->data; |
469 | struct htable *t = h->table; | 469 | struct htable *t = h->table; |
@@ -776,7 +776,7 @@ retry: | |||
776 | } | 776 | } |
777 | 777 | ||
778 | static int | 778 | static int |
779 | type_pf_tadd(struct ip_set *set, void *value, u32 timeout) | 779 | type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) |
780 | { | 780 | { |
781 | struct ip_set_hash *h = set->data; | 781 | struct ip_set_hash *h = set->data; |
782 | struct htable *t = h->table; | 782 | struct htable *t = h->table; |
@@ -784,6 +784,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout) | |||
784 | struct hbucket *n; | 784 | struct hbucket *n; |
785 | struct type_pf_elem *data; | 785 | struct type_pf_elem *data; |
786 | int ret = 0, i, j = AHASH_MAX_SIZE + 1; | 786 | int ret = 0, i, j = AHASH_MAX_SIZE + 1; |
787 | bool flag_exist = flags & IPSET_FLAG_EXIST; | ||
787 | u32 key; | 788 | u32 key; |
788 | 789 | ||
789 | if (h->elements >= h->maxelem) | 790 | if (h->elements >= h->maxelem) |
@@ -799,7 +800,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout) | |||
799 | for (i = 0; i < n->pos; i++) { | 800 | for (i = 0; i < n->pos; i++) { |
800 | data = ahash_tdata(n, i); | 801 | data = ahash_tdata(n, i); |
801 | if (type_pf_data_equal(data, d)) { | 802 | if (type_pf_data_equal(data, d)) { |
802 | if (type_pf_data_expired(data)) | 803 | if (type_pf_data_expired(data) || flag_exist) |
803 | j = i; | 804 | j = i; |
804 | else { | 805 | else { |
805 | ret = -IPSET_ERR_EXIST; | 806 | ret = -IPSET_ERR_EXIST; |
@@ -833,7 +834,7 @@ out: | |||
833 | } | 834 | } |
834 | 835 | ||
835 | static int | 836 | static int |
836 | type_pf_tdel(struct ip_set *set, void *value, u32 timeout) | 837 | type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) |
837 | { | 838 | { |
838 | struct ip_set_hash *h = set->data; | 839 | struct ip_set_hash *h = set->data; |
839 | struct htable *t = h->table; | 840 | struct htable *t = h->table; |
@@ -905,7 +906,7 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) | |||
905 | #endif | 906 | #endif |
906 | 907 | ||
907 | static int | 908 | static int |
908 | type_pf_ttest(struct ip_set *set, void *value, u32 timeout) | 909 | type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) |
909 | { | 910 | { |
910 | struct ip_set_hash *h = set->data; | 911 | struct ip_set_hash *h = set->data; |
911 | struct htable *t = h->table; | 912 | struct htable *t = h->table; |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index ba2d16607f48..85b1cdf0a4b8 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c | |||
@@ -54,7 +54,7 @@ ip_to_id(const struct bitmap_ip *m, u32 ip) | |||
54 | } | 54 | } |
55 | 55 | ||
56 | static int | 56 | static int |
57 | bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) | 57 | bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags) |
58 | { | 58 | { |
59 | const struct bitmap_ip *map = set->data; | 59 | const struct bitmap_ip *map = set->data; |
60 | u16 id = *(u16 *)value; | 60 | u16 id = *(u16 *)value; |
@@ -63,7 +63,7 @@ bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static int | 65 | static int |
66 | bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) | 66 | bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags) |
67 | { | 67 | { |
68 | struct bitmap_ip *map = set->data; | 68 | struct bitmap_ip *map = set->data; |
69 | u16 id = *(u16 *)value; | 69 | u16 id = *(u16 *)value; |
@@ -75,7 +75,7 @@ bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) | |||
75 | } | 75 | } |
76 | 76 | ||
77 | static int | 77 | static int |
78 | bitmap_ip_del(struct ip_set *set, void *value, u32 timeout) | 78 | bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags) |
79 | { | 79 | { |
80 | struct bitmap_ip *map = set->data; | 80 | struct bitmap_ip *map = set->data; |
81 | u16 id = *(u16 *)value; | 81 | u16 id = *(u16 *)value; |
@@ -131,7 +131,7 @@ nla_put_failure: | |||
131 | /* Timeout variant */ | 131 | /* Timeout variant */ |
132 | 132 | ||
133 | static int | 133 | static int |
134 | bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) | 134 | bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) |
135 | { | 135 | { |
136 | const struct bitmap_ip *map = set->data; | 136 | const struct bitmap_ip *map = set->data; |
137 | const unsigned long *members = map->members; | 137 | const unsigned long *members = map->members; |
@@ -141,13 +141,13 @@ bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | static int | 143 | static int |
144 | bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) | 144 | bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) |
145 | { | 145 | { |
146 | struct bitmap_ip *map = set->data; | 146 | struct bitmap_ip *map = set->data; |
147 | unsigned long *members = map->members; | 147 | unsigned long *members = map->members; |
148 | u16 id = *(u16 *)value; | 148 | u16 id = *(u16 *)value; |
149 | 149 | ||
150 | if (ip_set_timeout_test(members[id])) | 150 | if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST)) |
151 | return -IPSET_ERR_EXIST; | 151 | return -IPSET_ERR_EXIST; |
152 | 152 | ||
153 | members[id] = ip_set_timeout_set(timeout); | 153 | members[id] = ip_set_timeout_set(timeout); |
@@ -156,7 +156,7 @@ bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | static int | 158 | static int |
159 | bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout) | 159 | bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) |
160 | { | 160 | { |
161 | struct bitmap_ip *map = set->data; | 161 | struct bitmap_ip *map = set->data; |
162 | unsigned long *members = map->members; | 162 | unsigned long *members = map->members; |
@@ -231,7 +231,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
231 | 231 | ||
232 | ip = ip_to_id(map, ip); | 232 | ip = ip_to_id(map, ip); |
233 | 233 | ||
234 | return adtfn(set, &ip, map->timeout); | 234 | return adtfn(set, &ip, map->timeout, flags); |
235 | } | 235 | } |
236 | 236 | ||
237 | static int | 237 | static int |
@@ -266,7 +266,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], | |||
266 | 266 | ||
267 | if (adt == IPSET_TEST) { | 267 | if (adt == IPSET_TEST) { |
268 | id = ip_to_id(map, ip); | 268 | id = ip_to_id(map, ip); |
269 | return adtfn(set, &id, timeout); | 269 | return adtfn(set, &id, timeout, flags); |
270 | } | 270 | } |
271 | 271 | ||
272 | if (tb[IPSET_ATTR_IP_TO]) { | 272 | if (tb[IPSET_ATTR_IP_TO]) { |
@@ -293,7 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], | |||
293 | 293 | ||
294 | for (; !before(ip_to, ip); ip += map->hosts) { | 294 | for (; !before(ip_to, ip); ip += map->hosts) { |
295 | id = ip_to_id(map, ip); | 295 | id = ip_to_id(map, ip); |
296 | ret = adtfn(set, &id, timeout); | 296 | ret = adtfn(set, &id, timeout, flags); |
297 | 297 | ||
298 | if (ret && !ip_set_eexist(ret, flags)) | 298 | if (ret && !ip_set_eexist(ret, flags)) |
299 | return ret; | 299 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index a274300b6a56..913a461382e4 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c | |||
@@ -99,7 +99,7 @@ bitmap_ipmac_exist(const struct ipmac_telem *elem) | |||
99 | /* Base variant */ | 99 | /* Base variant */ |
100 | 100 | ||
101 | static int | 101 | static int |
102 | bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) | 102 | bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags) |
103 | { | 103 | { |
104 | const struct bitmap_ipmac *map = set->data; | 104 | const struct bitmap_ipmac *map = set->data; |
105 | const struct ipmac *data = value; | 105 | const struct ipmac *data = value; |
@@ -117,7 +117,7 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | static int | 119 | static int |
120 | bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout) | 120 | bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags) |
121 | { | 121 | { |
122 | struct bitmap_ipmac *map = set->data; | 122 | struct bitmap_ipmac *map = set->data; |
123 | const struct ipmac *data = value; | 123 | const struct ipmac *data = value; |
@@ -146,7 +146,7 @@ bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | static int | 148 | static int |
149 | bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout) | 149 | bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags) |
150 | { | 150 | { |
151 | struct bitmap_ipmac *map = set->data; | 151 | struct bitmap_ipmac *map = set->data; |
152 | const struct ipmac *data = value; | 152 | const struct ipmac *data = value; |
@@ -212,7 +212,7 @@ nla_put_failure: | |||
212 | /* Timeout variant */ | 212 | /* Timeout variant */ |
213 | 213 | ||
214 | static int | 214 | static int |
215 | bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) | 215 | bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) |
216 | { | 216 | { |
217 | const struct bitmap_ipmac *map = set->data; | 217 | const struct bitmap_ipmac *map = set->data; |
218 | const struct ipmac *data = value; | 218 | const struct ipmac *data = value; |
@@ -231,15 +231,16 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) | |||
231 | } | 231 | } |
232 | 232 | ||
233 | static int | 233 | static int |
234 | bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) | 234 | bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) |
235 | { | 235 | { |
236 | struct bitmap_ipmac *map = set->data; | 236 | struct bitmap_ipmac *map = set->data; |
237 | const struct ipmac *data = value; | 237 | const struct ipmac *data = value; |
238 | struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); | 238 | struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); |
239 | bool flag_exist = flags & IPSET_FLAG_EXIST; | ||
239 | 240 | ||
240 | switch (elem->match) { | 241 | switch (elem->match) { |
241 | case MAC_UNSET: | 242 | case MAC_UNSET: |
242 | if (!data->ether) | 243 | if (!(data->ether || flag_exist)) |
243 | /* Already added without ethernet address */ | 244 | /* Already added without ethernet address */ |
244 | return -IPSET_ERR_EXIST; | 245 | return -IPSET_ERR_EXIST; |
245 | /* Fill the MAC address and activate the timer */ | 246 | /* Fill the MAC address and activate the timer */ |
@@ -251,7 +252,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) | |||
251 | elem->timeout = ip_set_timeout_set(timeout); | 252 | elem->timeout = ip_set_timeout_set(timeout); |
252 | break; | 253 | break; |
253 | case MAC_FILLED: | 254 | case MAC_FILLED: |
254 | if (!bitmap_expired(map, data->id)) | 255 | if (!(bitmap_expired(map, data->id) || flag_exist)) |
255 | return -IPSET_ERR_EXIST; | 256 | return -IPSET_ERR_EXIST; |
256 | /* Fall through */ | 257 | /* Fall through */ |
257 | case MAC_EMPTY: | 258 | case MAC_EMPTY: |
@@ -273,7 +274,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) | |||
273 | } | 274 | } |
274 | 275 | ||
275 | static int | 276 | static int |
276 | bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout) | 277 | bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) |
277 | { | 278 | { |
278 | struct bitmap_ipmac *map = set->data; | 279 | struct bitmap_ipmac *map = set->data; |
279 | const struct ipmac *data = value; | 280 | const struct ipmac *data = value; |
@@ -359,7 +360,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
359 | data.id -= map->first_ip; | 360 | data.id -= map->first_ip; |
360 | data.ether = eth_hdr(skb)->h_source; | 361 | data.ether = eth_hdr(skb)->h_source; |
361 | 362 | ||
362 | return adtfn(set, &data, map->timeout); | 363 | return adtfn(set, &data, map->timeout, flags); |
363 | } | 364 | } |
364 | 365 | ||
365 | static int | 366 | static int |
@@ -399,7 +400,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[], | |||
399 | 400 | ||
400 | data.id -= map->first_ip; | 401 | data.id -= map->first_ip; |
401 | 402 | ||
402 | ret = adtfn(set, &data, timeout); | 403 | ret = adtfn(set, &data, timeout, flags); |
403 | 404 | ||
404 | return ip_set_eexist(ret, flags) ? 0 : ret; | 405 | return ip_set_eexist(ret, flags) ? 0 : ret; |
405 | } | 406 | } |
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index 6b38eb8f6ed8..a3935eef76fc 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c | |||
@@ -40,7 +40,7 @@ struct bitmap_port { | |||
40 | /* Base variant */ | 40 | /* Base variant */ |
41 | 41 | ||
42 | static int | 42 | static int |
43 | bitmap_port_test(struct ip_set *set, void *value, u32 timeout) | 43 | bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags) |
44 | { | 44 | { |
45 | const struct bitmap_port *map = set->data; | 45 | const struct bitmap_port *map = set->data; |
46 | u16 id = *(u16 *)value; | 46 | u16 id = *(u16 *)value; |
@@ -49,7 +49,7 @@ bitmap_port_test(struct ip_set *set, void *value, u32 timeout) | |||
49 | } | 49 | } |
50 | 50 | ||
51 | static int | 51 | static int |
52 | bitmap_port_add(struct ip_set *set, void *value, u32 timeout) | 52 | bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags) |
53 | { | 53 | { |
54 | struct bitmap_port *map = set->data; | 54 | struct bitmap_port *map = set->data; |
55 | u16 id = *(u16 *)value; | 55 | u16 id = *(u16 *)value; |
@@ -61,7 +61,7 @@ bitmap_port_add(struct ip_set *set, void *value, u32 timeout) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | static int | 63 | static int |
64 | bitmap_port_del(struct ip_set *set, void *value, u32 timeout) | 64 | bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags) |
65 | { | 65 | { |
66 | struct bitmap_port *map = set->data; | 66 | struct bitmap_port *map = set->data; |
67 | u16 id = *(u16 *)value; | 67 | u16 id = *(u16 *)value; |
@@ -119,7 +119,7 @@ nla_put_failure: | |||
119 | /* Timeout variant */ | 119 | /* Timeout variant */ |
120 | 120 | ||
121 | static int | 121 | static int |
122 | bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) | 122 | bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) |
123 | { | 123 | { |
124 | const struct bitmap_port *map = set->data; | 124 | const struct bitmap_port *map = set->data; |
125 | const unsigned long *members = map->members; | 125 | const unsigned long *members = map->members; |
@@ -129,13 +129,13 @@ bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | static int | 131 | static int |
132 | bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) | 132 | bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) |
133 | { | 133 | { |
134 | struct bitmap_port *map = set->data; | 134 | struct bitmap_port *map = set->data; |
135 | unsigned long *members = map->members; | 135 | unsigned long *members = map->members; |
136 | u16 id = *(u16 *)value; | 136 | u16 id = *(u16 *)value; |
137 | 137 | ||
138 | if (ip_set_timeout_test(members[id])) | 138 | if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST)) |
139 | return -IPSET_ERR_EXIST; | 139 | return -IPSET_ERR_EXIST; |
140 | 140 | ||
141 | members[id] = ip_set_timeout_set(timeout); | 141 | members[id] = ip_set_timeout_set(timeout); |
@@ -144,7 +144,7 @@ bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) | |||
144 | } | 144 | } |
145 | 145 | ||
146 | static int | 146 | static int |
147 | bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout) | 147 | bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) |
148 | { | 148 | { |
149 | struct bitmap_port *map = set->data; | 149 | struct bitmap_port *map = set->data; |
150 | unsigned long *members = map->members; | 150 | unsigned long *members = map->members; |
@@ -225,7 +225,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
225 | 225 | ||
226 | port -= map->first_port; | 226 | port -= map->first_port; |
227 | 227 | ||
228 | return adtfn(set, &port, map->timeout); | 228 | return adtfn(set, &port, map->timeout, flags); |
229 | } | 229 | } |
230 | 230 | ||
231 | static int | 231 | static int |
@@ -259,7 +259,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], | |||
259 | 259 | ||
260 | if (adt == IPSET_TEST) { | 260 | if (adt == IPSET_TEST) { |
261 | id = port - map->first_port; | 261 | id = port - map->first_port; |
262 | return adtfn(set, &id, timeout); | 262 | return adtfn(set, &id, timeout, flags); |
263 | } | 263 | } |
264 | 264 | ||
265 | if (tb[IPSET_ATTR_PORT_TO]) { | 265 | if (tb[IPSET_ATTR_PORT_TO]) { |
@@ -277,7 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], | |||
277 | 277 | ||
278 | for (; port <= port_to; port++) { | 278 | for (; port <= port_to; port++) { |
279 | id = port - map->first_port; | 279 | id = port - map->first_port; |
280 | ret = adtfn(set, &id, timeout); | 280 | ret = adtfn(set, &id, timeout, flags); |
281 | 281 | ||
282 | if (ret && !ip_set_eexist(ret, flags)) | 282 | if (ret && !ip_set_eexist(ret, flags)) |
283 | return ret; | 283 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index 43bcce200129..368302001120 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c | |||
@@ -121,7 +121,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
121 | if (ip == 0) | 121 | if (ip == 0) |
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | 123 | ||
124 | return adtfn(set, &ip, h->timeout); | 124 | return adtfn(set, &ip, h->timeout, flags); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int | 127 | static int |
@@ -157,7 +157,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
157 | nip = htonl(ip); | 157 | nip = htonl(ip); |
158 | if (nip == 0) | 158 | if (nip == 0) |
159 | return -IPSET_ERR_HASH_ELEM; | 159 | return -IPSET_ERR_HASH_ELEM; |
160 | return adtfn(set, &nip, timeout); | 160 | return adtfn(set, &nip, timeout, flags); |
161 | } | 161 | } |
162 | 162 | ||
163 | if (tb[IPSET_ATTR_IP_TO]) { | 163 | if (tb[IPSET_ATTR_IP_TO]) { |
@@ -182,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
182 | nip = htonl(ip); | 182 | nip = htonl(ip); |
183 | if (nip == 0) | 183 | if (nip == 0) |
184 | return -IPSET_ERR_HASH_ELEM; | 184 | return -IPSET_ERR_HASH_ELEM; |
185 | ret = adtfn(set, &nip, timeout); | 185 | ret = adtfn(set, &nip, timeout, flags); |
186 | 186 | ||
187 | if (ret && !ip_set_eexist(ret, flags)) | 187 | if (ret && !ip_set_eexist(ret, flags)) |
188 | return ret; | 188 | return ret; |
@@ -294,7 +294,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
294 | if (ipv6_addr_any(&ip.in6)) | 294 | if (ipv6_addr_any(&ip.in6)) |
295 | return -EINVAL; | 295 | return -EINVAL; |
296 | 296 | ||
297 | return adtfn(set, &ip, h->timeout); | 297 | return adtfn(set, &ip, h->timeout, flags); |
298 | } | 298 | } |
299 | 299 | ||
300 | static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { | 300 | static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { |
@@ -336,7 +336,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
336 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 336 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
337 | } | 337 | } |
338 | 338 | ||
339 | ret = adtfn(set, &ip, timeout); | 339 | ret = adtfn(set, &ip, timeout, flags); |
340 | 340 | ||
341 | return ip_set_eexist(ret, flags) ? 0 : ret; | 341 | return ip_set_eexist(ret, flags) ? 0 : ret; |
342 | } | 342 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 14281b6b8074..65c2ff4b27aa 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -138,7 +138,7 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
138 | 138 | ||
139 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); | 139 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); |
140 | 140 | ||
141 | return adtfn(set, &data, h->timeout); | 141 | return adtfn(set, &data, h->timeout, flags); |
142 | } | 142 | } |
143 | 143 | ||
144 | static int | 144 | static int |
@@ -192,7 +192,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
192 | if (adt == IPSET_TEST || | 192 | if (adt == IPSET_TEST || |
193 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 193 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
194 | tb[IPSET_ATTR_PORT_TO])) { | 194 | tb[IPSET_ATTR_PORT_TO])) { |
195 | ret = adtfn(set, &data, timeout); | 195 | ret = adtfn(set, &data, timeout, flags); |
196 | return ip_set_eexist(ret, flags) ? 0 : ret; | 196 | return ip_set_eexist(ret, flags) ? 0 : ret; |
197 | } | 197 | } |
198 | 198 | ||
@@ -224,7 +224,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
224 | for (p = port; p <= port_to; p++) { | 224 | for (p = port; p <= port_to; p++) { |
225 | data.ip = htonl(ip); | 225 | data.ip = htonl(ip); |
226 | data.port = htons(p); | 226 | data.port = htons(p); |
227 | ret = adtfn(set, &data, timeout); | 227 | ret = adtfn(set, &data, timeout, flags); |
228 | 228 | ||
229 | if (ret && !ip_set_eexist(ret, flags)) | 229 | if (ret && !ip_set_eexist(ret, flags)) |
230 | return ret; | 230 | return ret; |
@@ -342,7 +342,7 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
342 | 342 | ||
343 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); | 343 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); |
344 | 344 | ||
345 | return adtfn(set, &data, h->timeout); | 345 | return adtfn(set, &data, h->timeout, flags); |
346 | } | 346 | } |
347 | 347 | ||
348 | static int | 348 | static int |
@@ -396,7 +396,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
396 | } | 396 | } |
397 | 397 | ||
398 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 398 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
399 | ret = adtfn(set, &data, timeout); | 399 | ret = adtfn(set, &data, timeout, flags); |
400 | return ip_set_eexist(ret, flags) ? 0 : ret; | 400 | return ip_set_eexist(ret, flags) ? 0 : ret; |
401 | } | 401 | } |
402 | 402 | ||
@@ -407,7 +407,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
407 | 407 | ||
408 | for (; port <= port_to; port++) { | 408 | for (; port <= port_to; port++) { |
409 | data.port = htons(port); | 409 | data.port = htons(port); |
410 | ret = adtfn(set, &data, timeout); | 410 | ret = adtfn(set, &data, timeout, flags); |
411 | 411 | ||
412 | if (ret && !ip_set_eexist(ret, flags)) | 412 | if (ret && !ip_set_eexist(ret, flags)) |
413 | return ret; | 413 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 401c8a2531db..670e5e4a1232 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -142,7 +142,7 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
142 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); | 142 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); |
143 | ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); | 143 | ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); |
144 | 144 | ||
145 | return adtfn(set, &data, h->timeout); | 145 | return adtfn(set, &data, h->timeout, flags); |
146 | } | 146 | } |
147 | 147 | ||
148 | static int | 148 | static int |
@@ -200,7 +200,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
200 | if (adt == IPSET_TEST || | 200 | if (adt == IPSET_TEST || |
201 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 201 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
202 | tb[IPSET_ATTR_PORT_TO])) { | 202 | tb[IPSET_ATTR_PORT_TO])) { |
203 | ret = adtfn(set, &data, timeout); | 203 | ret = adtfn(set, &data, timeout, flags); |
204 | return ip_set_eexist(ret, flags) ? 0 : ret; | 204 | return ip_set_eexist(ret, flags) ? 0 : ret; |
205 | } | 205 | } |
206 | 206 | ||
@@ -232,7 +232,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
232 | for (p = port; p <= port_to; p++) { | 232 | for (p = port; p <= port_to; p++) { |
233 | data.ip = htonl(ip); | 233 | data.ip = htonl(ip); |
234 | data.port = htons(p); | 234 | data.port = htons(p); |
235 | ret = adtfn(set, &data, timeout); | 235 | ret = adtfn(set, &data, timeout, flags); |
236 | 236 | ||
237 | if (ret && !ip_set_eexist(ret, flags)) | 237 | if (ret && !ip_set_eexist(ret, flags)) |
238 | return ret; | 238 | return ret; |
@@ -356,7 +356,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
356 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); | 356 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); |
357 | ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); | 357 | ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); |
358 | 358 | ||
359 | return adtfn(set, &data, h->timeout); | 359 | return adtfn(set, &data, h->timeout, flags); |
360 | } | 360 | } |
361 | 361 | ||
362 | static int | 362 | static int |
@@ -414,7 +414,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
414 | } | 414 | } |
415 | 415 | ||
416 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 416 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
417 | ret = adtfn(set, &data, timeout); | 417 | ret = adtfn(set, &data, timeout, flags); |
418 | return ip_set_eexist(ret, flags) ? 0 : ret; | 418 | return ip_set_eexist(ret, flags) ? 0 : ret; |
419 | } | 419 | } |
420 | 420 | ||
@@ -425,7 +425,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
425 | 425 | ||
426 | for (; port <= port_to; port++) { | 426 | for (; port <= port_to; port++) { |
427 | data.port = htons(port); | 427 | data.port = htons(port); |
428 | ret = adtfn(set, &data, timeout); | 428 | ret = adtfn(set, &data, timeout, flags); |
429 | 429 | ||
430 | if (ret && !ip_set_eexist(ret, flags)) | 430 | if (ret && !ip_set_eexist(ret, flags)) |
431 | return ret; | 431 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 4743e5402522..4bb365c9f3db 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -162,7 +162,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
162 | ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); | 162 | ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); |
163 | data.ip2 &= ip_set_netmask(data.cidr); | 163 | data.ip2 &= ip_set_netmask(data.cidr); |
164 | 164 | ||
165 | return adtfn(set, &data, h->timeout); | 165 | return adtfn(set, &data, h->timeout, flags); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int | 168 | static int |
@@ -228,7 +228,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
228 | if (adt == IPSET_TEST || | 228 | if (adt == IPSET_TEST || |
229 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 229 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
230 | tb[IPSET_ATTR_PORT_TO])) { | 230 | tb[IPSET_ATTR_PORT_TO])) { |
231 | ret = adtfn(set, &data, timeout); | 231 | ret = adtfn(set, &data, timeout, flags); |
232 | return ip_set_eexist(ret, flags) ? 0 : ret; | 232 | return ip_set_eexist(ret, flags) ? 0 : ret; |
233 | } | 233 | } |
234 | 234 | ||
@@ -260,7 +260,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
260 | for (p = port; p <= port_to; p++) { | 260 | for (p = port; p <= port_to; p++) { |
261 | data.ip = htonl(ip); | 261 | data.ip = htonl(ip); |
262 | data.port = htons(p); | 262 | data.port = htons(p); |
263 | ret = adtfn(set, &data, timeout); | 263 | ret = adtfn(set, &data, timeout, flags); |
264 | 264 | ||
265 | if (ret && !ip_set_eexist(ret, flags)) | 265 | if (ret && !ip_set_eexist(ret, flags)) |
266 | return ret; | 266 | return ret; |
@@ -410,7 +410,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
410 | ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); | 410 | ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); |
411 | ip6_netmask(&data.ip2, data.cidr); | 411 | ip6_netmask(&data.ip2, data.cidr); |
412 | 412 | ||
413 | return adtfn(set, &data, h->timeout); | 413 | return adtfn(set, &data, h->timeout, flags); |
414 | } | 414 | } |
415 | 415 | ||
416 | static int | 416 | static int |
@@ -476,7 +476,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
476 | } | 476 | } |
477 | 477 | ||
478 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 478 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
479 | ret = adtfn(set, &data, timeout); | 479 | ret = adtfn(set, &data, timeout, flags); |
480 | return ip_set_eexist(ret, flags) ? 0 : ret; | 480 | return ip_set_eexist(ret, flags) ? 0 : ret; |
481 | } | 481 | } |
482 | 482 | ||
@@ -487,7 +487,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
487 | 487 | ||
488 | for (; port <= port_to; port++) { | 488 | for (; port <= port_to; port++) { |
489 | data.port = htons(port); | 489 | data.port = htons(port); |
490 | ret = adtfn(set, &data, timeout); | 490 | ret = adtfn(set, &data, timeout, flags); |
491 | 491 | ||
492 | if (ret && !ip_set_eexist(ret, flags)) | 492 | if (ret && !ip_set_eexist(ret, flags)) |
493 | return ret; | 493 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index c4db202b7da4..440b38f9fe3b 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
@@ -141,7 +141,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
141 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); | 141 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); |
142 | data.ip &= ip_set_netmask(data.cidr); | 142 | data.ip &= ip_set_netmask(data.cidr); |
143 | 143 | ||
144 | return adtfn(set, &data, h->timeout); | 144 | return adtfn(set, &data, h->timeout, flags); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int | 147 | static int |
@@ -179,7 +179,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
179 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 179 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
180 | } | 180 | } |
181 | 181 | ||
182 | ret = adtfn(set, &data, timeout); | 182 | ret = adtfn(set, &data, timeout, flags); |
183 | 183 | ||
184 | return ip_set_eexist(ret, flags) ? 0 : ret; | 184 | return ip_set_eexist(ret, flags) ? 0 : ret; |
185 | } | 185 | } |
@@ -306,7 +306,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
306 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); | 306 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); |
307 | ip6_netmask(&data.ip, data.cidr); | 307 | ip6_netmask(&data.ip, data.cidr); |
308 | 308 | ||
309 | return adtfn(set, &data, h->timeout); | 309 | return adtfn(set, &data, h->timeout, flags); |
310 | } | 310 | } |
311 | 311 | ||
312 | static int | 312 | static int |
@@ -344,7 +344,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
344 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 344 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
345 | } | 345 | } |
346 | 346 | ||
347 | ret = adtfn(set, &data, timeout); | 347 | ret = adtfn(set, &data, timeout, flags); |
348 | 348 | ||
349 | return ip_set_eexist(ret, flags) ? 0 : ret; | 349 | return ip_set_eexist(ret, flags) ? 0 : ret; |
350 | } | 350 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index d2a40362dd3a..2d31291ba83e 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -158,7 +158,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
158 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); | 158 | ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); |
159 | data.ip &= ip_set_netmask(data.cidr); | 159 | data.ip &= ip_set_netmask(data.cidr); |
160 | 160 | ||
161 | return adtfn(set, &data, h->timeout); | 161 | return adtfn(set, &data, h->timeout, flags); |
162 | } | 162 | } |
163 | 163 | ||
164 | static int | 164 | static int |
@@ -216,7 +216,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
216 | } | 216 | } |
217 | 217 | ||
218 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 218 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
219 | ret = adtfn(set, &data, timeout); | 219 | ret = adtfn(set, &data, timeout, flags); |
220 | return ip_set_eexist(ret, flags) ? 0 : ret; | 220 | return ip_set_eexist(ret, flags) ? 0 : ret; |
221 | } | 221 | } |
222 | 222 | ||
@@ -227,7 +227,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
227 | 227 | ||
228 | for (; port <= port_to; port++) { | 228 | for (; port <= port_to; port++) { |
229 | data.port = htons(port); | 229 | data.port = htons(port); |
230 | ret = adtfn(set, &data, timeout); | 230 | ret = adtfn(set, &data, timeout, flags); |
231 | 231 | ||
232 | if (ret && !ip_set_eexist(ret, flags)) | 232 | if (ret && !ip_set_eexist(ret, flags)) |
233 | return ret; | 233 | return ret; |
@@ -371,7 +371,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
371 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); | 371 | ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); |
372 | ip6_netmask(&data.ip, data.cidr); | 372 | ip6_netmask(&data.ip, data.cidr); |
373 | 373 | ||
374 | return adtfn(set, &data, h->timeout); | 374 | return adtfn(set, &data, h->timeout, flags); |
375 | } | 375 | } |
376 | 376 | ||
377 | static int | 377 | static int |
@@ -429,7 +429,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
429 | } | 429 | } |
430 | 430 | ||
431 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 431 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
432 | ret = adtfn(set, &data, timeout); | 432 | ret = adtfn(set, &data, timeout, flags); |
433 | return ip_set_eexist(ret, flags) ? 0 : ret; | 433 | return ip_set_eexist(ret, flags) ? 0 : ret; |
434 | } | 434 | } |
435 | 435 | ||
@@ -440,7 +440,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
440 | 440 | ||
441 | for (; port <= port_to; port++) { | 441 | for (; port <= port_to; port++) { |
442 | data.port = htons(port); | 442 | data.port = htons(port); |
443 | ret = adtfn(set, &data, timeout); | 443 | ret = adtfn(set, &data, timeout, flags); |
444 | 444 | ||
445 | if (ret && !ip_set_eexist(ret, flags)) | 445 | if (ret && !ip_set_eexist(ret, flags)) |
446 | return ret; | 446 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index e9159e99fc4b..a0290ffad355 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -109,15 +109,28 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
109 | } | 109 | } |
110 | 110 | ||
111 | static bool | 111 | static bool |
112 | next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id) | 112 | id_eq(const struct list_set *map, u32 i, ip_set_id_t id) |
113 | { | 113 | { |
114 | const struct set_elem *elem; | 114 | const struct set_elem *elem; |
115 | 115 | ||
116 | if (i + 1 < map->size) { | 116 | if (i < map->size) { |
117 | elem = list_set_elem(map, i + 1); | 117 | elem = list_set_elem(map, i); |
118 | return elem->id == id; | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static bool | ||
125 | id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id) | ||
126 | { | ||
127 | const struct set_elem *elem; | ||
128 | |||
129 | if (i < map->size) { | ||
130 | elem = list_set_elem(map, i); | ||
118 | return !!(elem->id == id && | 131 | return !!(elem->id == id && |
119 | !(with_timeout(map->timeout) && | 132 | !(with_timeout(map->timeout) && |
120 | list_set_expired(map, i + 1))); | 133 | list_set_expired(map, i))); |
121 | } | 134 | } |
122 | 135 | ||
123 | return 0; | 136 | return 0; |
@@ -190,12 +203,26 @@ list_set_del(struct list_set *map, u32 i) | |||
190 | return 0; | 203 | return 0; |
191 | } | 204 | } |
192 | 205 | ||
206 | static void | ||
207 | cleanup_entries(struct list_set *map) | ||
208 | { | ||
209 | struct set_telem *e; | ||
210 | u32 i; | ||
211 | |||
212 | for (i = 0; i < map->size; i++) { | ||
213 | e = list_set_telem(map, i); | ||
214 | if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) | ||
215 | list_set_del(map, i); | ||
216 | } | ||
217 | } | ||
218 | |||
193 | static int | 219 | static int |
194 | list_set_uadt(struct ip_set *set, struct nlattr *tb[], | 220 | list_set_uadt(struct ip_set *set, struct nlattr *tb[], |
195 | enum ipset_adt adt, u32 *lineno, u32 flags) | 221 | enum ipset_adt adt, u32 *lineno, u32 flags) |
196 | { | 222 | { |
197 | struct list_set *map = set->data; | 223 | struct list_set *map = set->data; |
198 | bool with_timeout = with_timeout(map->timeout); | 224 | bool with_timeout = with_timeout(map->timeout); |
225 | bool flag_exist = flags & IPSET_FLAG_EXIST; | ||
199 | int before = 0; | 226 | int before = 0; |
200 | u32 timeout = map->timeout; | 227 | u32 timeout = map->timeout; |
201 | ip_set_id_t id, refid = IPSET_INVALID_ID; | 228 | ip_set_id_t id, refid = IPSET_INVALID_ID; |
@@ -248,6 +275,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
248 | } | 275 | } |
249 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 276 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
250 | } | 277 | } |
278 | if (with_timeout && adt != IPSET_TEST) | ||
279 | cleanup_entries(map); | ||
251 | 280 | ||
252 | switch (adt) { | 281 | switch (adt) { |
253 | case IPSET_TEST: | 282 | case IPSET_TEST: |
@@ -259,22 +288,37 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
259 | else if (with_timeout && list_set_expired(map, i)) | 288 | else if (with_timeout && list_set_expired(map, i)) |
260 | continue; | 289 | continue; |
261 | else if (before > 0 && elem->id == id) | 290 | else if (before > 0 && elem->id == id) |
262 | ret = next_id_eq(map, i, refid); | 291 | ret = id_eq_timeout(map, i + 1, refid); |
263 | else if (before < 0 && elem->id == refid) | 292 | else if (before < 0 && elem->id == refid) |
264 | ret = next_id_eq(map, i, id); | 293 | ret = id_eq_timeout(map, i + 1, id); |
265 | else if (before == 0 && elem->id == id) | 294 | else if (before == 0 && elem->id == id) |
266 | ret = 1; | 295 | ret = 1; |
267 | } | 296 | } |
268 | break; | 297 | break; |
269 | case IPSET_ADD: | 298 | case IPSET_ADD: |
270 | for (i = 0; i < map->size && !ret; i++) { | 299 | for (i = 0; i < map->size; i++) { |
271 | elem = list_set_elem(map, i); | 300 | elem = list_set_elem(map, i); |
272 | if (elem->id == id && | 301 | if (elem->id != id) |
273 | !(with_timeout && list_set_expired(map, i))) | 302 | continue; |
303 | if (!(with_timeout && flag_exist)) { | ||
274 | ret = -IPSET_ERR_EXIST; | 304 | ret = -IPSET_ERR_EXIST; |
305 | goto finish; | ||
306 | } else { | ||
307 | struct set_telem *e = list_set_telem(map, i); | ||
308 | |||
309 | if ((before > 1 && | ||
310 | !id_eq(map, i + 1, refid)) || | ||
311 | (before < 0 && | ||
312 | (i == 0 || !id_eq(map, i - 1, refid)))) { | ||
313 | ret = -IPSET_ERR_EXIST; | ||
314 | goto finish; | ||
315 | } | ||
316 | e->timeout = ip_set_timeout_set(timeout); | ||
317 | ip_set_put_byindex(id); | ||
318 | ret = 0; | ||
319 | goto finish; | ||
320 | } | ||
275 | } | 321 | } |
276 | if (ret == -IPSET_ERR_EXIST) | ||
277 | break; | ||
278 | ret = -IPSET_ERR_LIST_FULL; | 322 | ret = -IPSET_ERR_LIST_FULL; |
279 | for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { | 323 | for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { |
280 | elem = list_set_elem(map, i); | 324 | elem = list_set_elem(map, i); |
@@ -283,9 +327,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
283 | : list_set_add(map, i, id, timeout); | 327 | : list_set_add(map, i, id, timeout); |
284 | else if (elem->id != refid) | 328 | else if (elem->id != refid) |
285 | continue; | 329 | continue; |
286 | else if (with_timeout && list_set_expired(map, i)) | 330 | else if (before > 0) |
287 | ret = -IPSET_ERR_REF_EXIST; | ||
288 | else if (before) | ||
289 | ret = list_set_add(map, i, id, timeout); | 331 | ret = list_set_add(map, i, id, timeout); |
290 | else if (i + 1 < map->size) | 332 | else if (i + 1 < map->size) |
291 | ret = list_set_add(map, i + 1, id, timeout); | 333 | ret = list_set_add(map, i + 1, id, timeout); |
@@ -299,16 +341,12 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
299 | ret = before != 0 ? -IPSET_ERR_REF_EXIST | 341 | ret = before != 0 ? -IPSET_ERR_REF_EXIST |
300 | : -IPSET_ERR_EXIST; | 342 | : -IPSET_ERR_EXIST; |
301 | break; | 343 | break; |
302 | } else if (with_timeout && list_set_expired(map, i)) | 344 | } else if (elem->id == id && |
303 | continue; | 345 | (before == 0 || |
304 | else if (elem->id == id && | 346 | (before > 0 && id_eq(map, i + 1, refid)))) |
305 | (before == 0 || | ||
306 | (before > 0 && | ||
307 | next_id_eq(map, i, refid)))) | ||
308 | ret = list_set_del(map, i); | 347 | ret = list_set_del(map, i); |
309 | else if (before < 0 && | 348 | else if (elem->id == refid && |
310 | elem->id == refid && | 349 | before < 0 && id_eq(map, i + 1, id)) |
311 | next_id_eq(map, i, id)) | ||
312 | ret = list_set_del(map, i + 1); | 350 | ret = list_set_del(map, i + 1); |
313 | } | 351 | } |
314 | break; | 352 | break; |
@@ -454,15 +492,9 @@ list_set_gc(unsigned long ul_set) | |||
454 | { | 492 | { |
455 | struct ip_set *set = (struct ip_set *) ul_set; | 493 | struct ip_set *set = (struct ip_set *) ul_set; |
456 | struct list_set *map = set->data; | 494 | struct list_set *map = set->data; |
457 | struct set_telem *e; | ||
458 | u32 i; | ||
459 | 495 | ||
460 | write_lock_bh(&set->lock); | 496 | write_lock_bh(&set->lock); |
461 | for (i = 0; i < map->size; i++) { | 497 | cleanup_entries(map); |
462 | e = list_set_telem(map, i); | ||
463 | if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) | ||
464 | list_set_del(map, i); | ||
465 | } | ||
466 | write_unlock_bh(&set->lock); | 498 | write_unlock_bh(&set->lock); |
467 | 499 | ||
468 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; | 500 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; |