]> granicus.if.org Git - ipset/commitdiff
Timeout can be modified for already added elements
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 27 Mar 2011 19:01:33 +0000 (21:01 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 27 Mar 2011 19:01:33 +0000 (21:01 +0200)
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

21 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_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/bitmap:ip.t
tests/hash:ip.t
tests/macipmap.t
tests/portmap.t
tests/setlist.t
tests/setlist.t.before [new file with mode: 0644]
tests/setlist.t.list1 [new file with mode: 0644]
tests/setlist.t.list2 [new file with mode: 0644]
tests/setlist.t.list3 [new file with mode: 0644]

index 5a262e3ae715999d1082801cfa25cc215b301cf3..277b7fbc7fb24a01707925408c5ead5b537f00ac 100644 (file)
@@ -214,7 +214,8 @@ enum ip_set_feature {
 
 struct ip_set;
 
-typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
+typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
+                          u32 timeout, u32 flags);
 
 /* Set type, variant-specific part */
 struct ip_set_type_variant {
index a0196ac790513b9c8dcbb8f33b04218a7fa67b01..7ea9a605ac034c994d4d34741523734ba4d503f8 100644 (file)
@@ -349,7 +349,7 @@ retry:
 /* Add an element to a hash and update the internal counters when succeeded,
  * otherwise report the proper error code. */
 static int
-type_pf_add(struct ip_set *set, void *value, u32 timeout)
+type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t;
@@ -388,7 +388,7 @@ out:
  * and free up space if possible.
  */
 static int
-type_pf_del(struct ip_set *set, void *value, u32 timeout)
+type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t = h->table;
@@ -463,7 +463,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 
 /* Test whether the element is added to the set */
 static int
-type_pf_test(struct ip_set *set, void *value, u32 timeout)
+type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t = h->table;
@@ -776,7 +776,7 @@ retry:
 }
 
 static int
-type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
+type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t = h->table;
@@ -784,6 +784,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
        struct hbucket *n;
        struct type_pf_elem *data;
        int ret = 0, i, j = AHASH_MAX_SIZE + 1;
+       bool flag_exist = flags & IPSET_FLAG_EXIST;
        u32 key;
 
        if (h->elements >= h->maxelem)
@@ -799,7 +800,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
        for (i = 0; i < n->pos; i++) {
                data = ahash_tdata(n, i);
                if (type_pf_data_equal(data, d)) {
-                       if (type_pf_data_expired(data))
+                       if (type_pf_data_expired(data) || flag_exist)
                                j = i;
                        else {
                                ret = -IPSET_ERR_EXIST;
@@ -833,7 +834,7 @@ out:
 }
 
 static int
-type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t = h->table;
@@ -905,7 +906,7 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 #endif
 
 static int
-type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
+type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct ip_set_hash *h = set->data;
        struct htable *t = h->table;
index a113ff066928445902ce5a4e43f51c115586c894..85b1cdf0a4b80641a1d441798435b7610b183804 100644 (file)
@@ -54,7 +54,7 @@ ip_to_id(const struct bitmap_ip *m, u32 ip)
 }
 
 static int
-bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_ip *map = set->data;
        u16 id = *(u16 *)value;
@@ -63,7 +63,7 @@ bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ip *map = set->data;
        u16 id = *(u16 *)value;
@@ -75,7 +75,7 @@ bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ip *map = set->data;
        u16 id = *(u16 *)value;
@@ -131,7 +131,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_ip *map = set->data;
        const unsigned long *members = map->members;
@@ -141,13 +141,13 @@ bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ip *map = set->data;
        unsigned long *members = map->members;
        u16 id = *(u16 *)value;
 
-       if (ip_set_timeout_test(members[id]))
+       if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
                return -IPSET_ERR_EXIST;
 
        members[id] = ip_set_timeout_set(timeout);
@@ -156,7 +156,7 @@ bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ip *map = set->data;
        unsigned long *members = map->members;
@@ -231,7 +231,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        ip = ip_to_id(map, ip);
 
-       return adtfn(set, &ip, map->timeout);
+       return adtfn(set, &ip, map->timeout, flags);
 }
 
 static int
@@ -266,7 +266,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
        if (adt == IPSET_TEST) {
                id = ip_to_id(map, ip);
-               return adtfn(set, &id, timeout);
+               return adtfn(set, &id, timeout, flags);
        }
 
        if (tb[IPSET_ATTR_IP_TO]) {
@@ -293,7 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; !before(ip_to, ip); ip += map->hosts) {
                id = ip_to_id(map, ip);
-               ret = adtfn(set, &id, timeout);;
+               ret = adtfn(set, &id, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index 00a33242e90c2e89994a0711fcae7a61809225e5..35b487987c4efc4c155098c91001095a08b0186e 100644 (file)
@@ -99,7 +99,7 @@ bitmap_ipmac_exist(const struct ipmac_telem *elem)
 /* Base variant */
 
 static int
-bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
@@ -117,7 +117,7 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
@@ -146,7 +146,7 @@ bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
@@ -212,7 +212,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
@@ -231,15 +231,16 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
        struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+       bool flag_exist = flags & IPSET_FLAG_EXIST;
 
        switch (elem->match) {
        case MAC_UNSET:
-               if (!data->ether)
+               if (!(data->ether || flag_exist))
                        /* Already added without ethernet address */
                        return -IPSET_ERR_EXIST;
                /* Fill the MAC address and activate the timer */
@@ -251,7 +252,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
                elem->timeout = ip_set_timeout_set(timeout);
                break;
        case MAC_FILLED:
-               if (!bitmap_expired(map, data->id))
+               if (!(bitmap_expired(map, data->id) || flag_exist))
                        return -IPSET_ERR_EXIST;
                /* Fall through */
        case MAC_EMPTY:
@@ -273,7 +274,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_ipmac *map = set->data;
        const struct ipmac *data = value;
@@ -355,7 +356,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
        data.id -= map->first_ip;
        data.ether = eth_hdr(skb)->h_source;
 
-       return adtfn(set, &data, map->timeout);
+       return adtfn(set, &data, map->timeout, flags);
 }
 
 static int
@@ -395,7 +396,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
 
        data.id -= map->first_ip;
 
-       ret = adtfn(set, &data, timeout);
+       ret = adtfn(set, &data, timeout, flags);
 
        return ip_set_eexist(ret, flags) ? 0 : ret;
 }
index 6b38eb8f6ed823fc42ca7d0443349b506b8623f3..a3935eef76fcbed10bc9bd2478d86ef8a17ea4e2 100644 (file)
@@ -40,7 +40,7 @@ struct bitmap_port {
 /* Base variant */
 
 static int
-bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_port *map = set->data;
        u16 id = *(u16 *)value;
@@ -49,7 +49,7 @@ bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_port *map = set->data;
        u16 id = *(u16 *)value;
@@ -61,7 +61,7 @@ bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_port *map = set->data;
        u16 id = *(u16 *)value;
@@ -119,7 +119,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        const struct bitmap_port *map = set->data;
        const unsigned long *members = map->members;
@@ -129,13 +129,13 @@ bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_port *map = set->data;
        unsigned long *members = map->members;
        u16 id = *(u16 *)value;
 
-       if (ip_set_timeout_test(members[id]))
+       if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
                return -IPSET_ERR_EXIST;
 
        members[id] = ip_set_timeout_set(timeout);
@@ -144,7 +144,7 @@ bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
        struct bitmap_port *map = set->data;
        unsigned long *members = map->members;
@@ -225,7 +225,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        port -= map->first_port;
 
-       return adtfn(set, &port, map->timeout);
+       return adtfn(set, &port, map->timeout, flags);
 }
 
 static int
@@ -259,7 +259,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 
        if (adt == IPSET_TEST) {
                id = port - map->first_port;
-               return adtfn(set, &id, timeout);
+               return adtfn(set, &id, timeout, flags);
        }
 
        if (tb[IPSET_ATTR_PORT_TO]) {
@@ -277,7 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                id = port - map->first_port;
-               ret = adtfn(set, &id, timeout);
+               ret = adtfn(set, &id, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index 43bcce200129a1f9850cb5ab199102d0f4bb3b2e..36830200112063fea36a32dc8003e77bfef08380 100644 (file)
@@ -121,7 +121,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
        if (ip == 0)
                return -EINVAL;
 
-       return adtfn(set, &ip, h->timeout);
+       return adtfn(set, &ip, h->timeout, flags);
 }
 
 static int
@@ -157,7 +157,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                nip = htonl(ip);
                if (nip == 0)
                        return -IPSET_ERR_HASH_ELEM;
-               return adtfn(set, &nip, timeout);
+               return adtfn(set, &nip, timeout, flags);
        }
 
        if (tb[IPSET_ATTR_IP_TO]) {
@@ -182,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                nip = htonl(ip);
                if (nip == 0)
                        return -IPSET_ERR_HASH_ELEM;
-               ret = adtfn(set, &nip, timeout);
+               ret = adtfn(set, &nip, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
@@ -294,7 +294,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
        if (ipv6_addr_any(&ip.in6))
                return -EINVAL;
 
-       return adtfn(set, &ip, h->timeout);
+       return adtfn(set, &ip, h->timeout, flags);
 }
 
 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[],
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       ret = adtfn(set, &ip, timeout);
+       ret = adtfn(set, &ip, timeout, flags);
 
        return ip_set_eexist(ret, flags) ? 0 : ret;
 }
index 14281b6b8074142aab9e300b408fc7f4b9b86ae9..65c2ff4b27aa30e54dfbf8bf58634c2c50179926 100644 (file)
@@ -138,7 +138,7 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -192,7 +192,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
              tb[IPSET_ATTR_PORT_TO])) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -224,7 +224,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                for (p = port; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
-                       ret = adtfn(set, &data, timeout);
+                       ret = adtfn(set, &data, timeout, flags);
 
                        if (ret && !ip_set_eexist(ret, flags))
                                return ret;
@@ -342,7 +342,7 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -396,7 +396,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
        }
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -407,7 +407,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                data.port = htons(port);
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index 401c8a2531dbf471677ba4cb13923fda61e6d7cd..670e5e4a1232a4d6461fe8309beeaaecf406dd2b 100644 (file)
@@ -142,7 +142,7 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
        ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -200,7 +200,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
              tb[IPSET_ATTR_PORT_TO])) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -232,7 +232,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                for (p = port; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
-                       ret = adtfn(set, &data, timeout);
+                       ret = adtfn(set, &data, timeout, flags);
 
                        if (ret && !ip_set_eexist(ret, flags))
                                return ret;
@@ -356,7 +356,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
        ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -414,7 +414,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
        }
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -425,7 +425,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                data.port = htons(port);
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index 4743e5402522fb6793c2022ade4bed020b240295..4bb365c9f3db03dde2785033c4d9b1f251ab8ea2 100644 (file)
@@ -162,7 +162,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
        data.ip2 &= ip_set_netmask(data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -228,7 +228,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
              tb[IPSET_ATTR_PORT_TO])) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -260,7 +260,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                for (p = port; p <= port_to; p++) {
                        data.ip = htonl(ip);
                        data.port = htons(p);
-                       ret = adtfn(set, &data, timeout);
+                       ret = adtfn(set, &data, timeout, flags);
 
                        if (ret && !ip_set_eexist(ret, flags))
                                return ret;
@@ -410,7 +410,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
        ip6_netmask(&data.ip2, data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -476,7 +476,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
        }
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -487,7 +487,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                data.port = htons(port);
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index c4db202b7da4bcaefc22e9c637e3a242233c5c9e..440b38f9fe3b3e7d0b92a2fef1fb1bef941ee2b8 100644 (file)
@@ -141,7 +141,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
        data.ip &= ip_set_netmask(data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -179,7 +179,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       ret = adtfn(set, &data, timeout);
+       ret = adtfn(set, &data, timeout, flags);
 
        return ip_set_eexist(ret, flags) ? 0 : ret;
 }
@@ -306,7 +306,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
        ip6_netmask(&data.ip, data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -344,7 +344,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       ret = adtfn(set, &data, timeout);
+       ret = adtfn(set, &data, timeout, flags);
 
        return ip_set_eexist(ret, flags) ? 0 : ret;
 }
index d2a40362dd3aadb6510ff1603a42e132eeeb5c7a..2d31291ba83eb68dc3388a59ae24673ad33897de 100644 (file)
@@ -158,7 +158,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
        data.ip &= ip_set_netmask(data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -216,7 +216,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        }
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -227,7 +227,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                data.port = htons(port);
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
@@ -371,7 +371,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
        ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
        ip6_netmask(&data.ip, data.cidr);
 
-       return adtfn(set, &data, h->timeout);
+       return adtfn(set, &data, h->timeout, flags);
 }
 
 static int
