]> granicus.if.org Git - ipset/commitdiff
Fix adding ranges to hash types
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Fri, 6 May 2011 20:08:09 +0000 (22:08 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Fri, 6 May 2011 20:08:09 +0000 (22:08 +0200)
When ranges are added to hash types, the elements may trigger rehashing the set.
However, the last successfully added element was not kept track so the adding
started again with the first element after the rehashing. Bug reported by Mr Dash Four.

22 files changed:
kernel/include/linux/netfilter/ipset/ip_set.h
kernel/include/linux/netfilter/ipset/ip_set_ahash.h
kernel/net/netfilter/ipset/ip_set_bitmap_ip.c
kernel/net/netfilter/ipset/ip_set_bitmap_ipmac.c
kernel/net/netfilter/ipset/ip_set_bitmap_port.c
kernel/net/netfilter/ipset/ip_set_core.c
kernel/net/netfilter/ipset/ip_set_hash_ip.c
kernel/net/netfilter/ipset/ip_set_hash_ipport.c
kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
kernel/net/netfilter/ipset/ip_set_hash_net.c
kernel/net/netfilter/ipset/ip_set_hash_netport.c
kernel/net/netfilter/ipset/ip_set_list_set.c
tests/hash:ip,port,ip.t
tests/hash:ip,port,net.t
tests/hash:ip,port.t
tests/hash:ip.t
tests/hash:ip6,port,ip6.t
tests/hash:ip6,port,net6.t
tests/hash:ip6,port.t
tests/hash:net,port.t
tests/hash:net6,port.t

index e677c4d8f00e8f60fe4fdb18d1ff103d3fe927d1..710ba00702984bae764df396b50454032ae57b69 100644 (file)
@@ -244,7 +244,7 @@ struct ip_set_type_variant {
         *                      zero for no match/success to add/delete
         *                      positive for matching element */
        int (*uadt)(struct ip_set *set, struct nlattr *tb[],
-                   enum ipset_adt adt, u32 *lineno, u32 flags);
+                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
 
        /* Low level add/del/test functions */
        ipset_adtfn adt[IPSET_ADT_MAX];
index 690fa69af12f132eb513ef4d6f9443e625b95273..6a4969dcbeb8b8069c9c75d55968f355bf3323d1 100644 (file)
@@ -5,6 +5,11 @@
 #include <linux/jhash.h>
 #include <linux/netfilter/ipset/ip_set_timeout.h>
 
+#define CONCAT(a, b, c)                a##b##c
+#define TOKEN(a, b, c)         CONCAT(a, b, c)
+
+#define type_pf_next           TOKEN(TYPE, PF, _elem)
+
 /* Hashing which uses arrays to resolve clashing. The hash table is resized
  * (doubled) when searching becomes too long.
  * Internally jhash is used with the assumption that the size of the
@@ -54,6 +59,7 @@ struct ip_set_hash {
        u32 initval;            /* random jhash init value */
        u32 timeout;            /* timeout value, if enabled */
        struct timer_list gc;   /* garbage collection when timeout enabled */
+       struct type_pf_next next; /* temporary storage for uadd */
 #ifdef IP_SET_HASH_WITH_NETMASK
        u8 netmask;             /* netmask value for subnets to store */
 #endif
@@ -217,6 +223,7 @@ ip_set_hash_destroy(struct ip_set *set)
 #define type_pf_data_netmask   TOKEN(TYPE, PF, _data_netmask)
 #define type_pf_data_list      TOKEN(TYPE, PF, _data_list)
 #define type_pf_data_tlist     TOKEN(TYPE, PF, _data_tlist)
+#define type_pf_data_next      TOKEN(TYPE, PF, _data_next)
 
 #define type_pf_elem           TOKEN(TYPE, PF, _elem)
 #define type_pf_telem          TOKEN(TYPE, PF, _telem)
@@ -346,6 +353,9 @@ retry:
        return 0;
 }
 
+static inline void
+type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
+
 /* Add an element to a hash and update the internal counters when succeeded,
  * otherwise report the proper error code. */
 static int
@@ -372,8 +382,11 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
                }
 
        ret = type_pf_elem_add(n, value);
