]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Introduce --update-counters-first flag for the set target
authorJozsef Kadlecsik <kadlec@netfilter.org>
Mon, 9 Mar 2020 11:01:42 +0000 (12:01 +0100)
committerJozsef Kadlecsik <kadlec@netfilter.org>
Mon, 9 Mar 2020 11:01:42 +0000 (12:01 +0100)
Stefano Brivio reported that the patch 'netfilter: ipset:
Fix "don't update counters" mode when counters used at the matching'
changed the semantic of when the counters are updated. Before the patch
the counters were updated regardless of the results of the counter
matches, after the patch the counters were updated only if the counter
match conditions (if specified) matched the packet. In order to handle
both ways, the --update-counters-first flag is introduced: when the flag
is specified, the counters are updated before checking the counter match
conditions. Without the flag the current evaluation path (i.e. update
only if counter conditions match) works.

Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
kernel/include/uapi/linux/netfilter/ipset/ip_set.h
kernel/net/netfilter/ipset/ip_set_core.c
kernel/net/netfilter/xt_set.c

index 7545af48036319758ff5a620358e1103c68280f2..68813290136aa74dbf38646db50905c4b5a76abf 100644 (file)
@@ -186,6 +186,9 @@ enum ipset_cmd_flags {
        IPSET_FLAG_MAP_SKBPRIO = (1 << IPSET_FLAG_BIT_MAP_SKBPRIO),
        IPSET_FLAG_BIT_MAP_SKBQUEUE = 10,
        IPSET_FLAG_MAP_SKBQUEUE = (1 << IPSET_FLAG_BIT_MAP_SKBQUEUE),
+       IPSET_FLAG_BIT_UPDATE_COUNTERS_FIRST = 11,
+       IPSET_FLAG_UPDATE_COUNTERS_FIRST =
+               (1 << IPSET_FLAG_BIT_UPDATE_COUNTERS_FIRST),
        IPSET_FLAG_CMD_MAX = 15,
 };
 
index 1df653620606d56c3f967caa8af5f5ff83c7a742..082d89d704cf9698c986889ae036308b01c1fbad 100644 (file)
@@ -622,10 +622,9 @@ ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
 
 static void
 ip_set_update_counter(struct ip_set_counter *counter,
-                     const struct ip_set_ext *ext, u32 flags)
+                     const struct ip_set_ext *ext)
 {
-       if (ext->packets != ULLONG_MAX &&
-           !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
+       if (ext->packets != ULLONG_MAX) {
                ip_set_add_bytes(ext->bytes, counter);
                ip_set_add_packets(ext->packets, counter);
        }
@@ -649,13 +648,19 @@ ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext,
        if (SET_WITH_COUNTER(set)) {
                struct ip_set_counter *counter = ext_counter(data, set);
 
+               if (flags & IPSET_FLAG_UPDATE_COUNTERS_FIRST)
+                       ip_set_update_counter(counter, ext);
+
                if (flags & IPSET_FLAG_MATCH_COUNTERS &&
                    !(ip_set_match_counter(ip_set_get_packets(counter),
                                mext->packets, mext->packets_op) &&
                      ip_set_match_counter(ip_set_get_bytes(counter),
                                mext->bytes, mext->bytes_op)))
                        return false;
-               ip_set_update_counter(counter, ext, flags);
+
+               if (!(flags & (IPSET_FLAG_UPDATE_COUNTERS_FIRST |
+                              IPSET_FLAG_SKIP_COUNTER_UPDATE)))
+                       ip_set_update_counter(counter, ext);
        }
        if (SET_WITH_SKBINFO(set))
                ip_set_get_skbinfo(ext_skbinfo(data, set),
index 95efb3a25661c388bda40bb946611ced864c1a34..76395225118f6d751f54bf985513c306cca1011b 100644 (file)
@@ -646,6 +646,27 @@ static struct xt_match set_matches[] __read_mostly = {
                .destroy        = set_match_v4_destroy,
                .me             = THIS_MODULE
        },
+       /* --update-counters-first flag support */
+       {
+               .name           = "set",
+               .family         = NFPROTO_IPV4,
+               .revision       = 5,
+               .match          = set_match_v4,
+               .matchsize      = sizeof(struct xt_set_info_match_v4),
+               .checkentry     = set_match_v4_checkentry,
+               .destroy        = set_match_v4_destroy,
+               .me             = THIS_MODULE
+       },
+       {
+               .name           = "set",
+               .family         = NFPROTO_IPV6,
+               .revision       = 5,
+               .match          = set_match_v4,
+               .matchsize      = sizeof(struct xt_set_info_match_v4),
+               .checkentry     = set_match_v4_checkentry,
+               .destroy        = set_match_v4_destroy,
+               .me             = THIS_MODULE
+       },
 };
 
 static struct xt_target set_targets[] __read_mostly = {