@@ -429,7 +429,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
        }
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -440,7 +440,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        for (; port <= port_to; port++) {
                data.port = htons(port);
-               ret = adtfn(set, &data, timeout);
+               ret = adtfn(set, &data, timeout, flags);
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
index e9159e99fc4bd491f2e0d11cecabed5172b1bd27..a0290ffad35549b42e14103b2c91ca7ab048bceb 100644 (file)
@@ -109,15 +109,28 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
 }
 
 static bool
-next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
+id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
 {
        const struct set_elem *elem;
 
-       if (i + 1 < map->size) {
-               elem = list_set_elem(map, i + 1);
+       if (i < map->size) {
+               elem = list_set_elem(map, i);
+               return elem->id == id;
+       }
+
+       return 0;
+}
+
+static bool
+id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id)
+{
+       const struct set_elem *elem;
+
+       if (i < map->size) {
+               elem = list_set_elem(map, i);
                return !!(elem->id == id &&
                          !(with_timeout(map->timeout) &&
-                           list_set_expired(map, i + 1)));
+                           list_set_expired(map, i)));
        }
 
        return 0;
@@ -190,12 +203,26 @@ list_set_del(struct list_set *map, u32 i)
        return 0;
 }
 
+static void
+cleanup_entries(struct list_set *map)
+{
+       struct set_telem *e;
+       u32 i;
+
+       for (i = 0; i < map->size; i++) {
+               e = list_set_telem(map, i);
+               if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
+                       list_set_del(map, i);
+       }
+}
+
 static int
 list_set_uadt(struct ip_set *set, struct nlattr *tb[],
              enum ipset_adt adt, u32 *lineno, u32 flags)
 {
        struct list_set *map = set->data;
        bool with_timeout = with_timeout(map->timeout);
+       bool flag_exist = flags & IPSET_FLAG_EXIST;
        int before = 0;
        u32 timeout = map->timeout;
        ip_set_id_t id, refid = IPSET_INVALID_ID;
@@ -248,6 +275,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                }
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
+       if (with_timeout && adt != IPSET_TEST)
+               cleanup_entries(map);
 
        switch (adt) {
        case IPSET_TEST:
@@ -259,22 +288,37 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                        else if (with_timeout && list_set_expired(map, i))
                                continue;
                        else if (before > 0 && elem->id == id)
-                               ret = next_id_eq(map, i, refid);
+                               ret = id_eq_timeout(map, i + 1, refid);
                        else if (before < 0 && elem->id == refid)
-                               ret = next_id_eq(map, i, id);
+                               ret = id_eq_timeout(map, i + 1, id);
                        else if (before == 0 && elem->id == id)
                                ret = 1;
                }
                break;
        case IPSET_ADD:
