summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@netfilter.org>2020-03-09 12:01:42 +0100
committerJozsef Kadlecsik <kadlec@netfilter.org>2020-03-09 12:01:42 +0100
commitc2dfb6432aea5bb0a3522901b0c44f42d8adbd49 (patch)
tree4d2d2a370a8ec52871a7b3781ed024ac4dc35d8f
parent73dfa4dfe56f748bd419dd79133d4a61e0917e74 (diff)
downloadipset-c2dfb6432aea5bb0a3522901b0c44f42d8adbd49.tar.gz
Introduce --update-counters-first flag for the set target
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>
-rw-r--r--kernel/include/uapi/linux/netfilter/ipset/ip_set.h3
-rw-r--r--kernel/net/netfilter/ipset/ip_set_core.c13
-rw-r--r--kernel/net/netfilter/xt_set.c21
3 files changed, 33 insertions, 4 deletions
diff --git a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
index 7545af4..6881329 100644
--- a/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
+++ b/kernel/include/uapi/linux/netfilter/ipset/ip_set.h
@@ -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,
};
diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c
index 1df6536..082d89d 100644
--- a/kernel/net/netfilter/ipset/ip_set_core.c
+++ b/kernel/net/netfilter/ipset/ip_set_core.c
@@ -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),
diff --git a/kernel/net/netfilter/xt_set.c b/kernel/net/netfilter/xt_set.c
index 95efb3a..7639522 100644
--- a/kernel/net/netfilter/xt_set.c
+++ b/kernel/net/netfilter/xt_set.c
@@ -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 = {