-       if (ret != 0)
+       if (ret != 0) {
+               if (ret == -EAGAIN)
+                       type_pf_data_next(h, d);
                goto out;
+       }
 
 #ifdef IP_SET_HASH_WITH_NETS
        add_cidr(h, d->cidr, HOST_MASK);
@@ -589,7 +602,7 @@ type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
             enum ipset_adt adt, const struct ip_set_adt_opt *opt);
 static int
 type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
-            enum ipset_adt adt, u32 *lineno, u32 flags);
+            enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
 
 static const struct ip_set_type_variant type_pf_variant = {
        .kadt   = type_pf_kadt,
@@ -821,8 +834,11 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
                goto out;
        }
        ret = type_pf_elem_tadd(n, d, timeout);
-       if (ret != 0)
+       if (ret != 0) {
+               if (ret == -EEXIST)
+                       type_pf_data_next(h, d);
                goto out;
+       }
 
 #ifdef IP_SET_HASH_WITH_NETS
        add_cidr(h, d->cidr, HOST_MASK);
index 75990b37ca379bca6bf808a2ecb443b49a92e807..3a71c8e4155703910fd361287fb2601bbe42bef2 100644 (file)
@@ -236,7 +236,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
 
 static int
 bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
-              enum ipset_adt adt, u32 *lineno, u32 flags)
+              enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        struct bitmap_ip *map = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
index cbe77f36650b56479a6fc755be4aaa82215ade08..fdd5f79d93f3184bfd895bbbf541801b94b9ea14 100644 (file)
@@ -365,7 +365,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 
 static int
 bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
-                 enum ipset_adt adt, u32 *lineno, u32 flags)
+                 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct bitmap_ipmac *map = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
index 0b0ae19d0290bc0a7964f58bb177a01e1d01c67b..a6a5b3558ddc4e2f69d49668e15d82dd9d510ca2 100644 (file)
@@ -231,7 +231,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
 
 static int
 bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
-                enum ipset_adt adt, u32 *lineno, u32 flags)
+                enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        struct bitmap_port *map = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
index ea1f56151a96656202a8d3deae6e5d3b1df931dc..d12f136e0686ddb5c781cbd3430538b059d486c3 100644 (file)
@@ -1163,17 +1163,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
        struct nlattr *tb[], enum ipset_adt adt,
        u32 flags, bool use_lineno)
 {
-       int ret, retried = 0;
+       int ret;
        u32 lineno = 0;
-       bool eexist = flags & IPSET_FLAG_EXIST;
+       bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
 
        do {
                write_lock_bh(&set->lock);
-               ret = set->variant->uadt(set, tb, adt, &lineno, flags);
+               ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
                write_unlock_bh(&set->lock);
+               retried = true;
        } while (ret == -EAGAIN &&
                 set->variant->resize &&
-                (ret = set->variant->resize(set, retried++)) == 0);
+                (ret = set->variant->resize(set, retried)) == 0);
 
        if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
                return 0;
@@ -1346,7 +1347,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
                return -IPSET_ERR_PROTOCOL;
 
        read_lock_bh(&set->lock);
-       ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
+       ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
        read_unlock_bh(&set->lock);
        /* Userspace can't trigger element to be re-added */
        if (ret == -EAGAIN)
index 65a445477f6493dba214df27e28b914786cb144a..c99e861ce031cd43aa20f0c58afc6bd1958bbab6 100644 (file)
@@ -108,6 +108,12 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
+{
+       h->next.ip = ntohl(d->ip);
+}
+
 static int
 hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
              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,
 
 static int
 hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