-               for (i = 0; i < map->size && !ret; i++) {
+               for (i = 0; i < map->size; i++) {
                        elem = list_set_elem(map, i);
-                       if (elem->id == id &&
-                           !(with_timeout && list_set_expired(map, i)))
+                       if (elem->id != id)
+                               continue;
+                       if (!(with_timeout && flag_exist)) {
                                ret = -IPSET_ERR_EXIST;
+                               goto finish;
+                       } else {
+                               struct set_telem *e = list_set_telem(map, i);
+
+                               if ((before > 1 &&
+                                    !id_eq(map, i + 1, refid)) ||
+                                   (before < 0 &&
+                                    (i == 0 || !id_eq(map, i - 1, refid)))) {
+                                       ret = -IPSET_ERR_EXIST;
+                                       goto finish;
+                               }
+                               e->timeout = ip_set_timeout_set(timeout);
+                               ip_set_put_byindex(id);
+                               ret = 0;
+                               goto finish;
+                       }
                }
-               if (ret == -IPSET_ERR_EXIST)
-                       break;
                ret = -IPSET_ERR_LIST_FULL;
                for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
                        elem = list_set_elem(map, i);
@@ -283,9 +327,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                                        : list_set_add(map, i, id, timeout);
                        else if (elem->id != refid)
                                continue;
-                       else if (with_timeout && list_set_expired(map, i))
-                               ret = -IPSET_ERR_REF_EXIST;
-                       else if (before)
+                       else if (before > 0)
                                ret = list_set_add(map, i, id, timeout);
                        else if (i + 1 < map->size)
                                ret = list_set_add(map, i + 1, id, timeout);
@@ -299,16 +341,12 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                                ret = before != 0 ? -IPSET_ERR_REF_EXIST
                                                  : -IPSET_ERR_EXIST;
                                break;
-                       } else if (with_timeout && list_set_expired(map, i))
-                               continue;
-                       else if (elem->id == id &&
-                                (before == 0 ||
-                                 (before > 0 &&
-                                  next_id_eq(map, i, refid))))
+                       } else if (elem->id == id &&
+                                  (before == 0 ||
+                                   (before > 0 && id_eq(map, i + 1, refid))))
                                ret = list_set_del(map, i);
