Blob Blame Raw
From 2e7cb6c2d46d9b8b91ff4b5d6797b7544c23ba44 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 13 Jan 2020 16:58:57 +0100
Subject: [PATCH] monitor: Fix output for ranges in anonymous sets

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1774742
Upstream Status: nftables commit ddbacd70d061e

commit ddbacd70d061eb1b6808f501969809bfb5d03001
Author: Phil Sutter <phil@nwl.cc>
Date:   Mon Jan 13 14:53:24 2020 +0100

    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>
---
 include/rule.h                         | 5 +++++
 src/monitor.c                          | 2 +-
 tests/monitor/testcases/set-interval.t | 5 +++++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/include/rule.h b/include/rule.h
index 0b2eba3..47eb29f 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -363,6 +363,11 @@ static inline bool set_is_meter(uint32_t set_flags)
 	return set_is_anonymous(set_flags) && (set_flags & NFT_SET_EVAL);
 }
 
+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 0da9858..fb803cf 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 59930c5..1fbcfe2 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]}]}}}]}}}
-- 
1.8.3.1