-             enum ipset_adt adt, u32 *lineno, u32 flags)
+             enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -178,6 +184,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
+       if (retried)
+               ip = h->next.ip;
        for (; !before(ip_to, ip); ip += hosts) {
                nip = htonl(ip);
                if (nip == 0)
@@ -281,6 +289,11 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
+{
+}
+
 static int
 hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
              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] = {
 
 static int
 hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
-             enum ipset_adt adt, u32 *lineno, u32 flags)
+             enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
index 9f179bb4f13e6388844991a7444781062e36bddb..aa91b2c73be3eca96662c04b9d6ed967f7c9b025 100644 (file)
@@ -124,6 +124,14 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipport4_data_next(struct ip_set_hash *h,
+                      const struct hash_ipport4_elem *d)
+{
+       h->next.ip = ntohl(d->ip);
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
                  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,
 
 static int
 hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
-                 enum ipset_adt adt, u32 *lineno, u32 flags)
+                 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to, p, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -220,8 +228,11 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
-       for (; !before(ip_to, ip); ip++)
-               for (p = port; p <= port_to; p++) {
+       if (retried)
+               ip = h->next.ip;
+       for (; !before(ip_to, ip); ip++) {
+               p = retried && ip == h->next.ip ? h->next.port : port;
+               for (; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
                        ret = adtfn(set, &data, timeout, flags);
@@ -231,6 +242,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                        else
                                ret = 0;
                }
+       }
        return ret;
 }
 
@@ -328,6 +340,13 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipport6_data_next(struct ip_set_hash *h,
+                      const struct hash_ipport6_elem *d)
+{
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
                  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,
 
 static int
 hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
-                 enum ipset_adt adt, u32 *lineno, u32 flags)
+                 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -405,6 +424,8 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
        if (port > port_to)
                swap(port, port_to);
 
+       if (retried)
+               port = h->next.port;
        for (; port <= port_to; port++) {
                data.port = htons(port);
                ret = adtfn(set, &data, timeout, flags);
index 7cfa52b3498192f8868537f3e19724e1bcd6fe49..b88e74e0bf06d491764fc1efc272c641a4d1fc66 100644 (file)
@@ -127,6 +127,14 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportip4_data_next(struct ip_set_hash *h,
+                        const struct hash_ipportip4_elem *d)
+{
+       h->next.ip = ntohl(d->ip);
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
                    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,
 
 static int
 hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
-                   enum ipset_adt adt, u32 *lineno, u32 flags)
+                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to, p, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -228,8 +236,11 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
-       for (; !before(ip_to, ip); ip++)
-               for (p = port; p <= port_to; p++) {
+       if (retried)
+               ip = h->next.ip;
+       for (; !before(ip_to, ip); ip++) {
+               p = retried && ip == h->next.ip ? h->next.port : port;
+               for (; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
                        ret = adtfn(set, &data, timeout, flags);
@@ -239,6 +250,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                        else
                                ret = 0;
                }
+       }
        return ret;
 }
 
@@ -341,6 +353,13 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportip6_data_next(struct ip_set_hash *h,
+                        const struct hash_ipportip6_elem *d)
+{
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
                    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,
 
 static int
 hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
-                   enum ipset_adt adt, u32 *lineno, u32 flags)
+                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -423,6 +442,8 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
        if (port > port_to)
                swap(port, port_to);
 
+       if (retried)
+               port = h->next.port;
        for (; port <= port_to; port++) {
                data.port = htons(port);
                ret = adtfn(set, &data, timeout, flags);
index 104042aba92bb41a4843443c9540f735d3b42103..605ef3bf94ef1ffffe39abd6dcd59fd5d0c9bd2f 100644 (file)
@@ -140,6 +140,14 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportnet4_data_next(struct ip_set_hash *h,
+                         const struct hash_ipportnet4_elem *d)
+{
+       h->next.ip = ntohl(d->ip);
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
                     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,
 
 static int
 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
-                    enum ipset_adt adt, u32 *lineno, u32 flags)
+                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
-       u32 ip, ip_to, p, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -256,8 +264,11 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
-       for (; !before(ip_to, ip); ip++)
-               for (p = port; p <= port_to; p++) {
+       if (retried)
+               ip = h->next.ip;
+       for (; !before(ip_to, ip); ip++) {
+               p = retried && ip == h->next.ip ? h->next.port : port;
+               for (; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
                        ret = adtfn(set, &data, timeout, flags);
@@ -267,6 +278,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                        else
                                ret = 0;
                }
+       }
        return ret;
 }
 
@@ -388,6 +400,13 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportnet6_data_next(struct ip_set_hash *h,
+                         const struct hash_ipportnet6_elem *d)
+{
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
                     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,
 
 static int
 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
-                    enum ipset_adt adt, u32 *lineno, u32 flags)
+                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -485,6 +504,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
        if (port > port_to)
                swap(port, port_to);
 
+       if (retried)
+               port = h->next.port;
        for (; port <= port_to; port++) {
                data.port = htons(port);
                ret = adtfn(set, &data, timeout, flags);
index 0024053e409ad89cde18d199ef4eddf70456b26f..e6f8bc5771caf036356fef9f0319e7f2029bcd5d 100644 (file)
@@ -125,6 +125,12 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_net4_data_next(struct ip_set_hash *h,
+                   const struct hash_net4_elem *d)
+{
+}
+
 static int
 hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
               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,
 
 static int
 hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
-              enum ipset_adt adt, u32 *lineno, u32 flags)
+              enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -290,6 +296,12 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_net6_data_next(struct ip_set_hash *h,
+                   const struct hash_net6_elem *d)
+{
+}
+
 static int
 hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
               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,
 
 static int
 hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
-              enum ipset_adt adt, u32 *lineno, u32 flags)
+              enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
index 7a2327b3407d9639c279275ea87f9ae238c39e26..037b829178dce0847fa081b421cde6cc7ddc44c2 100644 (file)
@@ -137,6 +137,13 @@ nla_put_failure:
 #define HOST_MASK      32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_netport4_data_next(struct ip_set_hash *h,
+                       const struct hash_netport4_elem *d)
+{
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
                   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,
 
 static int
 hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
-                  enum ipset_adt adt, u32 *lineno, u32 flags)
+                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -225,6 +232,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (port > port_to)
                swap(port, port_to);
 
