Blob Blame History Raw
From 299aeba9aa84ae0556a0bba18b7adace89069a91 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Mon, 13 Jan 2020 14:53:24 +0100
Subject: [PATCH] monitor: Fix output for ranges in anonymous sets

Previous fix for named interval sets was simply wrong: Instead of
limiting decomposing to anonymous interval sets, it effectively disabled
it entirely.

Since code needs to check for both interval and anonymous bits
separately, introduce set_is_interval() helper to keep the code
readable.

Also extend test case to assert ranges in anonymous sets are correctly
printed by echo or monitor modes. Without this fix, range boundaries are
printed as individual set elements.

Fixes: 5d57fa3e99bb9 ("monitor: Do not decompose non-anonymous sets")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit ddbacd70d061eb1b6808f501969809bfb5d03001)

Conflicts:
	include/rule.h
- Context change due to missing other set_is_*() helpers.
- Manually added set_is_anonymous() helper since code fix uses it.
- Manually added missing include statement to make NFT_SET_* flags
  known.

Signed-off-by: Phil Sutter <psutter@redhat.com>
---
 include/rule.h                         | 11 +++++++++++
 src/monitor.c                          |  2 +-
 tests/monitor/testcases/set-interval.t |  5 +++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/include/rule.h b/include/rule.h
index 12c2984a14362..c2d1d5212649f 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -4,6 +4,7 @@
 #include <stdint.h>
 #include <nftables.h>
 #include <list.h>
+#include <linux/netfilter/nf_tables.h>
 
 /**
  * struct handle_spec - handle ID
@@ -289,6 +290,16 @@ extern const char *set_policy2str(uint32_t policy);
 extern void set_print(const struct set *set, struct output_ctx *octx);
 extern void set_print_plain(const struct set *s, struct output_ctx *octx);
 
+static inline bool set_is_anonymous(uint32_t set_flags)
+{
+       return set_flags & NFT_SET_ANONYMOUS;
+}
+
+static inline bool set_is_interval(uint32_t set_flags)
+{
+	return set_flags & NFT_SET_INTERVAL;
+}
+
 #include <statement.h>
 
 struct counter {
diff --git a/src/monitor.c b/src/monitor.c
index ba8e11888a215..9bb3424d76be2 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -500,7 +500,7 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
 
 static void rule_map_decompose_cb(struct set *s, void *data)
 {
-	if (s->flags & (NFT_SET_INTERVAL & NFT_SET_ANONYMOUS))
+	if (set_is_interval(s->flags) && set_is_anonymous(s->flags))
 		interval_map_decompose(s->init);
 }
 
diff --git a/tests/monitor/testcases/set-interval.t b/tests/monitor/testcases/set-interval.t
index 59930c58243d8..1fbcfe222a2b0 100644
--- a/tests/monitor/testcases/set-interval.t
+++ b/tests/monitor/testcases/set-interval.t
@@ -18,3 +18,8 @@ J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set"
 I add rule ip t c tcp dport @s
 O -
 J {"add": {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"payload": {"protocol": "tcp", "field": "dport"}}, "right": "@s"}}]}}}
+
+# test anonymous interval sets as well
+I add rule ip t c tcp dport { 20, 30-40 }
+O -
+J {"add": {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"payload": {"protocol": "tcp", "field": "dport"}}, "right": {"set": [20, {"range": [30, 40]}]}}}]}}}
-- 
2.24.1