aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/ipset/ip_set.h2
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h22
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c2
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c2
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c2
-rw-r--r--net/netfilter/ipset/ip_set_core.c11
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c17
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c31
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c31
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c31
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c22
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c2
13 files changed, 157 insertions, 34 deletions
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index e677c4d8f00e..710ba0070298 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -244,7 +244,7 @@ struct ip_set_type_variant {
244 * zero for no match/success to add/delete 244 * zero for no match/success to add/delete
245 * positive for matching element */ 245 * positive for matching element */
246 int (*uadt)(struct ip_set *set, struct nlattr *tb[], 246 int (*uadt)(struct ip_set *set, struct nlattr *tb[],
247 enum ipset_adt adt, u32 *lineno, u32 flags); 247 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
248 248
249 /* Low level add/del/test functions */ 249 /* Low level add/del/test functions */
250 ipset_adtfn adt[IPSET_ADT_MAX]; 250 ipset_adtfn adt[IPSET_ADT_MAX];
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index 6c0219348b43..8709bd950c8b 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -5,6 +5,11 @@
5#include <linux/jhash.h> 5#include <linux/jhash.h>
6#include <linux/netfilter/ipset/ip_set_timeout.h> 6#include <linux/netfilter/ipset/ip_set_timeout.h>
7 7
8#define CONCAT(a, b, c) a##b##c
9#define TOKEN(a, b, c) CONCAT(a, b, c)
10
11#define type_pf_next TOKEN(TYPE, PF, _elem)
12
8/* Hashing which uses arrays to resolve clashing. The hash table is resized 13/* Hashing which uses arrays to resolve clashing. The hash table is resized
9 * (doubled) when searching becomes too long. 14 * (doubled) when searching becomes too long.
10 * Internally jhash is used with the assumption that the size of the 15 * Internally jhash is used with the assumption that the size of the
@@ -54,6 +59,7 @@ struct ip_set_hash {
54 u32 initval; /* random jhash init value */ 59 u32 initval; /* random jhash init value */
55 u32 timeout; /* timeout value, if enabled */ 60 u32 timeout; /* timeout value, if enabled */
56 struct timer_list gc; /* garbage collection when timeout enabled */ 61 struct timer_list gc; /* garbage collection when timeout enabled */
62 struct type_pf_next next; /* temporary storage for uadd */
57#ifdef IP_SET_HASH_WITH_NETMASK 63#ifdef IP_SET_HASH_WITH_NETMASK
58 u8 netmask; /* netmask value for subnets to store */ 64 u8 netmask; /* netmask value for subnets to store */
59#endif 65#endif
@@ -217,6 +223,7 @@ ip_set_hash_destroy(struct ip_set *set)
217#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask) 223#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask)
218#define type_pf_data_list TOKEN(TYPE, PF, _data_list) 224#define type_pf_data_list TOKEN(TYPE, PF, _data_list)
219#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) 225#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
226#define type_pf_data_next TOKEN(TYPE, PF, _data_next)
220 227
221#define type_pf_elem TOKEN(TYPE, PF, _elem) 228#define type_pf_elem TOKEN(TYPE, PF, _elem)
222#define type_pf_telem TOKEN(TYPE, PF, _telem) 229#define type_pf_telem TOKEN(TYPE, PF, _telem)
@@ -346,6 +353,9 @@ retry:
346 return 0; 353 return 0;
347} 354}
348 355
356static inline void
357type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
358
349/* Add an element to a hash and update the internal counters when succeeded, 359/* Add an element to a hash and update the internal counters when succeeded,
350 * otherwise report the proper error code. */ 360 * otherwise report the proper error code. */
351static int 361static int
@@ -372,8 +382,11 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
372 } 382 }
373 383
374 ret = type_pf_elem_add(n, value); 384 ret = type_pf_elem_add(n, value);
375 if (ret != 0) 385 if (ret != 0) {
386 if (ret == -EAGAIN)
387 type_pf_data_next(h, d);
376 goto out; 388 goto out;
389 }
377 390
378#ifdef IP_SET_HASH_WITH_NETS 391#ifdef IP_SET_HASH_WITH_NETS
379 add_cidr(h, d->cidr, HOST_MASK); 392 add_cidr(h, d->cidr, HOST_MASK);
@@ -589,7 +602,7 @@ type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
589 enum ipset_adt adt, const struct ip_set_adt_opt *opt); 602 enum ipset_adt adt, const struct ip_set_adt_opt *opt);
590static int 603static int
591type_pf_uadt(struct ip_set *set, struct nlattr *tb[], 604type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
592 enum ipset_adt adt, u32 *lineno, u32 flags); 605 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
593 606
594static const struct ip_set_type_variant type_pf_variant = { 607static const struct ip_set_type_variant type_pf_variant = {
595 .kadt = type_pf_kadt, 608 .kadt = type_pf_kadt,
@@ -821,8 +834,11 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
821 goto out; 834 goto out;
822 } 835 }
823 ret = type_pf_elem_tadd(n, d, timeout); 836 ret = type_pf_elem_tadd(n, d, timeout);
824 if (ret != 0) 837 if (ret != 0) {
838 if (ret == -EEXIST)
839 type_pf_data_next(h, d);
825 goto out; 840 goto out;
841 }
826 842
827#ifdef IP_SET_HASH_WITH_NETS 843#ifdef IP_SET_HASH_WITH_NETS
828 add_cidr(h, d->cidr, HOST_MASK); 844 add_cidr(h, d->cidr, HOST_MASK);
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index 75990b37ca37..3a71c8e41557 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -236,7 +236,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
236 236
237static int 237static int
238bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], 238bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
239 enum ipset_adt adt, u32 *lineno, u32 flags) 239 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
240{ 240{
241 struct bitmap_ip *map = set->data; 241 struct bitmap_ip *map = set->data;
242 ipset_adtfn adtfn = set->variant->adt[adt]; 242 ipset_adtfn adtfn = set->variant->adt[adt];
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index cbe77f36650b..fdd5f79d93f3 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -365,7 +365,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
365 365
366static int 366static int
367bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[], 367bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
368 enum ipset_adt adt, u32 *lineno, u32 flags) 368 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
369{ 369{
370 const struct bitmap_ipmac *map = set->data; 370 const struct bitmap_ipmac *map = set->data;
371 ipset_adtfn adtfn = set->variant->adt[adt]; 371 ipset_adtfn adtfn = set->variant->adt[adt];
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index 0b0ae19d0290..a6a5b3558ddc 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -231,7 +231,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
231 231
232static int 232static int
233bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], 233bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
234 enum ipset_adt adt, u32 *lineno, u32 flags) 234 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
235{ 235{
236 struct bitmap_port *map = set->data; 236 struct bitmap_port *map = set->data;
237 ipset_adtfn adtfn = set->variant->adt[adt]; 237 ipset_adtfn adtfn = set->variant->adt[adt];
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 8446c7d81898..528a9b3933ab 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1158,17 +1158,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
1158 struct nlattr *tb[], enum ipset_adt adt, 1158 struct nlattr *tb[], enum ipset_adt adt,
1159 u32 flags, bool use_lineno) 1159 u32 flags, bool use_lineno)
1160{ 1160{
1161 int ret, retried = 0; 1161 int ret;
1162 u32 lineno = 0; 1162 u32 lineno = 0;
1163 bool eexist = flags & IPSET_FLAG_EXIST; 1163 bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
1164 1164
1165 do { 1165 do {
1166 write_lock_bh(&set->lock); 1166 write_lock_bh(&set->lock);
1167 ret = set->variant->uadt(set, tb, adt, &lineno, flags); 1167 ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
1168 write_unlock_bh(&set->lock); 1168 write_unlock_bh(&set->lock);
1169 retried = true;
1169 } while (ret == -EAGAIN && 1170 } while (ret == -EAGAIN &&
1170 set->variant->resize && 1171 set->variant->resize &&
1171 (ret = set->variant->resize(set, retried++)) == 0); 1172 (ret = set->variant->resize(set, retried)) == 0);
1172 1173
1173 if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) 1174 if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
1174 return 0; 1175 return 0;
@@ -1341,7 +1342,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
1341 return -IPSET_ERR_PROTOCOL; 1342 return -IPSET_ERR_PROTOCOL;
1342 1343
1343 read_lock_bh(&set->lock); 1344 read_lock_bh(&set->lock);
1344 ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0); 1345 ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
1345 read_unlock_bh(&set->lock); 1346 read_unlock_bh(&set->lock);
1346 /* Userspace can't trigger element to be re-added */ 1347 /* Userspace can't trigger element to be re-added */
1347 if (ret == -EAGAIN) 1348 if (ret == -EAGAIN)
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index 65a445477f64..c99e861ce031 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -108,6 +108,12 @@ nla_put_failure:
108#define HOST_MASK 32 108#define HOST_MASK 32
109#include <linux/netfilter/ipset/ip_set_ahash.h> 109#include <linux/netfilter/ipset/ip_set_ahash.h>
110 110
111static inline void
112hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
113{
114 h->next.ip = ntohl(d->ip);
115}
116
111static int 117static int
112hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, 118hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
113 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 119 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -126,7 +132,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
126 132
127static int 133static int
128hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], 134hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
129 enum ipset_adt adt, u32 *lineno, u32 flags) 135 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
130{ 136{
131 const struct ip_set_hash *h = set->data; 137 const struct ip_set_hash *h = set->data;
132 ipset_adtfn adtfn = set->variant->adt[adt]; 138 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -178,6 +184,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
178 184
179 hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); 185 hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
180 186
187 if (retried)
188 ip = h->next.ip;
181 for (; !before(ip_to, ip); ip += hosts) { 189 for (; !before(ip_to, ip); ip += hosts) {
182 nip = htonl(ip); 190 nip = htonl(ip);
183 if (nip == 0) 191 if (nip == 0)
@@ -281,6 +289,11 @@ nla_put_failure:
281#define HOST_MASK 128 289#define HOST_MASK 128
282#include <linux/netfilter/ipset/ip_set_ahash.h> 290#include <linux/netfilter/ipset/ip_set_ahash.h>
283 291
292static inline void
293hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
294{
295}
296
284static int 297static int
285hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, 298hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
286 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 299 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -305,7 +318,7 @@ static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
305 318
306static int 319static int
307hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], 320hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
308 enum ipset_adt adt, u32 *lineno, u32 flags) 321 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
309{ 322{
310 const struct ip_set_hash *h = set->data; 323 const struct ip_set_hash *h = set->data;
311 ipset_adtfn adtfn = set->variant->adt[adt]; 324 ipset_adtfn adtfn = set->variant->adt[adt];
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index 9f179bb4f13e..aa91b2c73be3 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -124,6 +124,14 @@ nla_put_failure:
124#define HOST_MASK 32 124#define HOST_MASK 32
125#include <linux/netfilter/ipset/ip_set_ahash.h> 125#include <linux/netfilter/ipset/ip_set_ahash.h>
126 126
127static inline void
128hash_ipport4_data_next(struct ip_set_hash *h,
129 const struct hash_ipport4_elem *d)
130{
131 h->next.ip = ntohl(d->ip);
132 h->next.port = ntohs(d->port);
133}
134
127static int 135static int
128hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, 136hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
129 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 137 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -143,12 +151,12 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
143 151
144static int 152static int
145hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], 153hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
146 enum ipset_adt adt, u32 *lineno, u32 flags) 154 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
147{ 155{
148 const struct ip_set_hash *h = set->data; 156 const struct ip_set_hash *h = set->data;
149 ipset_adtfn adtfn = set->variant->adt[adt]; 157 ipset_adtfn adtfn = set->variant->adt[adt];
150 struct hash_ipport4_elem data = { }; 158 struct hash_ipport4_elem data = { };
151 u32 ip, ip_to, p, port, port_to; 159 u32 ip, ip_to, p = 0, port, port_to;
152 u32 timeout = h->timeout; 160 u32 timeout = h->timeout;
153 bool with_ports = false; 161 bool with_ports = false;
154 int ret; 162 int ret;
@@ -220,8 +228,11 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
220 swap(port, port_to); 228 swap(port, port_to);
221 } 229 }
222 230
223 for (; !before(ip_to, ip); ip++) 231 if (retried)
224 for (p = port; p <= port_to; p++) { 232 ip = h->next.ip;
233 for (; !before(ip_to, ip); ip++) {
234 p = retried && ip == h->next.ip ? h->next.port : port;
235 for (; p <= port_to; p++) {
225 data.ip = htonl(ip); 236 data.ip = htonl(ip);
226 data.port = htons(p); 237 data.port = htons(p);
227 ret = adtfn(set, &data, timeout, flags); 238 ret = adtfn(set, &data, timeout, flags);
@@ -231,6 +242,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
231 else 242 else
232 ret = 0; 243 ret = 0;
233 } 244 }
245 }
234 return ret; 246 return ret;
235} 247}
236 248
@@ -328,6 +340,13 @@ nla_put_failure:
328#define HOST_MASK 128 340#define HOST_MASK 128
329#include <linux/netfilter/ipset/ip_set_ahash.h> 341#include <linux/netfilter/ipset/ip_set_ahash.h>
330 342
343static inline void
344hash_ipport6_data_next(struct ip_set_hash *h,
345 const struct hash_ipport6_elem *d)
346{
347 h->next.port = ntohs(d->port);
348}
349
331static int 350static int
332hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, 351hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
333 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 352 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -347,7 +366,7 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
347 366
348static int 367static int
349hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], 368hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
350 enum ipset_adt adt, u32 *lineno, u32 flags) 369 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
351{ 370{
352 const struct ip_set_hash *h = set->data; 371 const struct ip_set_hash *h = set->data;
353 ipset_adtfn adtfn = set->variant->adt[adt]; 372 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -405,6 +424,8 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
405 if (port > port_to) 424 if (port > port_to)
406 swap(port, port_to); 425 swap(port, port_to);
407 426
427 if (retried)
428 port = h->next.port;
408 for (; port <= port_to; port++) { 429 for (; port <= port_to; port++) {
409 data.port = htons(port); 430 data.port = htons(port);
410 ret = adtfn(set, &data, timeout, flags); 431 ret = adtfn(set, &data, timeout, flags);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 7cfa52b34981..b88e74e0bf06 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -127,6 +127,14 @@ nla_put_failure:
127#define HOST_MASK 32 127#define HOST_MASK 32
128#include <linux/netfilter/ipset/ip_set_ahash.h> 128#include <linux/netfilter/ipset/ip_set_ahash.h>
129 129
130static inline void
131hash_ipportip4_data_next(struct ip_set_hash *h,
132 const struct hash_ipportip4_elem *d)
133{
134 h->next.ip = ntohl(d->ip);
135 h->next.port = ntohs(d->port);
136}
137
130static int 138static int
131hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, 139hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
132 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 140 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -147,12 +155,12 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
147 155
148static int 156static int
149hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], 157hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
150 enum ipset_adt adt, u32 *lineno, u32 flags) 158 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
151{ 159{
152 const struct ip_set_hash *h = set->data; 160 const struct ip_set_hash *h = set->data;
153 ipset_adtfn adtfn = set->variant->adt[adt]; 161 ipset_adtfn adtfn = set->variant->adt[adt];
154 struct hash_ipportip4_elem data = { }; 162 struct hash_ipportip4_elem data = { };
155 u32 ip, ip_to, p, port, port_to; 163 u32 ip, ip_to, p = 0, port, port_to;
156 u32 timeout = h->timeout; 164 u32 timeout = h->timeout;
157 bool with_ports = false; 165 bool with_ports = false;
158 int ret; 166 int ret;
@@ -228,8 +236,11 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
228 swap(port, port_to); 236 swap(port, port_to);
229 } 237 }
230 238
231 for (; !before(ip_to, ip); ip++) 239 if (retried)
232 for (p = port; p <= port_to; p++) { 240 ip = h->next.ip;
241 for (; !before(ip_to, ip); ip++) {
242 p = retried && ip == h->next.ip ? h->next.port : port;
243 for (; p <= port_to; p++) {
233 data.ip = htonl(ip); 244 data.ip = htonl(ip);
234 data.port = htons(p); 245 data.port = htons(p);
235 ret = adtfn(set, &data, timeout, flags); 246 ret = adtfn(set, &data, timeout, flags);
@@ -239,6 +250,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
239 else 250 else
240 ret = 0; 251 ret = 0;
241 } 252 }
253 }
242 return ret; 254 return ret;
243} 255}
244 256
@@ -341,6 +353,13 @@ nla_put_failure:
341#define HOST_MASK 128 353#define HOST_MASK 128
342#include <linux/netfilter/ipset/ip_set_ahash.h> 354#include <linux/netfilter/ipset/ip_set_ahash.h>
343 355
356static inline void
357hash_ipportip6_data_next(struct ip_set_hash *h,
358 const struct hash_ipportip6_elem *d)
359{
360 h->next.port = ntohs(d->port);
361}
362
344static int 363static int
345hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, 364hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
346 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 365 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -361,7 +380,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
361 380
362static int 381static int
363hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], 382hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
364 enum ipset_adt adt, u32 *lineno, u32 flags) 383 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
365{ 384{
366 const struct ip_set_hash *h = set->data; 385 const struct ip_set_hash *h = set->data;
367 ipset_adtfn adtfn = set->variant->adt[adt]; 386 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -423,6 +442,8 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
423 if (port > port_to) 442 if (port > port_to)
424 swap(port, port_to); 443 swap(port, port_to);
425 444
445 if (retried)
446 port = h->next.port;
426 for (; port <= port_to; port++) { 447 for (; port <= port_to; port++) {
427 data.port = htons(port); 448 data.port = htons(port);
428 ret = adtfn(set, &data, timeout, flags); 449 ret = adtfn(set, &data, timeout, flags);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 104042aba92b..605ef3bf94ef 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -140,6 +140,14 @@ nla_put_failure:
140#define HOST_MASK 32 140#define HOST_MASK 32
141#include <linux/netfilter/ipset/ip_set_ahash.h> 141#include <linux/netfilter/ipset/ip_set_ahash.h>
142 142
143static inline void
144hash_ipportnet4_data_next(struct ip_set_hash *h,
145 const struct hash_ipportnet4_elem *d)
146{
147 h->next.ip = ntohl(d->ip);
148 h->next.port = ntohs(d->port);
149}
150
143static int 151static int
144hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 152hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
145 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 153 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -167,12 +175,12 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
167 175
168static int 176static int
169hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], 177hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
170 enum ipset_adt adt, u32 *lineno, u32 flags) 178 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
171{ 179{
172 const struct ip_set_hash *h = set->data; 180 const struct ip_set_hash *h = set->data;
173 ipset_adtfn adtfn = set->variant->adt[adt]; 181 ipset_adtfn adtfn = set->variant->adt[adt];
174 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; 182 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
175 u32 ip, ip_to, p, port, port_to; 183 u32 ip, ip_to, p = 0, port, port_to;
176 u32 timeout = h->timeout; 184 u32 timeout = h->timeout;
177 bool with_ports = false; 185 bool with_ports = false;
178 int ret; 186 int ret;
@@ -256,8 +264,11 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
256 swap(port, port_to); 264 swap(port, port_to);
257 } 265 }
258 266
259 for (; !before(ip_to, ip); ip++) 267 if (retried)
260 for (p = port; p <= port_to; p++) { 268 ip = h->next.ip;
269 for (; !before(ip_to, ip); ip++) {
270 p = retried && ip == h->next.ip ? h->next.port : port;
271 for (; p <= port_to; p++) {
261 data.ip = htonl(ip); 272 data.ip = htonl(ip);
262 data.port = htons(p); 273 data.port = htons(p);
263 ret = adtfn(set, &data, timeout, flags); 274 ret = adtfn(set, &data, timeout, flags);
@@ -267,6 +278,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
267 else 278 else
268 ret = 0; 279 ret = 0;
269 } 280 }
281 }
270 return ret; 282 return ret;
271} 283}
272 284
@@ -388,6 +400,13 @@ nla_put_failure:
388#define HOST_MASK 128 400#define HOST_MASK 128
389#include <linux/netfilter/ipset/ip_set_ahash.h> 401#include <linux/netfilter/ipset/ip_set_ahash.h>
390 402
403static inline void
404hash_ipportnet6_data_next(struct ip_set_hash *h,
405 const struct hash_ipportnet6_elem *d)
406{
407 h->next.port = ntohs(d->port);
408}
409
391static int 410static int
392hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 411hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
393 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 412 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -415,7 +434,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
415 434
416static int 435static int
417hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 436hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
418 enum ipset_adt adt, u32 *lineno, u32 flags) 437 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
419{ 438{
420 const struct ip_set_hash *h = set->data; 439 const struct ip_set_hash *h = set->data;
421 ipset_adtfn adtfn = set->variant->adt[adt]; 440 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -485,6 +504,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
485 if (port > port_to) 504 if (port > port_to)
486 swap(port, port_to); 505 swap(port, port_to);
487 506
507 if (retried)
508 port = h->next.port;
488 for (; port <= port_to; port++) { 509 for (; port <= port_to; port++) {
489 data.port = htons(port); 510 data.port = htons(port);
490 ret = adtfn(set, &data, timeout, flags); 511 ret = adtfn(set, &data, timeout, flags);
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 0024053e409a..e6f8bc5771ca 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -125,6 +125,12 @@ nla_put_failure:
125#define HOST_MASK 32 125#define HOST_MASK 32
126#include <linux/netfilter/ipset/ip_set_ahash.h> 126#include <linux/netfilter/ipset/ip_set_ahash.h>
127 127
128static inline void
129hash_net4_data_next(struct ip_set_hash *h,
130 const struct hash_net4_elem *d)
131{
132}
133
128static int 134static int
129hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, 135hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
130 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 136 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -146,7 +152,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
146 152
147static int 153static int
148hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], 154hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
149 enum ipset_adt adt, u32 *lineno, u32 flags) 155 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
150{ 156{
151 const struct ip_set_hash *h = set->data; 157 const struct ip_set_hash *h = set->data;
152 ipset_adtfn adtfn = set->variant->adt[adt]; 158 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -290,6 +296,12 @@ nla_put_failure:
290#define HOST_MASK 128 296#define HOST_MASK 128
291#include <linux/netfilter/ipset/ip_set_ahash.h> 297#include <linux/netfilter/ipset/ip_set_ahash.h>
292 298
299static inline void
300hash_net6_data_next(struct ip_set_hash *h,
301 const struct hash_net6_elem *d)
302{
303}
304
293static int 305static int
294hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, 306hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
295 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 307 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -311,7 +323,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
311 323
312static int 324static int
313hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], 325hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
314 enum ipset_adt adt, u32 *lineno, u32 flags) 326 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
315{ 327{
316 const struct ip_set_hash *h = set->data; 328 const struct ip_set_hash *h = set->data;
317 ipset_adtfn adtfn = set->variant->adt[adt]; 329 ipset_adtfn adtfn = set->variant->adt[adt];
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index 7a2327b3407d..037b829178dc 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -137,6 +137,13 @@ nla_put_failure:
137#define HOST_MASK 32 137#define HOST_MASK 32
138#include <linux/netfilter/ipset/ip_set_ahash.h> 138#include <linux/netfilter/ipset/ip_set_ahash.h>
139 139
140static inline void
141hash_netport4_data_next(struct ip_set_hash *h,
142 const struct hash_netport4_elem *d)
143{
144 h->next.port = ntohs(d->port);
145}
146
140static int 147static int
141hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, 148hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
142 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 149 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -163,7 +170,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
163 170
164static int 171static int
165hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], 172hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
166 enum ipset_adt adt, u32 *lineno, u32 flags) 173 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
167{ 174{
168 const struct ip_set_hash *h = set->data; 175 const struct ip_set_hash *h = set->data;
169 ipset_adtfn adtfn = set->variant->adt[adt]; 176 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -225,6 +232,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
225 if (port > port_to) 232 if (port > port_to)
226 swap(port, port_to); 233 swap(port, port_to);
227 234
235 if (retried)
236 port = h->next.port;
228 for (; port <= port_to; port++) { 237 for (; port <= port_to; port++) {
229 data.port = htons(port); 238 data.port = htons(port);
230 ret = adtfn(set, &data, timeout, flags); 239 ret = adtfn(set, &data, timeout, flags);
@@ -350,6 +359,13 @@ nla_put_failure:
350#define HOST_MASK 128 359#define HOST_MASK 128
351#include <linux/netfilter/ipset/ip_set_ahash.h> 360#include <linux/netfilter/ipset/ip_set_ahash.h>
352 361
362static inline void
363hash_netport6_data_next(struct ip_set_hash *h,
364 const struct hash_netport6_elem *d)
365{
366 h->next.port = ntohs(d->port);
367}
368
353static int 369static int
354hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, 370hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
355 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 371 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
@@ -376,7 +392,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
376 392
377static int 393static int
378hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], 394hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
379 enum ipset_adt adt, u32 *lineno, u32 flags) 395 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
380{ 396{
381 const struct ip_set_hash *h = set->data; 397 const struct ip_set_hash *h = set->data;
382 ipset_adtfn adtfn = set->variant->adt[adt]; 398 ipset_adtfn adtfn = set->variant->adt[adt];
@@ -438,6 +454,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
438 if (port > port_to) 454 if (port > port_to)
439 swap(port, port_to); 455 swap(port, port_to);
440 456
457 if (retried)
458 port = h->next.port;
441 for (; port <= port_to; port++) { 459 for (; port <= port_to; port++) {
442 data.port = htons(port); 460 data.port = htons(port);
443 ret = adtfn(set, &data, timeout, flags); 461 ret = adtfn(set, &data, timeout, flags);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index f05e9eb863dc..74f0dcc30d98 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -218,7 +218,7 @@ cleanup_entries(struct list_set *map)
218 218
219static int 219static int
220list_set_uadt(struct ip_set *set, struct nlattr *tb[], 220list_set_uadt(struct ip_set *set, struct nlattr *tb[],
221 enum ipset_adt adt, u32 *lineno, u32 flags) 221 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
222{ 222{
223 struct list_set *map = set->data; 223 struct list_set *map = set->data;
224 bool with_timeout = with_timeout(map->timeout); 224 bool with_timeout = with_timeout(map->timeout);