+       if (retried)
+               port = h->next.port;
        for (; port <= port_to; port++) {
                data.port = htons(port);
                ret = adtfn(set, &data, timeout, flags);
@@ -350,6 +359,13 @@ nla_put_failure:
 #define HOST_MASK      128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_netport6_data_next(struct ip_set_hash *h,
+                       const struct hash_netport6_elem *d)
+{
+       h->next.port = ntohs(d->port);
+}
+
 static int
 hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
                   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,
 
 static int
 hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
-                  enum ipset_adt adt, u32 *lineno, u32 flags)
+                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
@@ -438,6 +454,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
        if (port > port_to)
                swap(port, port_to);
 
+       if (retried)
+               port = h->next.port;
        for (; port <= port_to; port++) {
                data.port = htons(port);
                ret = adtfn(set, &data, timeout, flags);
index f05e9eb863dcf8402941c58770358915a5e1dc2f..74f0dcc30d982508bdf94dd170d4b04cc34e853f 100644 (file)
@@ -218,7 +218,7 @@ cleanup_entries(struct list_set *map)
 
 static int
 list_set_uadt(struct ip_set *set, struct nlattr *tb[],
-             enum ipset_adt adt, u32 *lineno, u32 flags)
+             enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
        struct list_set *map = set->data;
        bool with_timeout = with_timeout(map->timeout);
index 7a6f952b91e8e054537bee9749e5dc2b2f152a81..5b79ab830491b6ec48d3fa638079b120bd913806 100644 (file)
 0 n=`ipset save test|wc -l` && test $n -eq 17
 # Delete test set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:ip,port,ip hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 10.0.0.0-10.0.3.255,tcp:80-82,192.168.0.1
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 10.0|wc -l` && test $n -eq 3072
+# Destroy set
+0 ipset -X test
 # eof
index 34cdc1ac3a2fefbba49fdd4ccc639624b2136f2d..89b046c626902eb82bcf96a5a0ded8843b8a82f4 100644 (file)
 0 ipset flush test
 # Delete set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:ip,port,net hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 10.0.0.0-10.0.3.255,tcp:80-82,192.168.0.1/24
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 10.0|wc -l` && test $n -eq 3072
+# Destroy set
+0 ipset -X test
 # eof
index 9befcb8e6f17c9e47727b0dd8899c87e978d149a..639bfe6adae7479651d18855d1cf6a4a57fdf451 100644 (file)
 0 diff -u -I 'Size in memory.*' .foo hash:ip,port.t.list2
 # Delete set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:ip,port hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 10.0.0.0-10.0.3.255,tcp:80-82
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 10.0|wc -l` && test $n -eq 3072
+# Destroy set
+0 ipset -X test
 # eof
index e21ab6e2403ff86041b6cf1e125c9d8964d32709..10a180933fd2fd2a53291b690c3517a2cb51512d 100644 (file)
 0 n=`ipset -S test | wc -l` && test $n -eq 8161
 # IP: Destroy sets
 0 ipset -X
+# IP: Create set to add a range
+0 ipset new test hash:ip hashsize 64
+# IP: Add a range which forces a resizing
+0 ipset add test 10.0.0.0-10.0.3.255
+# IP: Check that correct number of elements are added
+0 n=`ipset list test|grep 10.0|wc -l` && test $n -eq 1024
+# IP: Destroy sets
+0 ipset -X
 # Network: Create a set with timeout
 0 ipset -N test iphash --hashsize 128 --netmask 24 timeout 5
 # Network: Add zero valued element
index 485a8e9a503f3fa2defd206b21cfc7efeba1236b..078ab6c3d44529f209cb50842332ed646e270b47 100644 (file)
 0 ipset test test 1::1,udp:80,2::2
 # Delete test set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:ip,port,ip -6 hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 1::1,tcp:80-1105,2::2
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 1::1|wc -l` && test $n -eq 1026
+# Destroy set
+0 ipset -X test
 # eof
index 91dc60fcd5b17721ee0db08806749d956e415d81..71814cf720d01b070e0ffd51bbed9ed006bb028b 100644 (file)
 0 ipset -F test
 # Range: Delete test set
 0 ipset -X test
+# Create set to add a range
+0 ipset new test hash:ip,port,net -6 hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 1::1,tcp:80-1105,2::2/12
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 1::1|wc -l` && test $n -eq 1026
+# Destroy set
+0 ipset -X test
 # eof
index 684074cb7d9713d98ac7f6f202ae57b9b87ba6a8..884933c29076fd2ac7d1ed171b8ec30546700a39 100644 (file)
 0 ipset test test 1::1,udp:80
 # Delete test set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:ip,port -6 hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 1::1,tcp:80-1105
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 1::1|wc -l` && test $n -eq 1026
+# Destroy set
+0 ipset -X test
 # eof
index ed8209a7d26e7cf4d02a6c7363dda64f446b4619..d5f420ca364f8b3ee9aafabbdce7bd630e4085dd 100644 (file)
 0 n=`ipset save test|wc -l` && test $n -eq 4
 # Delete test set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:net,port hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 10.0.0.0/24,tcp:80-1105
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 10.0|wc -l` && test $n -eq 1026
+# Destroy set
+0 ipset -X test
 # eof
index ac23288cd07d190824c6182ce7e36c640126327b..1638157251366280004d72fa3cab1c88c4c3d644 100644 (file)
 0 n=`ipset save test|wc -l` && test $n -eq 4
 # Delete test set
 0 ipset destroy test
+# Create set to add a range
+0 ipset new test hash:net,port -6 hashsize 64
+# Add a range which forces a resizing
+0 ipset add test 1::1/64,tcp:80-1105
+# Check that correct number of elements are added
+0 n=`ipset list test|grep 1::|wc -l` && test $n -eq 1026
+# Destroy set
+0 ipset -X test
 # eof