-                       else if (before < 0 &&
-                                elem->id == refid &&
-                                next_id_eq(map, i, id))
+                       else if (elem->id == refid &&
+                                before < 0 && id_eq(map, i + 1, id))
                                ret = list_set_del(map, i + 1);
                }
                break;
@@ -454,15 +492,9 @@ list_set_gc(unsigned long ul_set)
 {
        struct ip_set *set = (struct ip_set *) ul_set;
        struct list_set *map = set->data;
-       struct set_telem *e;
-       u32 i;
 
        write_lock_bh(&set->lock);
-       for (i = 0; i < map->size; i++) {
-               e = list_set_telem(map, i);
-               if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
-                       list_set_del(map, i);
-       }
+       cleanup_entries(map);
        write_unlock_bh(&set->lock);
 
        map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
index 40c2a98678c58afefca10f50e0b44d638a5c6501..271bf8936bea741d2b2eb52700c7367b9ff9f9dc 100644 (file)
 0 ipset list test > .foo
 # Full: Check listing
 0 diff -I 'Size in memory.*' .foo bitmap:ip.t.list3 && rm .foo
+# Full: flush set
+0 ipset flush test
+# Full: add element with 1s timeout
+0 ipset add test 1.1.1.1 timeout 1
+# Full: readd element with 3s timeout
+0 ipset add test 1.1.1.1 timeout 3 -exist
+# Full: sleep 2s
+0 sleep 2s
+# Full: check readded element
+0 ipset test test 1.1.1.1
 # Full: Delete test set
 0 ipset destroy test
 # eof
index a0547518a10e9b13a3a83ebd3442458b9bc08622..ce8b14b8176fb27e3739ccc8c64ee98013a17f4a 100644 (file)
 0 diff -I 'Size in memory.*' .foo hash:ip.t.list1 && rm .foo
 # Network: Flush test set
 0 ipset -F test
+# Network: add element with 1s timeout
+0 ipset add test 200.100.0.12 timeout 1
+# Network: readd element with 3s timeout
+0 ipset add test 200.100.0.12 timeout 3 -exist
+# Network: sleep 2s
+0 sleep 2s
+# Network: check readded element
+0 ipset test test 200.100.0.12
 # Network: Delete test set
 0 ipset -X test
 # eof
index ddc1393315efc1ce49c57a57a9b16cebb487eb82..7332f75a68fbf8a8b167e9ccb231e9d4f21249de 100644 (file)
 0 diff -I 'Size in memory.*' .foo macipmap.t.list2 && rm .foo
 # Range: Flush test set
 0 ipset -F test
+# Range: add element with 1s timeout
+0 ipset add test 2.0.200.214,00:11:22:33:44:57 timeout 1
+# Range: readd element with 3s timeout
+0 ipset add test 2.0.200.214,00:11:22:33:44:57 timeout 3 -exist
+# Range: sleep 2s
+0 sleep 2s
+# Range: check readded element
+0 ipset test test 2.0.200.214
 # Range: Delete test set
 0 ipset -X test
 # eof
index 989a83b9e89bfee0b921076134f20aceab26a527..084d68ce7293c64ad42d7c50d26ba3aeac09bdc5 100644 (file)
 # 0 diff -I 'Size in memory.*' .foo portmap.t.list2 && rm .foo
 # Full: Flush test set
 0 ipset -F test
+# Full: add element with 1s timeout
+0 ipset add test 567 timeout 1
+# Full: readd element with 3s timeout
+0 ipset add test 567 timeout 3 -exist
+# Full: sleep 2s
+0 sleep 2s
+# Full: check readded element
+0 ipset test test 567
 # Full: Delete test set
 0 ipset -X test
 # eof
index a322cd4682d919e296158fafc7465180654c83ed..8dcf54a22c31557e290d12cdada57c4892a2a6b4 100644 (file)
 0 ipset -F
 # Delete all sets
 0 ipset -X && rm setlist.t.r
+# Create sets a, b, c to check before/after in all combinations
+0 ipset restore < setlist.t.before
+# Add set a to test set
+0 ipset add test b
+# Add set c after b
+0 ipset add test c after b
+# Add set a before b
+0 ipset add test a before b
+# List test set
+0 ipset list test > .foo
+# Check listing
+0 diff -I 'Size in memory.*' .foo setlist.t.list1 && rm .foo
+# Test a set before b
+0 ipset test test a before b
+# Test c set after b
+0 ipset test test c after b
+# Delete b set before c
+0 ipset del test b before c
+# List test set
+0 ipset list test > .foo
+# Check listing
+0 diff -I 'Size in memory.*' .foo setlist.t.list2 && rm .foo
+# Delete c set after a
+0 ipset del test c after a
+# List test set
+0 ipset list test > .foo
+# Check listing
+0 diff -I 'Size in memory.*' .foo setlist.t.list3 && rm .foo
+# Flush sets
+0 ipset flush
+# Destroy sets
+0 ipset destroy
 # Restore list:set with timeout
 0 ipset -R < setlist.t.restore
 # Add set "before" last one
 0 sleep 10
 # Check reference numbers of the sets
 0 ref=`ipset list | grep 'References: 1' | wc -l` && test $ref -eq 0
+# Flush test set
+0 ipset flush test
+# Add element with 1s timeout
+0 ipset add test a timeout 1
+# Readd element with 3s timeout
+0 ipset add test a timeout 3 -exist
+# Sleep 2s
+# Check readded element
+0 ipset test test a
+# Flush all sets
+0 ipset flush
 # Delete all sets
 0 ipset -x
 # eof
diff --git a/tests/setlist.t.before b/tests/setlist.t.before
new file mode 100644 (file)
index 0000000..59ee644
--- /dev/null
@@ -0,0 +1,4 @@
+create a hash:ip
+create b hash:ip
+create c hash:ip
+create test list:set
diff --git a/tests/setlist.t.list1 b/tests/setlist.t.list1
new file mode 100644 (file)
index 0000000..7bba167
--- /dev/null
@@ -0,0 +1,10 @@
+Name: test
+Type: list:set
+Header: size 8 
+Size in memory: 120
+References: 0
+Members:
+a
+b
+c
+
diff --git a/tests/setlist.t.list2 b/tests/setlist.t.list2
new file mode 100644 (file)
index 0000000..2dc752a
--- /dev/null
@@ -0,0 +1,9 @@
+Name: test
+Type: list:set
+Header: size 8 
+Size in memory: 120
+References: 0
+Members:
+a
+c
+
diff --git a/tests/setlist.t.list3 b/tests/setlist.t.list3
new file mode 100644 (file)
index 0000000..5abe9e4
--- /dev/null
@@ -0,0 +1,8 @@
+Name: test
+Type: list:set
+Header: size 8 
+Size in memory: 120
+References: 0
+Members:
+a
+