diff --git a/SOURCES/0001-main-enforce-options-before-commands.patch b/SOURCES/0001-main-enforce-options-before-commands.patch new file mode 100644 index 0000000..45b750c --- /dev/null +++ b/SOURCES/0001-main-enforce-options-before-commands.patch @@ -0,0 +1,244 @@ +From 5fac849eac7ecfde4ca6f9c9c406ace030f358f2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 10 Jan 2020 19:54:16 +0100 +Subject: [PATCH] main: enforce options before commands + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1778883 +Upstream Status: nftables commit fb9cea50e8b37 + +commit fb9cea50e8b370b6931e7b53b1a881d3b95b1c91 +Author: Pablo Neira Ayuso +Date: Fri Dec 13 11:32:46 2019 +0100 + + main: enforce options before commands + + This patch turns on POSIXLY_CORRECT on the getopt parser to enforce + options before commands. Users get a hint in such a case: + + # nft list ruleset -a + Error: syntax error, options must be specified before commands + nft list ruleset -a + ^ ~~ + + This patch recovers 9fc71bc6b602 ("main: Fix for misleading error with + negative chain priority"). + + Tests have been updated. + + Signed-off-by: Pablo Neira Ayuso +--- + src/main.c | 46 +++++++++++++++++++++- + tests/shell/testcases/cache/0001_cache_handling_0 | 2 +- + tests/shell/testcases/chains/0016delete_handle_0 | 4 +- + .../shell/testcases/chains/0039negative_priority_0 | 8 ++++ + .../shell/testcases/flowtable/0010delete_handle_0 | 2 +- + .../shell/testcases/maps/0008interval_map_delete_0 | 2 +- + tests/shell/testcases/optionals/comments_0 | 2 +- + tests/shell/testcases/optionals/comments_handles_0 | 2 +- + .../testcases/optionals/delete_object_handles_0 | 4 +- + tests/shell/testcases/optionals/handles_0 | 2 +- + tests/shell/testcases/sets/0028delete_handle_0 | 2 +- + 11 files changed, 64 insertions(+), 12 deletions(-) + create mode 100755 tests/shell/testcases/chains/0039negative_priority_0 + +diff --git a/src/main.c b/src/main.c +index fde8b15..74199f9 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -46,7 +46,7 @@ enum opt_vals { + OPT_TERSE = 't', + OPT_INVALID = '?', + }; +-#define OPTSTRING "hvcf:iI:jvnsNaeSupypTt" ++#define OPTSTRING "+hvcf:iI:jvnsNaeSupypTt" + + static const struct option options[] = { + { +@@ -202,6 +202,47 @@ static const struct { + }, + }; + ++static void nft_options_error(int argc, char * const argv[], int pos) ++{ ++ int i; ++ ++ fprintf(stderr, "Error: syntax error, options must be specified before commands\n"); ++ for (i = 0; i < argc; i++) ++ fprintf(stderr, "%s ", argv[i]); ++ printf("\n%4c%*s\n", '^', pos - 2, "~~"); ++} ++ ++static bool nft_options_check(int argc, char * const argv[]) ++{ ++ bool skip = false, nonoption = false; ++ int pos = 0, i; ++ ++ for (i = 1; i < argc; i++) { ++ pos += strlen(argv[i - 1]) + 1; ++ if (argv[i][0] == '{') { ++ break; ++ } else if (skip) { ++ skip = false; ++ continue; ++ } else if (argv[i][0] == '-') { ++ if (nonoption) { ++ nft_options_error(argc, argv, pos); ++ return false; ++ } else if (argv[i][1] == 'I' || ++ argv[i][1] == 'f' || ++ !strcmp(argv[i], "--includepath") || ++ !strcmp(argv[i], "--file")) { ++ skip = true; ++ continue; ++ } ++ } else if (argv[i][0] != '-') { ++ nonoption = true; ++ } ++ } ++ ++ return true; ++} ++ + int main(int argc, char * const *argv) + { + char *buf = NULL, *filename = NULL; +@@ -211,6 +252,9 @@ int main(int argc, char * const *argv) + unsigned int len; + int i, val, rc; + ++ if (!nft_options_check(argc, argv)) ++ exit(EXIT_FAILURE); ++ + nft = nft_ctx_new(NFT_CTX_DEFAULT); + + while (1) { +diff --git a/tests/shell/testcases/cache/0001_cache_handling_0 b/tests/shell/testcases/cache/0001_cache_handling_0 +index 431aada..0a68440 100755 +--- a/tests/shell/testcases/cache/0001_cache_handling_0 ++++ b/tests/shell/testcases/cache/0001_cache_handling_0 +@@ -20,7 +20,7 @@ TMP=$(mktemp) + echo "$RULESET" >> "$TMP" + $NFT "flush ruleset;include \"$TMP\"" + rm -f "$TMP" +-rule_handle=$($NFT list ruleset -a | awk '/saddr/{print $NF}') ++rule_handle=$($NFT -a list ruleset | awk '/saddr/{print $NF}') + $NFT delete rule inet test test handle $rule_handle + $NFT delete set inet test test + $NFT -f - <<< "$RULESET" +diff --git a/tests/shell/testcases/chains/0016delete_handle_0 b/tests/shell/testcases/chains/0016delete_handle_0 +index 4633d77..8fd1ad8 100755 +--- a/tests/shell/testcases/chains/0016delete_handle_0 ++++ b/tests/shell/testcases/chains/0016delete_handle_0 +@@ -10,8 +10,8 @@ $NFT add chain ip6 test-ip6 x + $NFT add chain ip6 test-ip6 y + $NFT add chain ip6 test-ip6 z + +-chain_y_handle=$($NFT list ruleset -a | awk -v n=1 '/chain y/ && !--n {print $NF; exit}'); +-chain_z_handle=$($NFT list ruleset -a | awk -v n=2 '/chain z/ && !--n {print $NF; exit}'); ++chain_y_handle=$($NFT -a list ruleset | awk -v n=1 '/chain y/ && !--n {print $NF; exit}'); ++chain_z_handle=$($NFT -a list ruleset | awk -v n=2 '/chain z/ && !--n {print $NF; exit}'); + + $NFT delete chain test-ip handle $chain_y_handle + $NFT delete chain ip6 test-ip6 handle $chain_z_handle +diff --git a/tests/shell/testcases/chains/0039negative_priority_0 b/tests/shell/testcases/chains/0039negative_priority_0 +new file mode 100755 +index 0000000..ba17b8c +--- /dev/null ++++ b/tests/shell/testcases/chains/0039negative_priority_0 +@@ -0,0 +1,8 @@ ++#!/bin/bash ++ ++# Test parsing of negative priority values ++ ++set -e ++ ++$NFT add table t ++$NFT add chain t c { type filter hook input priority -30\; } +diff --git a/tests/shell/testcases/flowtable/0010delete_handle_0 b/tests/shell/testcases/flowtable/0010delete_handle_0 +index 303967d..985d4a3 100755 +--- a/tests/shell/testcases/flowtable/0010delete_handle_0 ++++ b/tests/shell/testcases/flowtable/0010delete_handle_0 +@@ -7,7 +7,7 @@ set -e + $NFT add table inet t + $NFT add flowtable inet t f { hook ingress priority filter\; devices = { lo }\; } + +-FH=$($NFT list ruleset -a | awk '/flowtable f/ { print $NF }') ++FH=$($NFT -a list ruleset | awk '/flowtable f/ { print $NF }') + + $NFT delete flowtable inet t handle $FH + +diff --git a/tests/shell/testcases/maps/0008interval_map_delete_0 b/tests/shell/testcases/maps/0008interval_map_delete_0 +index a43fd28..7da6eb3 100755 +--- a/tests/shell/testcases/maps/0008interval_map_delete_0 ++++ b/tests/shell/testcases/maps/0008interval_map_delete_0 +@@ -24,7 +24,7 @@ $NFT delete element filter m { 127.0.0.3 } + $NFT add element filter m { 127.0.0.3 : 0x3 } + $NFT add element filter m { 127.0.0.2 : 0x2 } + +-GET=$($NFT list ruleset -s) ++GET=$($NFT -s list ruleset) + if [ "$EXPECTED" != "$GET" ] ; then + DIFF="$(which diff)" + [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") +diff --git a/tests/shell/testcases/optionals/comments_0 b/tests/shell/testcases/optionals/comments_0 +index 29b8506..ab85936 100755 +--- a/tests/shell/testcases/optionals/comments_0 ++++ b/tests/shell/testcases/optionals/comments_0 +@@ -5,4 +5,4 @@ + $NFT add table test + $NFT add chain test test + $NFT add rule test test tcp dport 22 counter accept comment test_comment +-$NFT list table test -a | grep 'accept comment \"test_comment\"' >/dev/null ++$NFT -a list table test | grep 'accept comment \"test_comment\"' >/dev/null +diff --git a/tests/shell/testcases/optionals/comments_handles_0 b/tests/shell/testcases/optionals/comments_handles_0 +index 30539bf..a01df1d 100755 +--- a/tests/shell/testcases/optionals/comments_handles_0 ++++ b/tests/shell/testcases/optionals/comments_handles_0 +@@ -6,5 +6,5 @@ $NFT add table test + $NFT add chain test test + $NFT add rule test test tcp dport 22 counter accept comment test_comment + set -e +-$NFT list table test -a | grep 'accept comment \"test_comment\" # handle '[[:digit:]]$ >/dev/null ++$NFT -a list table test | grep 'accept comment \"test_comment\" # handle '[[:digit:]]$ >/dev/null + $NFT list table test | grep 'accept comment \"test_comment\"' | grep -v '# handle '[[:digit:]]$ >/dev/null +diff --git a/tests/shell/testcases/optionals/delete_object_handles_0 b/tests/shell/testcases/optionals/delete_object_handles_0 +index d5d9654..a2ae422 100755 +--- a/tests/shell/testcases/optionals/delete_object_handles_0 ++++ b/tests/shell/testcases/optionals/delete_object_handles_0 +@@ -10,8 +10,8 @@ $NFT add quota ip6 test-ip6 http-quota over 25 mbytes + $NFT add counter ip6 test-ip6 http-traffic + $NFT add quota ip6 test-ip6 ssh-quota 10 mbytes + +-counter_handle=$($NFT list ruleset -a | awk '/https-traffic/{print $NF}') +-quota_handle=$($NFT list ruleset -a | awk '/ssh-quota/{print $NF}') ++counter_handle=$($NFT -a list ruleset | awk '/https-traffic/{print $NF}') ++quota_handle=$($NFT -a list ruleset | awk '/ssh-quota/{print $NF}') + $NFT delete counter test-ip handle $counter_handle + $NFT delete quota ip6 test-ip6 handle $quota_handle + +diff --git a/tests/shell/testcases/optionals/handles_0 b/tests/shell/testcases/optionals/handles_0 +index 7c6a437..80f3c5b 100755 +--- a/tests/shell/testcases/optionals/handles_0 ++++ b/tests/shell/testcases/optionals/handles_0 +@@ -5,4 +5,4 @@ + $NFT add table test + $NFT add chain test test + $NFT add rule test test tcp dport 22 counter accept +-$NFT list table test -a | grep 'accept # handle '[[:digit:]]$ >/dev/null ++$NFT -a list table test | grep 'accept # handle '[[:digit:]]$ >/dev/null +diff --git a/tests/shell/testcases/sets/0028delete_handle_0 b/tests/shell/testcases/sets/0028delete_handle_0 +index 4e8b322..5ad17c2 100755 +--- a/tests/shell/testcases/sets/0028delete_handle_0 ++++ b/tests/shell/testcases/sets/0028delete_handle_0 +@@ -7,7 +7,7 @@ $NFT add set test-ip y { type inet_service \; timeout 3h45s \;} + $NFT add set test-ip z { type ipv4_addr\; flags constant , interval\;} + $NFT add set test-ip c {type ipv4_addr \; flags timeout \; elements={192.168.1.1 timeout 10s, 192.168.1.2 timeout 30s} \;} + +-set_handle=$($NFT list ruleset -a | awk '/set c/{print $NF}') ++set_handle=$($NFT -a list ruleset | awk '/set c/{print $NF}') + $NFT delete set test-ip handle $set_handle + + EXPECTED="table ip test-ip { +-- +1.8.3.1 + diff --git a/SOURCES/0002-main-restore-debug.patch b/SOURCES/0002-main-restore-debug.patch new file mode 100644 index 0000000..442f24b --- /dev/null +++ b/SOURCES/0002-main-restore-debug.patch @@ -0,0 +1,50 @@ +From 0c808b1ee29d4a0974f4cc5c0586138730361a41 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 10 Jan 2020 19:54:16 +0100 +Subject: [PATCH] main: restore --debug + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1778883 +Upstream Status: nftables commit ea5af85371bd1 + +commit ea5af85371bd18658ea2ffa0a6c9c48e2c64684b +Author: Pablo Neira Ayuso +Date: Thu Jan 9 18:16:18 2020 +0100 + + main: restore --debug + + Broken since options are mandatory before commands. + + Fixes: fb9cea50e8b3 ("main: enforce options before commands") + Signed-off-by: Pablo Neira Ayuso +--- + src/main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/main.c b/src/main.c +index 74199f9..6ab1b89 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -46,7 +46,7 @@ enum opt_vals { + OPT_TERSE = 't', + OPT_INVALID = '?', + }; +-#define OPTSTRING "+hvcf:iI:jvnsNaeSupypTt" ++#define OPTSTRING "+hvd:cf:iI:jvnsNaeSupypTt" + + static const struct option options[] = { + { +@@ -228,8 +228,10 @@ static bool nft_options_check(int argc, char * const argv[]) + if (nonoption) { + nft_options_error(argc, argv, pos); + return false; +- } else if (argv[i][1] == 'I' || ++ } else if (argv[i][1] == 'd' || ++ argv[i][1] == 'I' || + argv[i][1] == 'f' || ++ !strcmp(argv[i], "--debug") || + !strcmp(argv[i], "--includepath") || + !strcmp(argv[i], "--file")) { + skip = true; +-- +1.8.3.1 + diff --git a/SOURCES/0003-monitor-Do-not-decompose-non-anonymous-sets.patch b/SOURCES/0003-monitor-Do-not-decompose-non-anonymous-sets.patch new file mode 100644 index 0000000..5f1d629 --- /dev/null +++ b/SOURCES/0003-monitor-Do-not-decompose-non-anonymous-sets.patch @@ -0,0 +1,68 @@ +From 13bd961c3ba83e4189dcffdcf570c5a4391fd5f9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 10 Jan 2020 19:58:29 +0100 +Subject: [PATCH] monitor: Do not decompose non-anonymous sets + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1774742 +Upstream Status: nftables commit 5d57fa3e99bb9 + +commit 5d57fa3e99bb9f2044e236d4ddb7d874cfefe1dd +Author: Phil Sutter +Date: Thu Jan 9 13:34:20 2020 +0100 + + monitor: Do not decompose non-anonymous sets + + They have been decomposed already, trying to do that again causes a + segfault. This is a similar fix as in commit 8ecb885589591 ("src: + restore --echo with anonymous sets"). + + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + src/monitor.c | 2 +- + tests/monitor/testcases/set-interval.t | 20 ++++++++++++++++++++ + 2 files changed, 21 insertions(+), 1 deletion(-) + create mode 100644 tests/monitor/testcases/set-interval.t + +diff --git a/src/monitor.c b/src/monitor.c +index ea0393c..0da9858 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) ++ if (s->flags & (NFT_SET_INTERVAL & NFT_SET_ANONYMOUS)) + interval_map_decompose(s->init); + } + +diff --git a/tests/monitor/testcases/set-interval.t b/tests/monitor/testcases/set-interval.t +new file mode 100644 +index 0000000..59930c5 +--- /dev/null ++++ b/tests/monitor/testcases/set-interval.t +@@ -0,0 +1,20 @@ ++# setup first ++I add table ip t ++I add chain ip t c ++O - ++J {"add": {"table": {"family": "ip", "name": "t", "handle": 0}}} ++J {"add": {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}} ++ ++# add set with elements, monitor output expectedly differs ++I add set ip t s { type inet_service; flags interval; elements = { 20, 30-40 }; } ++O add set ip t s { type inet_service; flags interval; } ++O add element ip t s { 20 } ++O add element ip t s { 30-40 } ++J {"add": {"set": {"family": "ip", "name": "s", "table": "t", "type": "inet_service", "handle": 0, "flags": ["interval"]}}} ++J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set": [20]}}}} ++J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set": [{"range": [30, 40]}]}}}} ++ ++# this would crash nft ++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"}}]}}} +-- +1.8.3.1 + diff --git a/SOURCES/0004-monitor-Fix-output-for-ranges-in-anonymous-sets.patch b/SOURCES/0004-monitor-Fix-output-for-ranges-in-anonymous-sets.patch new file mode 100644 index 0000000..42209e3 --- /dev/null +++ b/SOURCES/0004-monitor-Fix-output-for-ranges-in-anonymous-sets.patch @@ -0,0 +1,80 @@ +From 2e7cb6c2d46d9b8b91ff4b5d6797b7544c23ba44 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +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 +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 + Reviewed-by: Pablo Neira Ayuso +--- + 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 + + 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 + diff --git a/SOURCES/0005-xfrm-spi-is-big-endian.patch b/SOURCES/0005-xfrm-spi-is-big-endian.patch new file mode 100644 index 0000000..8dd30e8 --- /dev/null +++ b/SOURCES/0005-xfrm-spi-is-big-endian.patch @@ -0,0 +1,51 @@ +From ca4d1604b18abf7189ecfd5e06cb74abc3694076 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 16 Jan 2020 18:40:52 +0100 +Subject: [PATCH] xfrm: spi is big-endian + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1790963 +Upstream Status: nftables commit 488356b895024 + +commit 488356b895024d0944b20feb1f930558726e0877 +Author: Florian Westphal +Date: Tue Jan 14 13:37:28 2020 +0100 + + xfrm: spi is big-endian + + the kernel stores spi in a __be32, so fix up the byteorder annotation. + + Signed-off-by: Florian Westphal + Acked-by: Pablo Neira Ayuso +--- + src/xfrm.c | 2 +- + tests/py/inet/ipsec.t.payload | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/xfrm.c b/src/xfrm.c +index 4dd53c3..336e8c9 100644 +--- a/src/xfrm.c ++++ b/src/xfrm.c +@@ -39,7 +39,7 @@ const struct xfrm_template xfrm_templates[] = { + [NFT_XFRM_KEY_DADDR_IP6] = XFRM_TEMPLATE_BE("daddr", &ip6addr_type, 16 * BITS_PER_BYTE), + [NFT_XFRM_KEY_SADDR_IP6] = XFRM_TEMPLATE_BE("saddr", &ip6addr_type, 16 * BITS_PER_BYTE), + [NFT_XFRM_KEY_REQID] = XFRM_TEMPLATE_HE("reqid", &integer_type, 4 * BITS_PER_BYTE), +- [NFT_XFRM_KEY_SPI] = XFRM_TEMPLATE_HE("spi", &integer_type, 4 * BITS_PER_BYTE), ++ [NFT_XFRM_KEY_SPI] = XFRM_TEMPLATE_BE("spi", &integer_type, 4 * BITS_PER_BYTE), + }; + + static void xfrm_expr_print(const struct expr *expr, struct output_ctx *octx) +diff --git a/tests/py/inet/ipsec.t.payload b/tests/py/inet/ipsec.t.payload +index 6049c66..c46a226 100644 +--- a/tests/py/inet/ipsec.t.payload ++++ b/tests/py/inet/ipsec.t.payload +@@ -16,7 +16,6 @@ ip ipsec-ip4 ipsec-input + # ipsec out spi 1-561 + inet ipsec-inet ipsec-post + [ xfrm load out 0 spi => reg 1 ] +- [ byteorder reg 1 = hton(reg 1, 4, 4) ] + [ cmp gte reg 1 0x01000000 ] + [ cmp lte reg 1 0x31020000 ] + +-- +1.8.3.1 + diff --git a/SOURCES/0006-tests-shell-Search-diff-tool-once-and-for-all.patch b/SOURCES/0006-tests-shell-Search-diff-tool-once-and-for-all.patch new file mode 100644 index 0000000..e6adbfc --- /dev/null +++ b/SOURCES/0006-tests-shell-Search-diff-tool-once-and-for-all.patch @@ -0,0 +1,573 @@ +From 8537751e48dfacee11d48ad3f050bdacc930284c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 17 Jan 2020 12:50:23 +0100 +Subject: [PATCH] tests: shell: Search diff tool once and for all + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1790793 +Upstream Status: nftables commit 68310ba0f9c20 + +commit 68310ba0f9c2066f7463d66a1a1938b66fb8a4c4 +Author: Phil Sutter +Date: Tue Jan 14 16:50:35 2020 +0100 + + tests: shell: Search diff tool once and for all + + Instead of calling 'which diff' over and over again, just detect the + tool's presence in run-tests.sh and pass $DIFF to each testcase just + like with nft binary. + + Fall back to using 'true' command to avoid the need for any conditional + calling in test cases. + + While being at it, unify potential diff calls so that a string + comparison in shell happens irrespective of diff presence. + + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + tests/shell/run-tests.sh | 7 ++++++- + tests/shell/testcases/flowtable/0010delete_handle_0 | 3 +-- + tests/shell/testcases/listing/0003table_0 | 6 ++---- + tests/shell/testcases/listing/0004table_0 | 3 +-- + tests/shell/testcases/listing/0005ruleset_ip_0 | 3 +-- + tests/shell/testcases/listing/0006ruleset_ip6_0 | 3 +-- + tests/shell/testcases/listing/0007ruleset_inet_0 | 3 +-- + tests/shell/testcases/listing/0008ruleset_arp_0 | 3 +-- + tests/shell/testcases/listing/0009ruleset_bridge_0 | 3 +-- + tests/shell/testcases/listing/0010sets_0 | 3 +-- + tests/shell/testcases/listing/0011sets_0 | 3 +-- + tests/shell/testcases/listing/0012sets_0 | 3 +-- + tests/shell/testcases/listing/0013objects_0 | 3 +-- + tests/shell/testcases/listing/0014objects_0 | 6 ++---- + tests/shell/testcases/listing/0015dynamic_0 | 3 +-- + tests/shell/testcases/listing/0017objects_0 | 3 +-- + tests/shell/testcases/listing/0018data_0 | 3 +-- + tests/shell/testcases/listing/0019set_0 | 3 +-- + tests/shell/testcases/listing/0020flowtable_0 | 3 +-- + tests/shell/testcases/maps/0003map_add_many_elements_0 | 3 +-- + tests/shell/testcases/maps/0004interval_map_create_once_0 | 3 +-- + tests/shell/testcases/maps/0008interval_map_delete_0 | 3 +-- + tests/shell/testcases/netns/0001nft-f_0 | 3 +-- + tests/shell/testcases/netns/0002loosecommands_0 | 3 +-- + tests/shell/testcases/netns/0003many_0 | 3 +-- + tests/shell/testcases/nft-f/0016redefines_1 | 3 +-- + tests/shell/testcases/optionals/delete_object_handles_0 | 3 +-- + tests/shell/testcases/optionals/update_object_handles_0 | 3 +-- + .../shell/testcases/rule_management/0001addinsertposition_0 | 12 ++++-------- + tests/shell/testcases/sets/0028delete_handle_0 | 3 +-- + tests/shell/testcases/sets/0036add_set_element_expiration_0 | 5 ++++- + tests/shell/testcases/transactions/0003table_0 | 4 +--- + tests/shell/testcases/transactions/0040set_0 | 3 +-- + 33 files changed, 46 insertions(+), 75 deletions(-) + +diff --git a/tests/shell/run-tests.sh b/tests/shell/run-tests.sh +index 632ccce..29a2c39 100755 +--- a/tests/shell/run-tests.sh ++++ b/tests/shell/run-tests.sh +@@ -43,6 +43,11 @@ if [ ! -x "$MODPROBE" ] ; then + msg_error "no modprobe binary found" + fi + ++DIFF="$(which diff)" ++if [ ! -x "$DIFF" ] ; then ++ DIFF=true ++fi ++ + if [ "$1" == "-v" ] ; then + VERBOSE=y + shift +@@ -96,7 +101,7 @@ do + kernel_cleanup + + msg_info "[EXECUTING] $testfile" +- test_output=$(NFT=$NFT ${testfile} 2>&1) ++ test_output=$(NFT=$NFT DIFF=$DIFF ${testfile} 2>&1) + rc_got=$? + echo -en "\033[1A\033[K" # clean the [EXECUTING] foobar line + +diff --git a/tests/shell/testcases/flowtable/0010delete_handle_0 b/tests/shell/testcases/flowtable/0010delete_handle_0 +index 985d4a3..8dd8d9f 100755 +--- a/tests/shell/testcases/flowtable/0010delete_handle_0 ++++ b/tests/shell/testcases/flowtable/0010delete_handle_0 +@@ -16,7 +16,6 @@ EXPECTED="table inet t { + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0003table_0 b/tests/shell/testcases/listing/0003table_0 +index 1b288e4..5060be0 100755 +--- a/tests/shell/testcases/listing/0003table_0 ++++ b/tests/shell/testcases/listing/0003table_0 +@@ -11,15 +11,13 @@ $NFT add table test + + GET="$($NFT list table test)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + + # also this way + GET="$($NFT list table ip test)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0004table_0 b/tests/shell/testcases/listing/0004table_0 +index 2c7c995..1d69119 100755 +--- a/tests/shell/testcases/listing/0004table_0 ++++ b/tests/shell/testcases/listing/0004table_0 +@@ -12,8 +12,7 @@ $NFT add table test2 + + GET="$($NFT list table test)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/listing/0005ruleset_ip_0 b/tests/shell/testcases/listing/0005ruleset_ip_0 +index c326680..39c0328 100755 +--- a/tests/shell/testcases/listing/0005ruleset_ip_0 ++++ b/tests/shell/testcases/listing/0005ruleset_ip_0 +@@ -15,7 +15,6 @@ $NFT add table bridge test + + GET="$($NFT list ruleset ip)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0006ruleset_ip6_0 b/tests/shell/testcases/listing/0006ruleset_ip6_0 +index 093d5a5..1b67f50 100755 +--- a/tests/shell/testcases/listing/0006ruleset_ip6_0 ++++ b/tests/shell/testcases/listing/0006ruleset_ip6_0 +@@ -15,7 +15,6 @@ $NFT add table bridge test + + GET="$($NFT list ruleset ip6)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0007ruleset_inet_0 b/tests/shell/testcases/listing/0007ruleset_inet_0 +index b24cc4c..257c7a9 100755 +--- a/tests/shell/testcases/listing/0007ruleset_inet_0 ++++ b/tests/shell/testcases/listing/0007ruleset_inet_0 +@@ -15,7 +15,6 @@ $NFT add table bridge test + + GET="$($NFT list ruleset inet)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0008ruleset_arp_0 b/tests/shell/testcases/listing/0008ruleset_arp_0 +index fff0fee..be42c47 100755 +--- a/tests/shell/testcases/listing/0008ruleset_arp_0 ++++ b/tests/shell/testcases/listing/0008ruleset_arp_0 +@@ -15,7 +15,6 @@ $NFT add table bridge test + + GET="$($NFT list ruleset arp)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0009ruleset_bridge_0 b/tests/shell/testcases/listing/0009ruleset_bridge_0 +index 247ed47..c6a99f5 100755 +--- a/tests/shell/testcases/listing/0009ruleset_bridge_0 ++++ b/tests/shell/testcases/listing/0009ruleset_bridge_0 +@@ -15,7 +15,6 @@ $NFT add table bridge test + + GET="$($NFT list ruleset bridge)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0010sets_0 b/tests/shell/testcases/listing/0010sets_0 +index 855cceb..0f5f2bd 100755 +--- a/tests/shell/testcases/listing/0010sets_0 ++++ b/tests/shell/testcases/listing/0010sets_0 +@@ -57,7 +57,6 @@ $NFT add set inet filter set2 { type icmpv6_type \; } + + GET="$($NFT list sets)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0011sets_0 b/tests/shell/testcases/listing/0011sets_0 +index aac9eac..b6f12b5 100755 +--- a/tests/shell/testcases/listing/0011sets_0 ++++ b/tests/shell/testcases/listing/0011sets_0 +@@ -38,7 +38,6 @@ $NFT add rule inet filter test tcp dport {80, 443} + GET="$($NFT list sets)" + + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0012sets_0 b/tests/shell/testcases/listing/0012sets_0 +index da16d94..6e4c959 100755 +--- a/tests/shell/testcases/listing/0012sets_0 ++++ b/tests/shell/testcases/listing/0012sets_0 +@@ -33,7 +33,6 @@ $NFT add set inet filter set2 { type icmpv6_type \; } + + GET="$($NFT list sets inet)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0013objects_0 b/tests/shell/testcases/listing/0013objects_0 +index f691579..4d39143 100755 +--- a/tests/shell/testcases/listing/0013objects_0 ++++ b/tests/shell/testcases/listing/0013objects_0 +@@ -42,7 +42,6 @@ $NFT add table test-ip + + GET="$($NFT list table test)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0014objects_0 b/tests/shell/testcases/listing/0014objects_0 +index 20f6840..31d94f8 100755 +--- a/tests/shell/testcases/listing/0014objects_0 ++++ b/tests/shell/testcases/listing/0014objects_0 +@@ -17,15 +17,13 @@ $NFT add table test-ip + + GET="$($NFT list quotas)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + + GET="$($NFT list quota test https-quota)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/listing/0015dynamic_0 b/tests/shell/testcases/listing/0015dynamic_0 +index 4ff74e3..65fbe62 100755 +--- a/tests/shell/testcases/listing/0015dynamic_0 ++++ b/tests/shell/testcases/listing/0015dynamic_0 +@@ -16,8 +16,7 @@ $NFT -f - <<< "$EXPECTED" + + GET="$($NFT list set ip filter test_set)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/listing/0017objects_0 b/tests/shell/testcases/listing/0017objects_0 +index 8a586e8..c4e72db 100755 +--- a/tests/shell/testcases/listing/0017objects_0 ++++ b/tests/shell/testcases/listing/0017objects_0 +@@ -13,7 +13,6 @@ $NFT flush map inet filter countermap + + GET="$($NFT list map inet filter countermap)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0018data_0 b/tests/shell/testcases/listing/0018data_0 +index 544b6bf..4af253d 100755 +--- a/tests/shell/testcases/listing/0018data_0 ++++ b/tests/shell/testcases/listing/0018data_0 +@@ -13,7 +13,6 @@ $NFT flush map inet filter ipmap + + GET="$($NFT list map inet filter ipmap)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0019set_0 b/tests/shell/testcases/listing/0019set_0 +index 54a8a06..6e8cb4d 100755 +--- a/tests/shell/testcases/listing/0019set_0 ++++ b/tests/shell/testcases/listing/0019set_0 +@@ -13,7 +13,6 @@ $NFT flush set inet filter ipset + + GET="$($NFT list set inet filter ipset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/listing/0020flowtable_0 b/tests/shell/testcases/listing/0020flowtable_0 +index 6f630f1..2f0a98d 100755 +--- a/tests/shell/testcases/listing/0020flowtable_0 ++++ b/tests/shell/testcases/listing/0020flowtable_0 +@@ -15,7 +15,6 @@ $NFT -f - <<< "$EXPECTED" + + GET="$($NFT list flowtable inet filter f)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/maps/0003map_add_many_elements_0 b/tests/shell/testcases/maps/0003map_add_many_elements_0 +index 047f949..2b254c5 100755 +--- a/tests/shell/testcases/maps/0003map_add_many_elements_0 ++++ b/tests/shell/testcases/maps/0003map_add_many_elements_0 +@@ -61,8 +61,7 @@ EXPECTED="table ip x { + }" + GET=$($NFT list ruleset) + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/maps/0004interval_map_create_once_0 b/tests/shell/testcases/maps/0004interval_map_create_once_0 +index 58b399c..3de0c9d 100755 +--- a/tests/shell/testcases/maps/0004interval_map_create_once_0 ++++ b/tests/shell/testcases/maps/0004interval_map_create_once_0 +@@ -60,8 +60,7 @@ EXPECTED="table ip x { + }" + GET=$($NFT list ruleset) + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/maps/0008interval_map_delete_0 b/tests/shell/testcases/maps/0008interval_map_delete_0 +index 7da6eb3..39ea312 100755 +--- a/tests/shell/testcases/maps/0008interval_map_delete_0 ++++ b/tests/shell/testcases/maps/0008interval_map_delete_0 +@@ -26,7 +26,6 @@ $NFT add element filter m { 127.0.0.2 : 0x2 } + + GET=$($NFT -s list ruleset) + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/netns/0001nft-f_0 b/tests/shell/testcases/netns/0001nft-f_0 +index 8194226..a591f2c 100755 +--- a/tests/shell/testcases/netns/0001nft-f_0 ++++ b/tests/shell/testcases/netns/0001nft-f_0 +@@ -93,8 +93,7 @@ fi + KERNEL_RULESET="$($IP netns exec $NETNS_NAME $NFT list ruleset)" + $IP netns del $NETNS_NAME + if [ "$RULESET" != "$KERNEL_RULESET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") ++ $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") + exit 1 + fi + exit 0 +diff --git a/tests/shell/testcases/netns/0002loosecommands_0 b/tests/shell/testcases/netns/0002loosecommands_0 +index 465c2e8..231f1fb 100755 +--- a/tests/shell/testcases/netns/0002loosecommands_0 ++++ b/tests/shell/testcases/netns/0002loosecommands_0 +@@ -56,7 +56,6 @@ RULESET="table ip t { + KERNEL_RULESET="$($IP netns exec $NETNS_NAME $NFT list ruleset)" + $IP netns del $NETNS_NAME + if [ "$RULESET" != "$KERNEL_RULESET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") ++ $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") + exit 1 + fi +diff --git a/tests/shell/testcases/netns/0003many_0 b/tests/shell/testcases/netns/0003many_0 +index a5fcb5d..afe9117 100755 +--- a/tests/shell/testcases/netns/0003many_0 ++++ b/tests/shell/testcases/netns/0003many_0 +@@ -97,8 +97,7 @@ function test_netns() + KERNEL_RULESET="$($IP netns exec $NETNS_NAME $NFT list ruleset)" + if [ "$RULESET" != "$KERNEL_RULESET" ] ; then + echo "E: ruleset in netns $NETNS_NAME differs from the loaded" >&2 +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") ++ $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") + $IP netns del $NETNS_NAME + exit 1 + fi +diff --git a/tests/shell/testcases/nft-f/0016redefines_1 b/tests/shell/testcases/nft-f/0016redefines_1 +index 4c26b37..1f59f6b 100755 +--- a/tests/shell/testcases/nft-f/0016redefines_1 ++++ b/tests/shell/testcases/nft-f/0016redefines_1 +@@ -26,8 +26,7 @@ $NFT -f - <<< "$RULESET" + GET="$($NFT list ruleset)" + + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + +diff --git a/tests/shell/testcases/optionals/delete_object_handles_0 b/tests/shell/testcases/optionals/delete_object_handles_0 +index a2ae422..9b65e67 100755 +--- a/tests/shell/testcases/optionals/delete_object_handles_0 ++++ b/tests/shell/testcases/optionals/delete_object_handles_0 +@@ -37,7 +37,6 @@ table ip6 test-ip6 { + GET="$($NFT list ruleset)" + + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/optionals/update_object_handles_0 b/tests/shell/testcases/optionals/update_object_handles_0 +index 17c0c86..8b12b8c 100755 +--- a/tests/shell/testcases/optionals/update_object_handles_0 ++++ b/tests/shell/testcases/optionals/update_object_handles_0 +@@ -19,7 +19,6 @@ EXPECTED="table ip test-ip { + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/rule_management/0001addinsertposition_0 b/tests/shell/testcases/rule_management/0001addinsertposition_0 +index bb3fda5..237e9e3 100755 +--- a/tests/shell/testcases/rule_management/0001addinsertposition_0 ++++ b/tests/shell/testcases/rule_management/0001addinsertposition_0 +@@ -30,8 +30,7 @@ for arg in "position 2" "handle 2" "index 0"; do + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + done +@@ -42,8 +41,7 @@ for arg in "position 3" "handle 3" "index 1"; do + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + done +@@ -62,8 +60,7 @@ for arg in "position 3" "handle 3" "index 1"; do + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + done +@@ -82,8 +79,7 @@ for arg in "position 2" "handle 2" "index 0"; do + + GET="$($NFT list ruleset)" + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi + done +diff --git a/tests/shell/testcases/sets/0028delete_handle_0 b/tests/shell/testcases/sets/0028delete_handle_0 +index 5ad17c2..c6d1253 100755 +--- a/tests/shell/testcases/sets/0028delete_handle_0 ++++ b/tests/shell/testcases/sets/0028delete_handle_0 +@@ -29,7 +29,6 @@ EXPECTED="table ip test-ip { + GET="$($NFT list ruleset)" + + if [ "$EXPECTED" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 + fi +diff --git a/tests/shell/testcases/sets/0036add_set_element_expiration_0 b/tests/shell/testcases/sets/0036add_set_element_expiration_0 +index 8dfed6c..51ed0f2 100755 +--- a/tests/shell/testcases/sets/0036add_set_element_expiration_0 ++++ b/tests/shell/testcases/sets/0036add_set_element_expiration_0 +@@ -8,6 +8,9 @@ add element ip x y { 1.1.1.1 timeout 30s expires 15s }" + + test_output=$($NFT -e -f - <<< "$RULESET" 2>&1) + +-diff -u <(echo "$test_output") <(echo "$RULESET") ++if [ "$test_output" != "$RULESET" ] ; then ++ $DIFF -u <(echo "$test_output") <(echo "$RULESET") ++ exit 1 ++fi + + $NFT "add chain ip x c; add rule ip x c ip saddr @y" +diff --git a/tests/shell/testcases/transactions/0003table_0 b/tests/shell/testcases/transactions/0003table_0 +index 6861eab..91186de 100755 +--- a/tests/shell/testcases/transactions/0003table_0 ++++ b/tests/shell/testcases/transactions/0003table_0 +@@ -14,7 +14,6 @@ fi + + KERNEL_RULESET="$($NFT list ruleset)" + if [ "" != "$KERNEL_RULESET" ] ; then +- DIFF="$(which diff)" + echo "Got a ruleset, but expected empty: " + echo "$KERNEL_RULESET" + exit 1 +@@ -42,7 +41,6 @@ $NFT -f - <<< "$RULESETFAIL" && exit 2 + + KERNEL_RULESET="$($NFT list ruleset)" + if [ "$RULESET" != "$KERNEL_RULESET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") ++ $DIFF -u <(echo "$RULESET") <(echo "$KERNEL_RULESET") + exit 1 + fi +diff --git a/tests/shell/testcases/transactions/0040set_0 b/tests/shell/testcases/transactions/0040set_0 +index a404abc..468816b 100755 +--- a/tests/shell/testcases/transactions/0040set_0 ++++ b/tests/shell/testcases/transactions/0040set_0 +@@ -29,8 +29,7 @@ fi + GET="$($NFT list ruleset)" + + if [ "$RULESET" != "$GET" ] ; then +- DIFF="$(which diff)" +- [ -x $DIFF ] && $DIFF -u <(echo "$RULESET") <(echo "$GET") ++ $DIFF -u <(echo "$RULESET") <(echo "$GET") + exit 1 + fi + +-- +1.8.3.1 + diff --git a/SOURCES/0007-cache-Fix-for-doubled-output-after-reset-command.patch b/SOURCES/0007-cache-Fix-for-doubled-output-after-reset-command.patch new file mode 100644 index 0000000..b1aba78 --- /dev/null +++ b/SOURCES/0007-cache-Fix-for-doubled-output-after-reset-command.patch @@ -0,0 +1,85 @@ +From a44bd9f4b6cf77cb75c5f596908100270893e8d5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 17 Jan 2020 12:50:23 +0100 +Subject: [PATCH] cache: Fix for doubled output after reset command + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1790793 +Upstream Status: nftables commit 7def18395d118 + +commit 7def18395d118e22a009de7e2e8de7f77906580b +Author: Phil Sutter +Date: Tue Jan 14 17:25:35 2020 +0100 + + cache: Fix for doubled output after reset command + + Reset command causes a dump of the objects to reset and adds those to + cache. Yet it ignored if the object in question was already there and up + to now CMD_RESET was flagged as NFT_CACHE_FULL. + + Tackle this from two angles: First, reduce cache requirements of reset + command to the necessary bits which is table cache. This alone would + suffice if there wasn't interactive mode (and other libnftables users): + A cache containing the objects to reset might be in place already, so + add dumped objects to cache only if they don't exist already. + + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + src/cache.c | 4 +++- + src/rule.c | 3 ++- + tests/shell/testcases/sets/0024named_objects_0 | 12 +++++++++++- + 3 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 0c28a28..05f0d68 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -138,8 +138,10 @@ unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) + case CMD_GET: + flags = evaluate_cache_get(cmd, flags); + break; +- case CMD_LIST: + case CMD_RESET: ++ flags |= NFT_CACHE_TABLE; ++ break; ++ case CMD_LIST: + case CMD_EXPORT: + case CMD_MONITOR: + flags |= NFT_CACHE_FULL; +diff --git a/src/rule.c b/src/rule.c +index d985d3a..3ca1805 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -2554,7 +2554,8 @@ static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd) + ret = netlink_reset_objs(ctx, cmd, type, dump); + list_for_each_entry_safe(obj, next, &ctx->list, list) { + table = table_lookup(&obj->handle, &ctx->nft->cache); +- list_move(&obj->list, &table->objs); ++ if (!obj_lookup(table, obj->handle.obj.name, obj->type)) ++ list_move(&obj->list, &table->objs); + } + if (ret < 0) + return ret; +diff --git a/tests/shell/testcases/sets/0024named_objects_0 b/tests/shell/testcases/sets/0024named_objects_0 +index 3bd16f2..21200c3 100755 +--- a/tests/shell/testcases/sets/0024named_objects_0 ++++ b/tests/shell/testcases/sets/0024named_objects_0 +@@ -35,4 +35,14 @@ table inet x { + set -e + $NFT -f - <<< "$RULESET" + +-$NFT reset counter inet x user321 ++EXPECTED="table inet x { ++ counter user321 { ++ packets 12 bytes 1433 ++ } ++}" ++ ++GET="$($NFT reset counter inet x user321)" ++if [ "$EXPECTED" != "$GET" ] ; then ++ $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ exit 1 ++fi +-- +1.8.3.1 + diff --git a/SOURCES/0008-netlink-Fix-leak-in-unterminated-string-deserializer.patch b/SOURCES/0008-netlink-Fix-leak-in-unterminated-string-deserializer.patch new file mode 100644 index 0000000..b15c611 --- /dev/null +++ b/SOURCES/0008-netlink-Fix-leak-in-unterminated-string-deserializer.patch @@ -0,0 +1,51 @@ +From cc70f19e588a0a33ed86c4a059b56a8f5b0c7a82 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 27 Jan 2020 16:11:41 +0100 +Subject: [PATCH] netlink: Fix leak in unterminated string deserializer + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1793030 +Upstream Status: nftables commit c3f6be3f2dced + +commit c3f6be3f2dcedf6d79751c0b975315ebc3184364 +Author: Phil Sutter +Date: Mon Jan 20 13:52:10 2020 +0100 + + netlink: Fix leak in unterminated string deserializer + + Allocated 'mask' expression is not freed before returning to caller, + although it is used temporarily only. + + Fixes: b851ba4731d9f ("src: add interface wildcard matching") + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + src/netlink_delinearize.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c +index 154353b..06a0312 100644 +--- a/src/netlink_delinearize.c ++++ b/src/netlink_delinearize.c +@@ -2030,7 +2030,7 @@ static bool __expr_postprocess_string(struct expr **exprp) + + static struct expr *expr_postprocess_string(struct expr *expr) + { +- struct expr *mask; ++ struct expr *mask, *out; + + assert(expr_basetype(expr)->type == TYPE_STRING); + if (__expr_postprocess_string(&expr)) +@@ -2040,7 +2040,9 @@ static struct expr *expr_postprocess_string(struct expr *expr) + BYTEORDER_HOST_ENDIAN, + expr->len + BITS_PER_BYTE, NULL); + mpz_init_bitmask(mask->value, expr->len); +- return string_wildcard_expr_alloc(&expr->location, mask, expr); ++ out = string_wildcard_expr_alloc(&expr->location, mask, expr); ++ expr_free(mask); ++ return out; + } + + static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) +-- +1.8.3.1 + diff --git a/SOURCES/0009-netlink-Fix-leaks-in-netlink_parse_cmp.patch b/SOURCES/0009-netlink-Fix-leaks-in-netlink_parse_cmp.patch new file mode 100644 index 0000000..46e878c --- /dev/null +++ b/SOURCES/0009-netlink-Fix-leaks-in-netlink_parse_cmp.patch @@ -0,0 +1,75 @@ +From 6ecccc872b9cbed921af10e32d1a628eb6a74c01 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 27 Jan 2020 16:11:41 +0100 +Subject: [PATCH] netlink: Fix leaks in netlink_parse_cmp() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1793030 +Upstream Status: nftables commit e957bd9f10d5e + +commit e957bd9f10d5e36671a0b0398e2037fc6201275b +Author: Phil Sutter +Date: Mon Jan 20 14:48:26 2020 +0100 + + netlink: Fix leaks in netlink_parse_cmp() + + This fixes several problems at once: + + * Err path would leak expr 'right' in two places and 'left' in one. + * Concat case would leak 'right' by overwriting the pointer. Introduce a + temporary variable to hold the new pointer. + + Fixes: 6377380bc265f ("netlink_delinearize: handle relational and lookup concat expressions") + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + src/netlink_delinearize.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c +index 06a0312..88dbd5a 100644 +--- a/src/netlink_delinearize.c ++++ b/src/netlink_delinearize.c +@@ -274,7 +274,7 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx, + { + struct nft_data_delinearize nld; + enum nft_registers sreg; +- struct expr *expr, *left, *right; ++ struct expr *expr, *left, *right, *tmp; + enum ops op; + + sreg = netlink_parse_register(nle, NFTNL_EXPR_CMP_SREG); +@@ -291,19 +291,26 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx, + + if (left->len > right->len && + expr_basetype(left) != &string_type) { +- return netlink_error(ctx, loc, "Relational expression size mismatch"); ++ netlink_error(ctx, loc, "Relational expression size mismatch"); ++ goto err_free; + } else if (left->len > 0 && left->len < right->len) { + expr_free(left); + left = netlink_parse_concat_expr(ctx, loc, sreg, right->len); + if (left == NULL) +- return; +- right = netlink_parse_concat_data(ctx, loc, sreg, right->len, right); +- if (right == NULL) +- return; ++ goto err_free; ++ tmp = netlink_parse_concat_data(ctx, loc, sreg, right->len, right); ++ if (tmp == NULL) ++ goto err_free; ++ expr_free(right); ++ right = tmp; + } + + expr = relational_expr_alloc(loc, op, left, right); + ctx->stmt = expr_stmt_alloc(loc, expr); ++ return; ++err_free: ++ expr_free(left); ++ expr_free(right); + } + + static void netlink_parse_lookup(struct netlink_parse_ctx *ctx, +-- +1.8.3.1 + diff --git a/SOURCES/0010-netlink-Avoid-potential-NULL-pointer-deref-in-netlin.patch b/SOURCES/0010-netlink-Avoid-potential-NULL-pointer-deref-in-netlin.patch new file mode 100644 index 0000000..b48f1e6 --- /dev/null +++ b/SOURCES/0010-netlink-Avoid-potential-NULL-pointer-deref-in-netlin.patch @@ -0,0 +1,42 @@ +From 55c537734f476d04c18f67083642b96bbead6219 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 27 Jan 2020 16:11:41 +0100 +Subject: [PATCH] netlink: Avoid potential NULL-pointer deref in + netlink_gen_payload_stmt() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1793030 +Upstream Status: nftables commit c9ddf0bff363f + +commit c9ddf0bff363fc9101b563b592db600bdf4d65c5 +Author: Phil Sutter +Date: Mon Jan 20 16:32:40 2020 +0100 + + netlink: Avoid potential NULL-pointer deref in netlink_gen_payload_stmt() + + With payload_needs_l4csum_update_pseudohdr() unconditionally + dereferencing passed 'desc' parameter and a previous check for it to be + non-NULL, make sure to call the function only if input is sane. + + Fixes: 68de70f2b3fc6 ("netlink_linearize: fix IPv6 layer 4 checksum mangling") + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + src/netlink_linearize.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c +index 498326d..cb1b7fe 100644 +--- a/src/netlink_linearize.c ++++ b/src/netlink_linearize.c +@@ -941,7 +941,7 @@ static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx, + nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_CSUM_OFFSET, + csum_off / BITS_PER_BYTE); + } +- if (expr->payload.base == PROTO_BASE_NETWORK_HDR && ++ if (expr->payload.base == PROTO_BASE_NETWORK_HDR && desc && + payload_needs_l4csum_update_pseudohdr(expr, desc)) + nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_FLAGS, + NFT_PAYLOAD_L4CSUM_PSEUDOHDR); +-- +1.8.3.1 + diff --git a/SOURCES/0011-tests-json_echo-Fix-for-Python3.patch b/SOURCES/0011-tests-json_echo-Fix-for-Python3.patch new file mode 100644 index 0000000..f907886 --- /dev/null +++ b/SOURCES/0011-tests-json_echo-Fix-for-Python3.patch @@ -0,0 +1,39 @@ +From 04d0d2e685063d422ce73b67eb01d4803100d379 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:35:27 +0100 +Subject: [PATCH] tests: json_echo: Fix for Python3 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1754047 +Upstream Status: nftables commit 582f142b1578b + +commit 582f142b1578b6036707242bfe874bcefc002ac2 +Author: Phil Sutter +Date: Thu Feb 6 01:21:30 2020 +0100 + + tests: json_echo: Fix for Python3 + + The keys() method returns an object which does not support indexing, so + convert it to a list prior to doing so. + + Fixes: a35e3a0cdc63a ("tests: json_echo: convert to py3") + Signed-off-by: Phil Sutter +--- + tests/json_echo/run-test.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/json_echo/run-test.py b/tests/json_echo/run-test.py +index a636d5f..fa7d69a 100755 +--- a/tests/json_echo/run-test.py ++++ b/tests/json_echo/run-test.py +@@ -119,7 +119,7 @@ def get_handle(output, search): + else: + data = item + +- k = search.keys()[0] ++ k = list(search.keys())[0] + + if not k in data: + continue +-- +1.8.3.1 + diff --git a/SOURCES/0012-tests-json_echo-Support-testing-host-binaries.patch b/SOURCES/0012-tests-json_echo-Support-testing-host-binaries.patch new file mode 100644 index 0000000..c2958df --- /dev/null +++ b/SOURCES/0012-tests-json_echo-Support-testing-host-binaries.patch @@ -0,0 +1,68 @@ +From 0eb301a3f50fb70cb78d955692f3feea1ad8095e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:35:27 +0100 +Subject: [PATCH] tests: json_echo: Support testing host binaries + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1754047 +Upstream Status: nftables commit 106b1f2b93f82 + +commit 106b1f2b93f82784c18dd5e312bbf88e6c02a5b8 +Author: Phil Sutter +Date: Fri Jan 10 11:19:42 2020 +0100 + + tests: json_echo: Support testing host binaries + + Support -H/--host option to use host's libnftables.so.1. Alternatively + users may specify a custom library path via -l/--library option. + + Signed-off-by: Phil Sutter +--- + tests/json_echo/run-test.py | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/tests/json_echo/run-test.py b/tests/json_echo/run-test.py +index fa7d69a..36a377a 100755 +--- a/tests/json_echo/run-test.py ++++ b/tests/json_echo/run-test.py +@@ -4,6 +4,7 @@ from __future__ import print_function + import sys + import os + import json ++import argparse + + TESTS_PATH = os.path.dirname(os.path.abspath(__file__)) + sys.path.insert(0, os.path.join(TESTS_PATH, '../../py/')) +@@ -13,12 +14,26 @@ from nftables import Nftables + # Change working directory to repository root + os.chdir(TESTS_PATH + "/../..") + +-if not os.path.exists('src/.libs/libnftables.so'): +- print("The nftables library does not exist. " +- "You need to build the project.") ++parser = argparse.ArgumentParser(description='Run JSON echo tests') ++parser.add_argument('-H', '--host', action='store_true', ++ help='Run tests against installed libnftables.so.1') ++parser.add_argument('-l', '--library', default=None, ++ help='Path to libntables.so, overrides --host') ++args = parser.parse_args() ++ ++check_lib_path = True ++if args.library is None: ++ if args.host: ++ args.library = 'libnftables.so.1' ++ check_lib_path = False ++ else: ++ args.library = 'src/.libs/libnftables.so.1' ++ ++if check_lib_path and not os.path.exists(args.library): ++ print("Library not found at '%s'." % args.library) + sys.exit(1) + +-nftables = Nftables(sofile = 'src/.libs/libnftables.so') ++nftables = Nftables(sofile = args.library) + nftables.set_echo_output(True) + + # various commands to work with +-- +1.8.3.1 + diff --git a/SOURCES/0013-tests-monitor-Support-running-individual-test-cases.patch b/SOURCES/0013-tests-monitor-Support-running-individual-test-cases.patch new file mode 100644 index 0000000..26c9079 --- /dev/null +++ b/SOURCES/0013-tests-monitor-Support-running-individual-test-cases.patch @@ -0,0 +1,64 @@ +From 67f168ebfbeb26a8d7e4f1b9284cc32f13ceff9b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:35:27 +0100 +Subject: [PATCH] tests: monitor: Support running individual test cases + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1754047 +Upstream Status: nftables commit eb5034108cdc6 + +commit eb5034108cdc60341b2d61599077db935b6bbc4f +Author: Phil Sutter +Date: Fri Jan 10 11:15:45 2020 +0100 + + tests: monitor: Support running individual test cases + + Recognize testcase paths on command line and limit testing on those + only. + + Signed-off-by: Phil Sutter + Acked-by: Pablo Neira Ayuso +--- + tests/monitor/run-tests.sh | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh +index 0478cf6..efacdaa 100755 +--- a/tests/monitor/run-tests.sh ++++ b/tests/monitor/run-tests.sh +@@ -108,6 +108,7 @@ echo_run_test() { + touch $output_file + } + ++testcases="" + while [ -n "$1" ]; do + case "$1" in + -d|--debug) +@@ -118,11 +119,15 @@ while [ -n "$1" ]; do + test_json=true + shift + ;; ++ testcases/*.t) ++ testcases+=" $1" ++ shift ++ ;; + *) + echo "unknown option '$1'" + ;& + -h|--help) +- echo "Usage: $(basename $0) [-j|--json] [-d|--debug]" ++ echo "Usage: $(basename $0) [-j|--json] [-d|--debug] [testcase ...]" + exit 1 + ;; + esac +@@ -138,7 +143,7 @@ for variant in $variants; do + run_test=${variant}_run_test + output_append=${variant}_output_append + +- for testcase in testcases/*.t; do ++ for testcase in ${testcases:-testcases/*.t}; do + echo "$variant: running tests from file $(basename $testcase)" + # files are like this: + # +-- +1.8.3.1 + diff --git a/SOURCES/0014-tests-monitor-Support-testing-host-s-nft-binary.patch b/SOURCES/0014-tests-monitor-Support-testing-host-s-nft-binary.patch new file mode 100644 index 0000000..502b623 --- /dev/null +++ b/SOURCES/0014-tests-monitor-Support-testing-host-s-nft-binary.patch @@ -0,0 +1,40 @@ +From 18e1b545cbd2d055b16ec3bf5f481d8032dc5dbe Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:35:27 +0100 +Subject: [PATCH] tests: monitor: Support testing host's nft binary + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1754047 +Upstream Status: nftables commit 15ede6857c8c5 + +commit 15ede6857c8c578ec6211c8b68424183ba1baf1a +Author: Phil Sutter +Date: Wed Feb 5 19:48:53 2020 +0100 + + tests: monitor: Support testing host's nft binary + + Add support for -H/--host flag to use 'nft' tool from $PATH instead of + the local one. + + Signed-off-by: Phil Sutter +--- + tests/monitor/run-tests.sh | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh +index efacdaa..ffb833a 100755 +--- a/tests/monitor/run-tests.sh ++++ b/tests/monitor/run-tests.sh +@@ -119,6 +119,10 @@ while [ -n "$1" ]; do + test_json=true + shift + ;; ++ -H|--host) ++ nft=nft ++ shift ++ ;; + testcases/*.t) + testcases+=" $1" + shift +-- +1.8.3.1 + diff --git a/SOURCES/0015-tests-py-Support-testing-host-binaries.patch b/SOURCES/0015-tests-py-Support-testing-host-binaries.patch new file mode 100644 index 0000000..007fc9b --- /dev/null +++ b/SOURCES/0015-tests-py-Support-testing-host-binaries.patch @@ -0,0 +1,76 @@ +From 74575c409bad2940470f31946c97430043c3195e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:35:27 +0100 +Subject: [PATCH] tests: py: Support testing host binaries + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1754047 +Upstream Status: nftables commit 5f2746205e50c + +commit 5f2746205e50c77295d0f84f8178ee3a1ce15407 +Author: Phil Sutter +Date: Thu Feb 6 01:36:01 2020 +0100 + + tests: py: Support testing host binaries + + Support -H/--host option to use host's libnftables.so.1. Alternatively + users may specify a custom library path via -l/--library option. + + Signed-off-by: Phil Sutter +--- + tests/py/nft-test.py | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py +index 6edca3c..01ee6c9 100755 +--- a/tests/py/nft-test.py ++++ b/tests/py/nft-test.py +@@ -1357,10 +1357,16 @@ def main(): + dest='force_all_family', + help='keep testing all families on error') + ++ parser.add_argument('-H', '--host', action='store_true', ++ help='run tests against installed libnftables.so.1') ++ + parser.add_argument('-j', '--enable-json', action='store_true', + dest='enable_json', + help='test JSON functionality as well') + ++ parser.add_argument('-l', '--library', default=None, ++ help='path to libntables.so.1, overrides --host') ++ + parser.add_argument('-s', '--schema', action='store_true', + dest='enable_schema', + help='verify json input/output against schema') +@@ -1388,9 +1394,17 @@ def main(): + # Change working directory to repository root + os.chdir(TESTS_PATH + "/../..") + +- if not os.path.exists('src/.libs/libnftables.so'): +- print("The nftables library does not exist. " +- "You need to build the project.") ++ check_lib_path = True ++ if args.library is None: ++ if args.host: ++ args.library = 'libnftables.so.1' ++ check_lib_path = False ++ else: ++ args.library = 'src/.libs/libnftables.so.1' ++ ++ if check_lib_path and not os.path.exists(args.library): ++ print("The nftables library at '%s' does not exist. " ++ "You need to build the project." % args.library) + return + + if args.enable_schema and not args.enable_json: +@@ -1398,7 +1412,7 @@ def main(): + return + + global nftables +- nftables = Nftables(sofile = 'src/.libs/libnftables.so') ++ nftables = Nftables(sofile = args.library) + + test_files = files_ok = run_total = 0 + tests = passed = warnings = errors = 0 +-- +1.8.3.1 + diff --git a/SOURCES/0016-doc-nft.8-Mention-wildcard-interface-matching.patch b/SOURCES/0016-doc-nft.8-Mention-wildcard-interface-matching.patch new file mode 100644 index 0000000..f534eec --- /dev/null +++ b/SOURCES/0016-doc-nft.8-Mention-wildcard-interface-matching.patch @@ -0,0 +1,43 @@ +From d58192a8d2810271d5c6525dc66ba1e1ec3fd2b7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:39:44 +0100 +Subject: [PATCH] doc: nft.8: Mention wildcard interface matching + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1763652 +Upstream Status: nftables commit 03d45ad330a25 + +commit 03d45ad330a25323610648bb05f550e0fb9d65b2 +Author: Phil Sutter +Date: Thu Feb 6 12:24:51 2020 +0100 + + doc: nft.8: Mention wildcard interface matching + + Special meaning of asterisk in interface names wasn't described + anywhere. + + Signed-off-by: Phil Sutter +--- + doc/primary-expression.txt | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/doc/primary-expression.txt b/doc/primary-expression.txt +index 5473d59..a5cab9d 100644 +--- a/doc/primary-expression.txt ++++ b/doc/primary-expression.txt +@@ -36,6 +36,13 @@ add such a rule, it will stop matching if the interface gets renamed and it + will match again in case interface gets deleted and later a new interface + with the same name is created. + ++Like with iptables, wildcard matching on interface name prefixes is available for ++*iifname* and *oifname* matches by appending an asterisk (*) character. Note ++however that unlike iptables, nftables does not accept interface names ++consisting of the wildcard character only - users are supposed to just skip ++those always matching expressions. In order to match on literal asterisk ++character, one may escape it using backslash (\). ++ + .Meta expression types + [options="header"] + |================== +-- +1.8.3.1 + diff --git a/SOURCES/0017-scanner-Extend-asteriskstring-definition.patch b/SOURCES/0017-scanner-Extend-asteriskstring-definition.patch new file mode 100644 index 0000000..09717b0 --- /dev/null +++ b/SOURCES/0017-scanner-Extend-asteriskstring-definition.patch @@ -0,0 +1,39 @@ +From 34ba60c0c2b6057e8b56a77e47899bbeccd88bfd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Feb 2020 22:39:44 +0100 +Subject: [PATCH] scanner: Extend asteriskstring definition + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1763652 +Upstream Status: nftables commit 556c5a94b8067 + +commit 556c5a94b8067f33ef0a42836753dae0736b7524 +Author: Phil Sutter +Date: Thu Feb 6 12:31:56 2020 +0100 + + scanner: Extend asteriskstring definition + + Accept escaped asterisks also mid-string and as only character. + Especially the latter will help when translating from iptables where + asterisk has no special meaning. + + Signed-off-by: Phil Sutter +--- + src/scanner.l | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/scanner.l b/src/scanner.l +index d32adf4..7daf5c1 100644 +--- a/src/scanner.l ++++ b/src/scanner.l +@@ -120,7 +120,7 @@ numberstring ({decstring}|{hexstring}) + letter [a-zA-Z] + string ({letter}|[_.])({letter}|{digit}|[/\-_\.])* + quotedstring \"[^"]*\" +-asteriskstring ({string}\*|{string}\\\*) ++asteriskstring ({string}\*|{string}\\\*|\\\*|{string}\\\*{string}) + comment #.*$ + slash \/ + +-- +1.8.3.1 + diff --git a/SOURCES/0018-parser-add-a-helper-for-concat-expression-handling.patch b/SOURCES/0018-parser-add-a-helper-for-concat-expression-handling.patch new file mode 100644 index 0000000..5a93472 --- /dev/null +++ b/SOURCES/0018-parser-add-a-helper-for-concat-expression-handling.patch @@ -0,0 +1,162 @@ +From 160d84fb761c54a5f757aff907fc197d259196bd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 17 Feb 2020 15:26:42 +0100 +Subject: [PATCH] parser: add a helper for concat expression handling + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795224 +Upstream Status: nftables commit 10f114806ccd9 + +commit 10f114806ccd9d64f9d72eaa813babb04d719688 +Author: Florian Westphal +Date: Wed Dec 11 14:31:44 2019 +0100 + + parser: add a helper for concat expression handling + + Cull the repeated copy&paste snippets and add/use a helper for this. + + Signed-off-by: Florian Westphal +--- + src/parser_bison.y | 99 ++++++++++++++++++++++++------------------------------ + 1 file changed, 43 insertions(+), 56 deletions(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 707f467..0fd9b94 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -102,6 +102,25 @@ static void location_update(struct location *loc, struct location *rhs, int n) + } + } + ++static struct expr *handle_concat_expr(const struct location *loc, ++ struct expr *expr, ++ struct expr *expr_l, struct expr *expr_r, ++ struct location loc_rhs[3]) ++{ ++ if (expr->etype != EXPR_CONCAT) { ++ expr = concat_expr_alloc(loc); ++ compound_expr_add(expr, expr_l); ++ } else { ++ location_update(&expr_r->location, loc_rhs, 2); ++ ++ expr = expr_l; ++ expr->location = *loc; ++ } ++ ++ compound_expr_add(expr, expr_r); ++ return expr; ++} ++ + #define YYLLOC_DEFAULT(Current, Rhs, N) location_update(&Current, Rhs, N) + + #define symbol_value(loc, str) \ +@@ -1878,20 +1897,12 @@ data_type_atom_expr : type_identifier + data_type_expr : data_type_atom_expr + | data_type_expr DOT data_type_atom_expr + { +- if ($1->etype != EXPR_CONCAT) { +- $$ = concat_expr_alloc(&@$); +- compound_expr_add($$, $1); +- } else { +- struct location rhs[] = { +- [1] = @2, +- [2] = @3, +- }; +- location_update(&$3->location, rhs, 2); +- +- $$ = $1; +- $$->location = @$; +- } +- compound_expr_add($$, $3); ++ struct location rhs[] = { ++ [1] = @2, ++ [2] = @3, ++ }; ++ ++ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs); + } + ; + +@@ -2992,20 +3003,12 @@ basic_stmt_expr : inclusive_or_stmt_expr + concat_stmt_expr : basic_stmt_expr + | concat_stmt_expr DOT primary_stmt_expr + { +- if ($$->etype != EXPR_CONCAT) { +- $$ = concat_expr_alloc(&@$); +- compound_expr_add($$, $1); +- } else { +- struct location rhs[] = { +- [1] = @2, +- [2] = @3, +- }; +- location_update(&$3->location, rhs, 2); +- +- $$ = $1; +- $$->location = @$; +- } +- compound_expr_add($$, $3); ++ struct location rhs[] = { ++ [1] = @2, ++ [2] = @3, ++ }; ++ ++ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs); + } + ; + +@@ -3525,20 +3528,12 @@ basic_expr : inclusive_or_expr + concat_expr : basic_expr + | concat_expr DOT basic_expr + { +- if ($$->etype != EXPR_CONCAT) { +- $$ = concat_expr_alloc(&@$); +- compound_expr_add($$, $1); +- } else { +- struct location rhs[] = { +- [1] = @2, +- [2] = @3, +- }; +- location_update(&$3->location, rhs, 2); +- +- $$ = $1; +- $$->location = @$; +- } +- compound_expr_add($$, $3); ++ struct location rhs[] = { ++ [1] = @2, ++ [2] = @3, ++ }; ++ ++ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs); + } + ; + +@@ -3946,20 +3941,12 @@ basic_rhs_expr : inclusive_or_rhs_expr + concat_rhs_expr : basic_rhs_expr + | concat_rhs_expr DOT basic_rhs_expr + { +- if ($$->etype != EXPR_CONCAT) { +- $$ = concat_expr_alloc(&@$); +- compound_expr_add($$, $1); +- } else { +- struct location rhs[] = { +- [1] = @2, +- [2] = @3, +- }; +- location_update(&$3->location, rhs, 2); +- +- $$ = $1; +- $$->location = @$; +- } +- compound_expr_add($$, $3); ++ struct location rhs[] = { ++ [1] = @2, ++ [2] = @3, ++ }; ++ ++ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs); + } + ; + +-- +1.8.3.1 + diff --git a/SOURCES/0019-include-resync-nf_tables.h-cache-copy.patch b/SOURCES/0019-include-resync-nf_tables.h-cache-copy.patch new file mode 100644 index 0000000..bd55b39 --- /dev/null +++ b/SOURCES/0019-include-resync-nf_tables.h-cache-copy.patch @@ -0,0 +1,84 @@ +From e872d169c189f363ebbdc39105510c1809b58276 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Feb 2020 17:48:18 +0100 +Subject: [PATCH] include: resync nf_tables.h cache copy + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795224 +Upstream Status: nftables commit 9b94127950f98 + +commit 9b94127950f9848bc5a1505ae65ca3045ff68a16 +Author: Stefano Brivio +Date: Thu Jan 30 01:16:55 2020 +0100 + + include: resync nf_tables.h cache copy + + Get this header in sync with nf-next as of merge commit + b3a608222336 (5.6-rc1-ish). + + Signed-off-by: Stefano Brivio + Signed-off-by: Pablo Neira Ayuso +--- + include/linux/netfilter/nf_tables.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h +index ed8881a..1a99df3 100644 +--- a/include/linux/netfilter/nf_tables.h ++++ b/include/linux/netfilter/nf_tables.h +@@ -48,6 +48,7 @@ enum nft_registers { + + #define NFT_REG_SIZE 16 + #define NFT_REG32_SIZE 4 ++#define NFT_REG32_COUNT (NFT_REG32_15 - NFT_REG32_00 + 1) + + /** + * enum nft_verdicts - nf_tables internal verdicts +@@ -299,15 +300,29 @@ enum nft_set_policies { + * enum nft_set_desc_attributes - set element description + * + * @NFTA_SET_DESC_SIZE: number of elements in set (NLA_U32) ++ * @NFTA_SET_DESC_CONCAT: description of field concatenation (NLA_NESTED) + */ + enum nft_set_desc_attributes { + NFTA_SET_DESC_UNSPEC, + NFTA_SET_DESC_SIZE, ++ NFTA_SET_DESC_CONCAT, + __NFTA_SET_DESC_MAX + }; + #define NFTA_SET_DESC_MAX (__NFTA_SET_DESC_MAX - 1) + + /** ++ * enum nft_set_field_attributes - attributes of concatenated fields ++ * ++ * @NFTA_SET_FIELD_LEN: length of single field, in bits (NLA_U32) ++ */ ++enum nft_set_field_attributes { ++ NFTA_SET_FIELD_UNSPEC, ++ NFTA_SET_FIELD_LEN, ++ __NFTA_SET_FIELD_MAX ++}; ++#define NFTA_SET_FIELD_MAX (__NFTA_SET_FIELD_MAX - 1) ++ ++/** + * enum nft_set_attributes - nf_tables set netlink attributes + * + * @NFTA_SET_TABLE: table name (NLA_STRING) +@@ -368,6 +383,7 @@ enum nft_set_elem_flags { + * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) + * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) + * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING) ++ * @NFTA_SET_ELEM_KEY_END: closing key value (NLA_NESTED: nft_data) + */ + enum nft_set_elem_attributes { + NFTA_SET_ELEM_UNSPEC, +@@ -380,6 +396,7 @@ enum nft_set_elem_attributes { + NFTA_SET_ELEM_EXPR, + NFTA_SET_ELEM_PAD, + NFTA_SET_ELEM_OBJREF, ++ NFTA_SET_ELEM_KEY_END, + __NFTA_SET_ELEM_MAX + }; + #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) +-- +1.8.3.1 + diff --git a/SOURCES/0020-src-Add-support-for-NFTNL_SET_DESC_CONCAT.patch b/SOURCES/0020-src-Add-support-for-NFTNL_SET_DESC_CONCAT.patch new file mode 100644 index 0000000..663f661 --- /dev/null +++ b/SOURCES/0020-src-Add-support-for-NFTNL_SET_DESC_CONCAT.patch @@ -0,0 +1,181 @@ +From c8a5da2f527c85ab7c392cd293ff37d02a3f93a7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Feb 2020 17:48:18 +0100 +Subject: [PATCH] src: Add support for NFTNL_SET_DESC_CONCAT + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795224 +Upstream Status: nftables commit 6156ba34018dd +Conflicts: Context change in src/mnl.c due to missing commit + 6e48df5329eab ("src: add "typeof" build/parse/print support") + +commit 6156ba34018dddd59cb6737cfd5a69a0cbc5eaa4 +Author: Stefano Brivio +Date: Thu Jan 30 01:16:56 2020 +0100 + + src: Add support for NFTNL_SET_DESC_CONCAT + + To support arbitrary range concatenations, the kernel needs to know + how long each field in the concatenation is. The new libnftnl + NFTNL_SET_DESC_CONCAT set attribute describes this as an array of + lengths, in bytes, of concatenated fields. + + While evaluating concatenated expressions, export the datatype size + into the new field_len array, and hand the data over via libnftnl. + + Similarly, when data is passed back from libnftnl, parse it into + the set description. + + When set data is cloned, we now need to copy the additional fields + in set_clone(), too. + + This change depends on the libnftnl patch with title: + set: Add support for NFTA_SET_DESC_CONCAT attributes + + v4: No changes + v3: Rework to use set description data instead of a stand-alone + attribute + v2: No changes + + Signed-off-by: Stefano Brivio + Signed-off-by: Pablo Neira Ayuso +--- + include/expression.h | 2 ++ + include/rule.h | 6 +++++- + src/evaluate.c | 14 +++++++++++--- + src/mnl.c | 7 +++++++ + src/netlink.c | 11 +++++++++++ + src/rule.c | 2 +- + 6 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/include/expression.h b/include/expression.h +index 717b675..ee726aa 100644 +--- a/include/expression.h ++++ b/include/expression.h +@@ -256,6 +256,8 @@ struct expr { + struct list_head expressions; + unsigned int size; + uint32_t set_flags; ++ uint8_t field_len[NFT_REG32_COUNT]; ++ uint8_t field_count; + }; + struct { + /* EXPR_SET_REF */ +diff --git a/include/rule.h b/include/rule.h +index 47eb29f..c03b0b8 100644 +--- a/include/rule.h ++++ b/include/rule.h +@@ -290,7 +290,9 @@ extern struct rule *rule_lookup_by_index(const struct chain *chain, + * @rg_cache: cached range element (left) + * @policy: set mechanism policy + * @automerge: merge adjacents and overlapping elements, if possible +- * @desc: set mechanism desc ++ * @desc.size: count of set elements ++ * @desc.field_len: length of single concatenated fields, bytes ++ * @desc.field_count: count of concatenated fields + */ + struct set { + struct list_head list; +@@ -310,6 +312,8 @@ struct set { + bool automerge; + struct { + uint32_t size; ++ uint8_t field_len[NFT_REG32_COUNT]; ++ uint8_t field_count; + } desc; + }; + +diff --git a/src/evaluate.c b/src/evaluate.c +index a865902..58f458d 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -1216,6 +1216,8 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr, + struct expr *i, *next; + + list_for_each_entry_safe(i, next, &(*expr)->expressions, list) { ++ unsigned dsize_bytes; ++ + if (expr_is_constant(*expr) && dtype && off == 0) + return expr_binary_error(ctx->msgs, i, *expr, + "unexpected concat component, " +@@ -1240,6 +1242,9 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr, + i->dtype->name); + + ntype = concat_subtype_add(ntype, i->dtype->type); ++ ++ dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE); ++ (*expr)->field_len[(*expr)->field_count++] = dsize_bytes; + } + + (*expr)->flags |= flags; +@@ -3321,9 +3326,12 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) + "specified in %s definition", + set->key->dtype->name, type); + } +- if (set->flags & NFT_SET_INTERVAL && +- set->key->etype == EXPR_CONCAT) +- return set_error(ctx, set, "concatenated types not supported in interval sets"); ++ ++ if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) { ++ memcpy(&set->desc.field_len, &set->key->field_len, ++ sizeof(set->desc.field_len)); ++ set->desc.field_count = set->key->field_count; ++ } + + if (set_is_datamap(set->flags)) { + if (set->datatype == NULL) +diff --git a/src/mnl.c b/src/mnl.c +index aa5b0b4..221ee05 100644 +--- a/src/mnl.c ++++ b/src/mnl.c +@@ -881,6 +881,13 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd, + set->automerge)) + memory_allocation_error(); + ++ if (set->desc.field_len[0]) { ++ nftnl_set_set_data(nls, NFTNL_SET_DESC_CONCAT, ++ set->desc.field_len, ++ set->desc.field_count * ++ sizeof(set->desc.field_len[0])); ++ } ++ + nftnl_set_set_data(nls, NFTNL_SET_USERDATA, nftnl_udata_buf_data(udbuf), + nftnl_udata_buf_len(udbuf)); + nftnl_udata_buf_free(udbuf); +diff --git a/src/netlink.c b/src/netlink.c +index 486e124..83d863c 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -672,6 +672,17 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx, + if (nftnl_set_is_set(nls, NFTNL_SET_DESC_SIZE)) + set->desc.size = nftnl_set_get_u32(nls, NFTNL_SET_DESC_SIZE); + ++ if (nftnl_set_is_set(nls, NFTNL_SET_DESC_CONCAT)) { ++ uint32_t len = NFT_REG32_COUNT; ++ const uint8_t *data; ++ ++ data = nftnl_set_get_data(nls, NFTNL_SET_DESC_CONCAT, &len); ++ if (data) { ++ memcpy(set->desc.field_len, data, len); ++ set->desc.field_count = len; ++ } ++ } ++ + return set; + } + +diff --git a/src/rule.c b/src/rule.c +index 3ca1805..4669577 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -337,7 +337,7 @@ struct set *set_clone(const struct set *set) + new_set->objtype = set->objtype; + new_set->policy = set->policy; + new_set->automerge = set->automerge; +- new_set->desc.size = set->desc.size; ++ new_set->desc = set->desc; + + return new_set; + } +-- +1.8.3.1 + diff --git a/SOURCES/0021-src-Add-support-for-concatenated-set-ranges.patch b/SOURCES/0021-src-Add-support-for-concatenated-set-ranges.patch new file mode 100644 index 0000000..00f8f9e --- /dev/null +++ b/SOURCES/0021-src-Add-support-for-concatenated-set-ranges.patch @@ -0,0 +1,577 @@ +From 7b1f98e90a32865faca9a97f4348f20c753cd2f3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 14 Feb 2020 14:51:33 +0100 +Subject: [PATCH] src: Add support for concatenated set ranges + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795224 +Upstream Status: nftables commit 8ac2f3b2fca38 + +commit 8ac2f3b2fca38b6533043b0678730c10ba4dc5ef +Author: Stefano Brivio +Date: Thu Jan 30 01:16:57 2020 +0100 + + src: Add support for concatenated set ranges + + After exporting field lengths via NFTNL_SET_DESC_CONCAT attributes, + we now need to adjust parsing of user input and generation of + netlink key data to complete support for concatenation of set + ranges. + + Instead of using separate elements for start and end of a range, + denoting the end element by the NFT_SET_ELEM_INTERVAL_END flag, + as it's currently done for ranges without concatenation, we'll use + the new attribute NFTNL_SET_ELEM_KEY_END as suggested by Pablo. It + behaves in the same way as NFTNL_SET_ELEM_KEY, but it indicates + that the included key represents the upper bound of a range. + + For example, "packets with an IPv4 address between 192.0.2.0 and + 192.0.2.42, with destination port between 22 and 25", needs to be + expressed as a single element with two keys: + + NFTA_SET_ELEM_KEY: 192.0.2.0 . 22 + NFTA_SET_ELEM_KEY_END: 192.0.2.42 . 25 + + To achieve this, we need to: + + - adjust the lexer rules to allow multiton expressions as elements + of a concatenation. As wildcards are not allowed (semantics would + be ambiguous), exclude wildcards expressions from the set of + possible multiton expressions, and allow them directly where + needed. Concatenations now admit prefixes and ranges + + - generate, for each element in a range concatenation, a second key + attribute, that includes the upper bound for the range + + - also expand prefixes and non-ranged values in the concatenation + to ranges: given a set with interval and concatenation support, + the kernel has no way to tell which elements are ranged, so they + all need to be. For example, 192.0.2.0 . 192.0.2.9 : 1024 is + sent as: + + NFTA_SET_ELEM_KEY: 192.0.2.0 . 1024 + NFTA_SET_ELEM_KEY_END: 192.0.2.9 . 1024 + + - aggregate ranges when elements received by the kernel represent + concatenated ranges, see concat_range_aggregate() + + - perform a few minor adjustments where interval expressions + are already handled: we have intervals in these sets, but + the set specification isn't just an interval, so we can't + just aggregate and deaggregate interval ranges linearly + + v4: No changes + v3: + - rework to use a separate key for closing element of range instead of + a separate element with EXPR_F_INTERVAL_END set (Pablo Neira Ayuso) + v2: + - reworked netlink_gen_concat_data(), moved loop body to a new function, + netlink_gen_concat_data_expr() (Phil Sutter) + - dropped repeated pattern in bison file, replaced by a new helper, + compound_expr_alloc_or_add() (Phil Sutter) + - added set_is_nonconcat_range() helper (Phil Sutter) + - in expr_evaluate_set(), we need to set NFT_SET_SUBKEY also on empty + sets where the set in the context already has the flag + - dropped additional 'end' parameter from netlink_gen_data(), + temporarily set EXPR_F_INTERVAL_END on expressions and use that from + netlink_gen_concat_data() to figure out we need to add the 'end' + element (Phil Sutter) + - replace range_mask_len() by a simplified version, as we don't need + to actually store the composing masks of a range (Phil Sutter) + + Signed-off-by: Stefano Brivio + Signed-off-by: Pablo Neira Ayuso +--- + include/expression.h | 1 + + include/rule.h | 5 +++ + src/evaluate.c | 5 +++ + src/netlink.c | 109 +++++++++++++++++++++++++++++++++++------------ + src/parser_bison.y | 17 ++++++-- + src/rule.c | 13 +++--- + src/segtree.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 7 files changed, 229 insertions(+), 38 deletions(-) + +diff --git a/include/expression.h b/include/expression.h +index ee726aa..2e41aa0 100644 +--- a/include/expression.h ++++ b/include/expression.h +@@ -460,6 +460,7 @@ extern int set_to_intervals(struct list_head *msgs, struct set *set, + struct expr *init, bool add, + unsigned int debug_mask, bool merge, + struct output_ctx *octx); ++extern void concat_range_aggregate(struct expr *set); + extern void interval_map_decompose(struct expr *set); + + extern struct expr *get_set_intervals(const struct set *set, +diff --git a/include/rule.h b/include/rule.h +index c03b0b8..626973e 100644 +--- a/include/rule.h ++++ b/include/rule.h +@@ -372,6 +372,11 @@ static inline bool set_is_interval(uint32_t set_flags) + return set_flags & NFT_SET_INTERVAL; + } + ++static inline bool set_is_non_concat_range(struct set *s) ++{ ++ return (s->flags & NFT_SET_INTERVAL) && s->desc.field_count <= 1; ++} ++ + #include + + struct counter { +diff --git a/src/evaluate.c b/src/evaluate.c +index 58f458d..0c84816 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -136,6 +136,11 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr, + + if ((*expr)->byteorder == byteorder) + return 0; ++ ++ /* Conversion for EXPR_CONCAT is handled for single composing ranges */ ++ if ((*expr)->etype == EXPR_CONCAT) ++ return 0; ++ + if (expr_basetype(*expr)->type != TYPE_INTEGER) + return expr_error(ctx->msgs, *expr, + "Byteorder mismatch: expected %s, got %s", +diff --git a/src/netlink.c b/src/netlink.c +index 83d863c..e0ba903 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -98,10 +98,11 @@ struct nftnl_expr *alloc_nft_expr(const char *name) + static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, + const struct expr *expr) + { +- const struct expr *elem, *key, *data; ++ const struct expr *elem, *data; + struct nftnl_set_elem *nlse; + struct nft_data_linearize nld; + struct nftnl_udata_buf *udbuf = NULL; ++ struct expr *key; + + nlse = nftnl_set_elem_alloc(); + if (nlse == NULL) +@@ -119,6 +120,16 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, + + netlink_gen_data(key, &nld); + nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len); ++ ++ if (set->set_flags & NFT_SET_INTERVAL && expr->key->field_count > 1) { ++ key->flags |= EXPR_F_INTERVAL_END; ++ netlink_gen_data(key, &nld); ++ key->flags &= ~EXPR_F_INTERVAL_END; ++ ++ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END, &nld.value, ++ nld.len); ++ } ++ + if (elem->timeout) + nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_TIMEOUT, + elem->timeout); +@@ -186,28 +197,58 @@ void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder, + data->len = len; + } + ++static int netlink_export_pad(unsigned char *data, const mpz_t v, ++ const struct expr *i) ++{ ++ mpz_export_data(data, v, i->byteorder, ++ div_round_up(i->len, BITS_PER_BYTE)); ++ ++ return netlink_padded_len(i->len) / BITS_PER_BYTE; ++} ++ ++static int netlink_gen_concat_data_expr(int end, const struct expr *i, ++ unsigned char *data) ++{ ++ switch (i->etype) { ++ case EXPR_RANGE: ++ i = end ? i->right : i->left; ++ break; ++ case EXPR_PREFIX: ++ if (end) { ++ int count; ++ mpz_t v; ++ ++ mpz_init_bitmask(v, i->len - i->prefix_len); ++ mpz_add(v, i->prefix->value, v); ++ count = netlink_export_pad(data, v, i); ++ mpz_clear(v); ++ return count; ++ } ++ return netlink_export_pad(data, i->prefix->value, i); ++ case EXPR_VALUE: ++ break; ++ default: ++ BUG("invalid expression type '%s' in set", expr_ops(i)->name); ++ } ++ ++ return netlink_export_pad(data, i->value, i); ++} ++ + static void netlink_gen_concat_data(const struct expr *expr, + struct nft_data_linearize *nld) + { ++ unsigned int len = expr->len / BITS_PER_BYTE, offset = 0; ++ int end = expr->flags & EXPR_F_INTERVAL_END; ++ unsigned char data[len]; + const struct expr *i; +- unsigned int len, offset; +- +- len = expr->len / BITS_PER_BYTE; +- if (1) { +- unsigned char data[len]; +- +- memset(data, 0, sizeof(data)); +- offset = 0; +- list_for_each_entry(i, &expr->expressions, list) { +- assert(i->etype == EXPR_VALUE); +- mpz_export_data(data + offset, i->value, i->byteorder, +- div_round_up(i->len, BITS_PER_BYTE)); +- offset += netlink_padded_len(i->len) / BITS_PER_BYTE; +- } + +- memcpy(nld->value, data, len); +- nld->len = len; +- } ++ memset(data, 0, len); ++ ++ list_for_each_entry(i, &expr->expressions, list) ++ offset += netlink_gen_concat_data_expr(end, i, data + offset); ++ ++ memcpy(nld->value, data, len); ++ nld->len = len; + } + + static void netlink_gen_constant_data(const struct expr *expr, +@@ -812,6 +853,7 @@ int netlink_delinearize_setelem(struct nftnl_set_elem *nlse, + if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_FLAGS)) + flags = nftnl_set_elem_get_u32(nlse, NFTNL_SET_ELEM_FLAGS); + ++key_end: + key = netlink_alloc_value(&netlink_location, &nld); + datatype_set(key, set->key->dtype); + key->byteorder = set->key->byteorder; +@@ -880,6 +922,15 @@ int netlink_delinearize_setelem(struct nftnl_set_elem *nlse, + } + out: + compound_expr_add(set->init, expr); ++ ++ if (!(flags & NFT_SET_ELEM_INTERVAL_END) && ++ nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_KEY_END)) { ++ flags |= NFT_SET_ELEM_INTERVAL_END; ++ nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_KEY_END, ++ &nld.len); ++ goto key_end; ++ } ++ + return 0; + } + +@@ -918,15 +969,16 @@ int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h, + set->init = set_expr_alloc(&internal_location, set); + nftnl_set_elem_foreach(nls, list_setelem_cb, ctx); + +- if (!(set->flags & NFT_SET_INTERVAL)) ++ if (set->flags & NFT_SET_INTERVAL && set->desc.field_count > 1) ++ concat_range_aggregate(set->init); ++ else if (set->flags & NFT_SET_INTERVAL) ++ interval_map_decompose(set->init); ++ else + list_expr_sort(&ctx->set->init->expressions); + + nftnl_set_free(nls); + ctx->set = NULL; + +- if (set->flags & NFT_SET_INTERVAL) +- interval_map_decompose(set->init); +- + return 0; + } + +@@ -935,6 +987,7 @@ int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h, + struct set *set, struct expr *init) + { + struct nftnl_set *nls, *nls_out = NULL; ++ int err = 0; + + nls = nftnl_set_alloc(); + if (nls == NULL) +@@ -958,18 +1011,18 @@ int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h, + set->init = set_expr_alloc(loc, set); + nftnl_set_elem_foreach(nls_out, list_setelem_cb, ctx); + +- if (!(set->flags & NFT_SET_INTERVAL)) ++ if (set->flags & NFT_SET_INTERVAL && set->desc.field_count > 1) ++ concat_range_aggregate(set->init); ++ else if (set->flags & NFT_SET_INTERVAL) ++ err = get_set_decompose(table, set); ++ else + list_expr_sort(&ctx->set->init->expressions); + + nftnl_set_free(nls); + nftnl_set_free(nls_out); + ctx->set = NULL; + +- if (set->flags & NFT_SET_INTERVAL && +- get_set_decompose(table, set) < 0) +- return -1; +- +- return 0; ++ return err; + } + + void netlink_dump_obj(struct nftnl_obj *nln, struct netlink_ctx *ctx) +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 0fd9b94..ea83f52 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -3551,7 +3551,6 @@ range_rhs_expr : basic_rhs_expr DASH basic_rhs_expr + + multiton_rhs_expr : prefix_rhs_expr + | range_rhs_expr +- | wildcard_expr + ; + + map_expr : concat_expr MAP rhs_expr +@@ -3645,7 +3644,7 @@ set_elem_option : TIMEOUT time_spec + ; + + set_lhs_expr : concat_rhs_expr +- | multiton_rhs_expr ++ | wildcard_expr + ; + + set_rhs_expr : concat_rhs_expr +@@ -3898,7 +3897,7 @@ list_rhs_expr : basic_rhs_expr COMMA basic_rhs_expr + ; + + rhs_expr : concat_rhs_expr { $$ = $1; } +- | multiton_rhs_expr { $$ = $1; } ++ | wildcard_expr { $$ = $1; } + | set_expr { $$ = $1; } + | set_ref_symbol_expr { $$ = $1; } + ; +@@ -3939,7 +3938,17 @@ basic_rhs_expr : inclusive_or_rhs_expr + ; + + concat_rhs_expr : basic_rhs_expr +- | concat_rhs_expr DOT basic_rhs_expr ++ | multiton_rhs_expr ++ | concat_rhs_expr DOT multiton_rhs_expr ++ { ++ struct location rhs[] = { ++ [1] = @2, ++ [2] = @3, ++ }; ++ ++ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs); ++ } ++ | concat_rhs_expr DOT basic_rhs_expr + { + struct location rhs[] = { + [1] = @2, +diff --git a/src/rule.c b/src/rule.c +index 4669577..e18237b 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -1512,7 +1512,8 @@ static int __do_add_setelems(struct netlink_ctx *ctx, struct set *set, + return -1; + + if (set->init != NULL && +- set->flags & NFT_SET_INTERVAL) { ++ set->flags & NFT_SET_INTERVAL && ++ set->desc.field_count <= 1) { + interval_map_decompose(expr); + list_splice_tail_init(&expr->expressions, &set->init->expressions); + set->init->size += expr->size; +@@ -1533,7 +1534,7 @@ static int do_add_setelems(struct netlink_ctx *ctx, struct cmd *cmd, + table = table_lookup(h, &ctx->nft->cache); + set = set_lookup(table, h->set.name); + +- if (set->flags & NFT_SET_INTERVAL && ++ if (set_is_non_concat_range(set) && + set_to_intervals(ctx->msgs, set, init, true, + ctx->nft->debug_mask, set->automerge, + &ctx->nft->output) < 0) +@@ -1548,7 +1549,7 @@ static int do_add_set(struct netlink_ctx *ctx, const struct cmd *cmd, + struct set *set = cmd->set; + + if (set->init != NULL) { +- if (set->flags & NFT_SET_INTERVAL && ++ if (set_is_non_concat_range(set) && + set_to_intervals(ctx->msgs, set, set->init, true, + ctx->nft->debug_mask, set->automerge, + &ctx->nft->output) < 0) +@@ -1634,7 +1635,7 @@ static int do_delete_setelems(struct netlink_ctx *ctx, struct cmd *cmd) + table = table_lookup(h, &ctx->nft->cache); + set = set_lookup(table, h->set.name); + +- if (set->flags & NFT_SET_INTERVAL && ++ if (set_is_non_concat_range(set) && + set_to_intervals(ctx->msgs, set, expr, false, + ctx->nft->debug_mask, set->automerge, + &ctx->nft->output) < 0) +@@ -2488,7 +2489,7 @@ static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd, + set = set_lookup(table, cmd->handle.set.name); + + /* Create a list of elements based of what we got from command line. */ +- if (set->flags & NFT_SET_INTERVAL) ++ if (set_is_non_concat_range(set)) + init = get_set_intervals(set, cmd->expr); + else + init = cmd->expr; +@@ -2501,7 +2502,7 @@ static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd, + if (err >= 0) + __do_list_set(ctx, cmd, table, new_set); + +- if (set->flags & NFT_SET_INTERVAL) ++ if (set_is_non_concat_range(set)) + expr_free(init); + + set_free(new_set); +diff --git a/src/segtree.c b/src/segtree.c +index 7217dbc..e859f84 100644 +--- a/src/segtree.c ++++ b/src/segtree.c +@@ -652,6 +652,11 @@ struct expr *get_set_intervals(const struct set *set, const struct expr *init) + set_elem_add(set, new_init, i->key->value, + i->flags, i->byteorder); + break; ++ case EXPR_CONCAT: ++ compound_expr_add(new_init, expr_clone(i)); ++ i->flags |= EXPR_F_INTERVAL_END; ++ compound_expr_add(new_init, expr_clone(i)); ++ break; + default: + range_expr_value_low(low, i); + set_elem_add(set, new_init, low, 0, i->byteorder); +@@ -823,6 +828,9 @@ static int expr_value_cmp(const void *p1, const void *p2) + struct expr *e2 = *(void * const *)p2; + int ret; + ++ if (expr_value(e1)->etype == EXPR_CONCAT) ++ return -1; ++ + ret = mpz_cmp(expr_value(e1)->value, expr_value(e2)->value); + if (ret == 0) { + if (e1->flags & EXPR_F_INTERVAL_END) +@@ -834,6 +842,115 @@ static int expr_value_cmp(const void *p1, const void *p2) + return ret; + } + ++/* Given start and end elements of a range, check if it can be represented as ++ * a single netmask, and if so, how long, by returning zero or a positive value. ++ */ ++static int range_mask_len(const mpz_t start, const mpz_t end, unsigned int len) ++{ ++ mpz_t tmp_start, tmp_end; ++ int ret; ++ ++ mpz_init_set_ui(tmp_start, mpz_get_ui(start)); ++ mpz_init_set_ui(tmp_end, mpz_get_ui(end)); ++ ++ while (mpz_cmp(tmp_start, tmp_end) <= 0 && ++ !mpz_tstbit(tmp_start, 0) && mpz_tstbit(tmp_end, 0) && ++ len--) { ++ mpz_fdiv_q_2exp(tmp_start, tmp_start, 1); ++ mpz_fdiv_q_2exp(tmp_end, tmp_end, 1); ++ } ++ ++ ret = !mpz_cmp(tmp_start, tmp_end) ? (int)len : -1; ++ ++ mpz_clear(tmp_start); ++ mpz_clear(tmp_end); ++ ++ return ret; ++} ++ ++/* Given a set with two elements (start and end), transform them into a ++ * concatenation of ranges. That is, from a list of start expressions and a list ++ * of end expressions, form a list of start - end expressions. ++ */ ++void concat_range_aggregate(struct expr *set) ++{ ++ struct expr *i, *start = NULL, *end, *r1, *r2, *next, *r1_next, *tmp; ++ struct list_head *r2_next; ++ int prefix_len, free_r1; ++ mpz_t range, p; ++ ++ list_for_each_entry_safe(i, next, &set->expressions, list) { ++ if (!start) { ++ start = i; ++ continue; ++ } ++ end = i; ++ ++ /* Walk over r1 (start expression) and r2 (end) in parallel, ++ * form ranges between corresponding r1 and r2 expressions, ++ * store them by replacing r2 expressions, and free r1 ++ * expressions. ++ */ ++ r2 = list_first_entry(&expr_value(end)->expressions, ++ struct expr, list); ++ list_for_each_entry_safe(r1, r1_next, ++ &expr_value(start)->expressions, ++ list) { ++ mpz_init(range); ++ mpz_init(p); ++ ++ r2_next = r2->list.next; ++ free_r1 = 0; ++ ++ if (!mpz_cmp(r1->value, r2->value)) { ++ free_r1 = 1; ++ goto next; ++ } ++ ++ mpz_sub(range, r2->value, r1->value); ++ mpz_sub_ui(range, range, 1); ++ mpz_and(p, r1->value, range); ++ ++ /* Check if we are forced, or if it's anyway preferable, ++ * to express the range as two points instead of a ++ * netmask. ++ */ ++ prefix_len = range_mask_len(r1->value, r2->value, ++ r1->len); ++ if (prefix_len < 0 || ++ !(r1->dtype->flags & DTYPE_F_PREFIX)) { ++ tmp = range_expr_alloc(&r1->location, r1, ++ r2); ++ ++ list_replace(&r2->list, &tmp->list); ++ r2_next = tmp->list.next; ++ } else { ++ tmp = prefix_expr_alloc(&r1->location, r1, ++ prefix_len); ++ tmp->len = r2->len; ++ ++ list_replace(&r2->list, &tmp->list); ++ r2_next = tmp->list.next; ++ expr_free(r2); ++ } ++ ++next: ++ mpz_clear(p); ++ mpz_clear(range); ++ ++ r2 = list_entry(r2_next, typeof(*r2), list); ++ compound_expr_remove(start, r1); ++ ++ if (free_r1) ++ expr_free(r1); ++ } ++ ++ compound_expr_remove(set, start); ++ expr_free(start); ++ start = NULL; ++ } ++} ++ + void interval_map_decompose(struct expr *set) + { + struct expr **elements, **ranges; +-- +1.8.3.1 + diff --git a/SOURCES/0022-parser_json-Support-ranges-in-concat-expressions.patch b/SOURCES/0022-parser_json-Support-ranges-in-concat-expressions.patch new file mode 100644 index 0000000..5ee20ac --- /dev/null +++ b/SOURCES/0022-parser_json-Support-ranges-in-concat-expressions.patch @@ -0,0 +1,119 @@ +From 68392da523f43b9ae09f824fa68b04b20c9c88f5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 20 May 2020 11:12:37 +0200 +Subject: [PATCH] parser_json: Support ranges in concat expressions + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1805798 +Upstream Status: nftables commit 9475ca305a993 + +commit 9475ca305a993751b05cf26ef8e785a00de98b94 +Author: Phil Sutter +Date: Fri Mar 6 16:15:48 2020 +0100 + + parser_json: Support ranges in concat expressions + + Duplicate commit 8ac2f3b2fca38's changes to bison parser into JSON + parser by introducing a new context flag signalling we're parsing + concatenated expressions. + + Fixes: 8ac2f3b2fca38 ("src: Add support for concatenated set ranges") + Signed-off-by: Phil Sutter + Acked-by: Eric Garver +--- + src/parser_json.c | 51 +++++++++++++++++++++++++++++---------------------- + 1 file changed, 29 insertions(+), 22 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index 031930e..c48faa8 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -40,6 +40,7 @@ + #define CTX_F_MANGLE (1 << 5) + #define CTX_F_SES (1 << 6) /* set_elem_expr_stmt */ + #define CTX_F_MAP (1 << 7) /* LHS of map_expr */ ++#define CTX_F_CONCAT (1 << 8) /* inside concat_expr */ + + struct json_ctx { + struct input_descriptor indesc; +@@ -99,6 +100,7 @@ static struct expr *json_parse_primary_expr(struct json_ctx *ctx, json_t *root); + static struct expr *json_parse_set_rhs_expr(struct json_ctx *ctx, json_t *root); + static struct expr *json_parse_set_elem_expr_stmt(struct json_ctx *ctx, json_t *root); + static struct expr *json_parse_map_lhs_expr(struct json_ctx *ctx, json_t *root); ++static struct expr *json_parse_concat_elem_expr(struct json_ctx *ctx, json_t *root); + static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root); + + /* parsing helpers */ +@@ -1058,7 +1060,7 @@ static struct expr *json_parse_concat_expr(struct json_ctx *ctx, + } + + json_array_foreach(root, index, value) { +- tmp = json_parse_primary_expr(ctx, value); ++ tmp = json_parse_concat_elem_expr(ctx, value); + if (!tmp) { + json_error(ctx, "Parsing expr at index %zd failed.", index); + expr_free(expr); +@@ -1354,28 +1356,28 @@ static struct expr *json_parse_expr(struct json_ctx *ctx, json_t *root) + { "set", json_parse_set_expr, CTX_F_RHS | CTX_F_STMT }, /* allow this as stmt expr because that allows set references */ + { "map", json_parse_map_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS }, + /* below three are multiton_rhs_expr */ +- { "prefix", json_parse_prefix_expr, CTX_F_RHS | CTX_F_STMT }, +- { "range", json_parse_range_expr, CTX_F_RHS | CTX_F_STMT }, +- { "payload", json_parse_payload_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP }, +- { "exthdr", json_parse_exthdr_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "tcp option", json_parse_tcp_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES }, +- { "ip option", json_parse_ip_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES }, +- { "meta", json_parse_meta_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP }, +- { "osf", json_parse_osf_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_MAP }, +- { "ipsec", json_parse_xfrm_expr, CTX_F_PRIMARY | CTX_F_MAP }, +- { "socket", json_parse_socket_expr, CTX_F_PRIMARY }, +- { "rt", json_parse_rt_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "ct", json_parse_ct_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP }, +- { "numgen", json_parse_numgen_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, ++ { "prefix", json_parse_prefix_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_CONCAT }, ++ { "range", json_parse_range_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_CONCAT }, ++ { "payload", json_parse_payload_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "exthdr", json_parse_exthdr_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "tcp option", json_parse_tcp_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT }, ++ { "ip option", json_parse_ip_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT }, ++ { "meta", json_parse_meta_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "osf", json_parse_osf_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_MAP | CTX_F_CONCAT }, ++ { "ipsec", json_parse_xfrm_expr, CTX_F_PRIMARY | CTX_F_MAP | CTX_F_CONCAT }, ++ { "socket", json_parse_socket_expr, CTX_F_PRIMARY | CTX_F_CONCAT }, ++ { "rt", json_parse_rt_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "ct", json_parse_ct_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "numgen", json_parse_numgen_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, + /* below two are hash expr */ +- { "jhash", json_parse_hash_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "symhash", json_parse_hash_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "fib", json_parse_fib_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "|", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "^", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "&", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { ">>", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, +- { "<<", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP }, ++ { "jhash", json_parse_hash_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "symhash", json_parse_hash_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "fib", json_parse_fib_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "|", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "^", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "&", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { ">>", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, ++ { "<<", json_parse_binop_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT }, + { "accept", json_parse_verdict_expr, CTX_F_RHS | CTX_F_SET_RHS }, + { "drop", json_parse_verdict_expr, CTX_F_RHS | CTX_F_SET_RHS }, + { "continue", json_parse_verdict_expr, CTX_F_RHS | CTX_F_SET_RHS }, +@@ -1500,6 +1502,11 @@ static struct expr *json_parse_map_lhs_expr(struct json_ctx *ctx, json_t *root) + return json_parse_flagged_expr(ctx, CTX_F_MAP, root); + } + ++static struct expr *json_parse_concat_elem_expr(struct json_ctx *ctx, json_t *root) ++{ ++ return json_parse_flagged_expr(ctx, CTX_F_CONCAT, root); ++} ++ + static struct expr *json_parse_dtype_expr(struct json_ctx *ctx, json_t *root) + { + if (json_is_string(root)) { +-- +1.8.3.1 + diff --git a/SOURCES/0023-doc-Document-notrack-statement.patch b/SOURCES/0023-doc-Document-notrack-statement.patch new file mode 100644 index 0000000..4c31fc5 --- /dev/null +++ b/SOURCES/0023-doc-Document-notrack-statement.patch @@ -0,0 +1,51 @@ +From f7a31d5c3277b29f104fd8ff48df24c8bc790f19 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Jun 2020 18:46:39 +0200 +Subject: [PATCH] doc: Document notrack statement + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1841292 +Upstream Status: nftables commit f16fbe76f62dc + +commit f16fbe76f62dcb9f7395d1837ad2d056463ba55f +Author: Phil Sutter +Date: Mon Jun 22 15:07:40 2020 +0200 + + doc: Document notrack statement + + Merely a stub, but better to mention it explicitly instead of having it + appear in synproxy examples and letting users guess as to what it does. + + Signed-off-by: Phil Sutter + Reviewed-by: Florian Westphal +--- + doc/statements.txt | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/doc/statements.txt b/doc/statements.txt +index 3b82436..749533a 100644 +--- a/doc/statements.txt ++++ b/doc/statements.txt +@@ -262,6 +262,20 @@ table inet raw { + ct event set new,related,destroy + -------------------------------------- + ++NOTRACK STATEMENT ++~~~~~~~~~~~~~~~~~ ++The notrack statement allows to disable connection tracking for certain ++packets. ++ ++[verse] ++*notrack* ++ ++Note that for this statement to be effective, it has to be applied to packets ++before a conntrack lookup happens. Therefore, it needs to sit in a chain with ++either prerouting or output hook and a hook priority of -300 or less. ++ ++See SYNPROXY STATEMENT for an example usage. ++ + META STATEMENT + ~~~~~~~~~~~~~~ + A meta statement sets the value of a meta expression. The existing meta fields +-- +1.8.3.1 + diff --git a/SOURCES/0024-JSON-Improve-performance-of-json_events_cb.patch b/SOURCES/0024-JSON-Improve-performance-of-json_events_cb.patch new file mode 100644 index 0000000..f7ed167 --- /dev/null +++ b/SOURCES/0024-JSON-Improve-performance-of-json_events_cb.patch @@ -0,0 +1,53 @@ +From 58d8baa70172bb9862276ac5f542248c88d3faf4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Jun 2020 18:48:14 +0200 +Subject: [PATCH] JSON: Improve performance of json_events_cb() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1835300 +Upstream Status: nftables commit c96c7da272e33 + +commit c96c7da272e33a34770c4de4e3e50f7ed264672e +Author: Phil Sutter +Date: Wed May 13 16:29:51 2020 +0200 + + JSON: Improve performance of json_events_cb() + + The function tries to insert handles into JSON input for echo option. + Yet there may be nothing to do if the given netlink message doesn't + contain a handle, e.g. if it is an 'add element' command. Calling + seqnum_to_json() is pointless overhead in that case, and if input is + large this overhead is significant. Better wait with that call until + after checking if the message is relevant at all. + + Signed-off-by: Phil Sutter + Acked-by: Eric Garver +--- + src/parser_json.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index c48faa8..ce8e566 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -3845,12 +3845,15 @@ static uint64_t handle_from_nlmsg(const struct nlmsghdr *nlh) + } + int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh) + { +- json_t *tmp, *json = seqnum_to_json(nlh->nlmsg_seq); + uint64_t handle = handle_from_nlmsg(nlh); ++ json_t *tmp, *json; + void *iter; + +- /* might be anonymous set, ignore message */ +- if (!json || !handle) ++ if (!handle) ++ return MNL_CB_OK; ++ ++ json = seqnum_to_json(nlh->nlmsg_seq); ++ if (!json) + return MNL_CB_OK; + + tmp = json_object_get(json, "add"); +-- +1.8.3.1 + diff --git a/SOURCES/main.nft b/SOURCES/main.nft new file mode 100644 index 0000000..6460d10 --- /dev/null +++ b/SOURCES/main.nft @@ -0,0 +1,64 @@ +# Sample configuration for nftables service. +# Load this by calling 'nft -f /etc/nftables/main.nft'. + +# Note about base chain priorities: +# The priority values used in these sample configs are +# offset by 20 in order to avoid ambiguity when firewalld +# is also running which uses an offset of 10. This means +# that packets will traverse firewalld first and if not +# dropped/rejected there will hit the chains defined here. +# Chains created by iptables, ebtables and arptables tools +# do not use an offset, so those chains are traversed first +# in any case. + +# drop any existing nftables ruleset +flush ruleset + +# a common table for both IPv4 and IPv6 +table inet nftables_svc { + + # protocols to allow + set allowed_protocols { + type inet_proto + elements = { icmp, icmpv6 } + } + + # interfaces to accept any traffic on + set allowed_interfaces { + type ifname + elements = { "lo" } + } + + # services to allow + set allowed_tcp_dports { + type inet_service + elements = { ssh, 9090 } + } + + # this chain gathers all accept conditions + chain allow { + ct state established,related accept + + meta l4proto @allowed_protocols accept + iifname @allowed_interfaces accept + tcp dport @allowed_tcp_dports accept + } + + # base-chain for traffic to this host + chain INPUT { + type filter hook input priority filter + 20 + policy accept + + jump allow + reject with icmpx type port-unreachable + } +} + +# By default, any forwarding traffic is allowed. +# Uncomment the following line to filter it based +# on the same criteria as input traffic. +#include "/etc/nftables/router.nft" + +# Uncomment the following line to enable masquerading of +# forwarded traffic. May be used with or without router.nft. +#include "/etc/nftables/nat.nft" diff --git a/SOURCES/nat.nft b/SOURCES/nat.nft new file mode 100644 index 0000000..7079893 --- /dev/null +++ b/SOURCES/nat.nft @@ -0,0 +1,30 @@ +# Sample configuration snippet for nftables service. +# Meant to be included by main.nft, not for direct use. + +# dedicated table for IPv4 +table ip nftables_svc { + + # interfaces to masquerade traffic from + set masq_interfaces { + type ifname + elements = { "virbr0" } + } + + # networks to masquerade traffic from + # 'interval' flag is required to support subnets + set masq_ips { + type ipv4_addr + flags interval + elements = { 192.168.122.0/24 } + } + + # base-chain to manipulate conntrack in postrouting, + # will see packets for new or related traffic only + chain POSTROUTING { + type nat hook postrouting priority srcnat + 20 + policy accept + + iifname @masq_interfaces oifname != @masq_interfaces masquerade + ip saddr @masq_ips masquerade + } +} diff --git a/SOURCES/nftables.conf b/SOURCES/nftables.conf index 5f602ac..c3d9649 100644 --- a/SOURCES/nftables.conf +++ b/SOURCES/nftables.conf @@ -1,14 +1,8 @@ -# -# This this will contain your nftables rules and -# is read by the systemd service when restarting -# -# These provide an iptables like set of filters -# (uncomment to include) -# include "/etc/nftables/bridge-filter.nft" -# include "/etc/nftables/inet-filter.nft" -# include "/etc/nftables/ipv4-filter.nft" -# include "/etc/nftables/ipv4-mangle.nft" -# include "/etc/nftables/ipv4-nat.nft" -# include "/etc/nftables/ipv6-filter.nft" -# include "/etc/nftables/ipv6-mangle.nft" -# include "/etc/nftables/ipv6-nat.nft" +# Uncomment the include statement here to load the default config sample +# in /etc/nftables for nftables service. + +#include "/etc/nftables/main.nft" + +# To customize, either edit the samples in /etc/nftables, append further +# commands to the end of this file or overwrite it after first service +# start by calling: 'nft list ruleset >/etc/sysconfig/nftables.conf'. diff --git a/SOURCES/router.nft b/SOURCES/router.nft new file mode 100644 index 0000000..6300a55 --- /dev/null +++ b/SOURCES/router.nft @@ -0,0 +1,16 @@ +# Sample configuration snippet for nftables service. +# Meant to be included by main.nft, not for direct use. + +# a common table for both IPv4 and IPv6 +table inet nftables_svc { + + # base-chain for traffic forwarded by this host + # re-uses 'allow' chain from main.nft + chain FORWARD { + type filter hook forward priority filter + 20 + policy accept + + jump allow + reject with icmpx type host-unreachable + } +} diff --git a/SPECS/nftables.spec b/SPECS/nftables.spec index e804602..4b4d94f 100644 --- a/SPECS/nftables.spec +++ b/SPECS/nftables.spec @@ -1,5 +1,5 @@ %define rpmversion 0.9.3 -%define specrelease 4%{?dist} +%define specrelease 14%{?dist} Name: nftables Version: %{rpmversion} @@ -13,6 +13,34 @@ URL: http://netfilter.org/projects/nftables/ Source0: http://ftp.netfilter.org/pub/nftables/nftables-%{version}.tar.bz2 Source1: nftables.service Source2: nftables.conf +Source3: main.nft +Source4: router.nft +Source5: nat.nft + +Patch1: 0001-main-enforce-options-before-commands.patch +Patch2: 0002-main-restore-debug.patch +Patch3: 0003-monitor-Do-not-decompose-non-anonymous-sets.patch +Patch4: 0004-monitor-Fix-output-for-ranges-in-anonymous-sets.patch +Patch5: 0005-xfrm-spi-is-big-endian.patch +Patch6: 0006-tests-shell-Search-diff-tool-once-and-for-all.patch +Patch7: 0007-cache-Fix-for-doubled-output-after-reset-command.patch +Patch8: 0008-netlink-Fix-leak-in-unterminated-string-deserializer.patch +Patch9: 0009-netlink-Fix-leaks-in-netlink_parse_cmp.patch +Patch10: 0010-netlink-Avoid-potential-NULL-pointer-deref-in-netlin.patch +Patch11: 0011-tests-json_echo-Fix-for-Python3.patch +Patch12: 0012-tests-json_echo-Support-testing-host-binaries.patch +Patch13: 0013-tests-monitor-Support-running-individual-test-cases.patch +Patch14: 0014-tests-monitor-Support-testing-host-s-nft-binary.patch +Patch15: 0015-tests-py-Support-testing-host-binaries.patch +Patch16: 0016-doc-nft.8-Mention-wildcard-interface-matching.patch +Patch17: 0017-scanner-Extend-asteriskstring-definition.patch +Patch18: 0018-parser-add-a-helper-for-concat-expression-handling.patch +Patch19: 0019-include-resync-nf_tables.h-cache-copy.patch +Patch20: 0020-src-Add-support-for-NFTNL_SET_DESC_CONCAT.patch +Patch21: 0021-src-Add-support-for-concatenated-set-ranges.patch +Patch22: 0022-parser_json-Support-ranges-in-concat-expressions.patch +Patch23: 0023-doc-Document-notrack-statement.patch +Patch24: 0024-JSON-Improve-performance-of-json_events_cb.patch BuildRequires: autogen BuildRequires: autoconf @@ -24,14 +52,14 @@ BuildRequires: bison BuildRequires: libmnl-devel BuildRequires: gmp-devel BuildRequires: readline-devel -BuildRequires: pkgconfig(libnftnl) >= 1.1.5-1 +BuildRequires: pkgconfig(libnftnl) >= 1.1.5-3 BuildRequires: systemd BuildRequires: asciidoc BuildRequires: iptables-devel BuildRequires: jansson-devel BuildRequires: python3-devel -Requires: libnftnl >= 1.1.5-1 +Requires: libnftnl >= 1.1.5-3 %description Netfilter Tables userspace utilities. @@ -77,6 +105,10 @@ cp -a %{SOURCE1} $RPM_BUILD_ROOT/%{_unitdir}/ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig cp -a %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/ +rm $RPM_BUILD_ROOT/%{_sysconfdir}/nftables/*.nft +cp %{SOURCE3} %{SOURCE4} %{SOURCE5} \ + $RPM_BUILD_ROOT/%{_sysconfdir}/nftables/ + find $RPM_BUILD_ROOT/%{_sysconfdir} \ \( -type d -exec chmod 0700 {} \; \) , \ \( -type f -exec chmod 0600 {} \; \) @@ -125,6 +157,53 @@ touch -r %{SOURCE2} $RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py %{python3_sitelib}/nftables/ %changelog +* Wed Jun 24 2020 Phil Sutter [0.9.3-14.el8] +- JSON: Improve performance of json_events_cb() (Phil Sutter) [1835300] +- doc: Document notrack statement (Phil Sutter) [1841292] + +* Wed May 27 2020 Phil Sutter [0.9.3-13.el8] +- parser_json: Support ranges in concat expressions (Phil Sutter) [1805798] + +* Thu Mar 26 2020 Phil Sutter [0.9.3-12.el8] +- Restore default config to be empty (Phil Sutter) [1694723] + +* Mon Feb 17 2020 Phil Sutter [0.9.3-11.el8] +- Package requires libnftnl-1.1.5-3 (Phil Sutter) [1795224] +- src: Add support for concatenated set ranges (Phil Sutter) [1795224] +- src: Add support for NFTNL_SET_DESC_CONCAT (Phil Sutter) [1795224] +- include: resync nf_tables.h cache copy (Phil Sutter) [1795224] +- parser: add a helper for concat expression handling (Phil Sutter) [1795224] + +* Wed Feb 12 2020 Phil Sutter [0.9.3-10.el8] +- scanner: Extend asteriskstring definition (Phil Sutter) [1763652] +- doc: nft.8: Mention wildcard interface matching (Phil Sutter) [1763652] +- tests: py: Support testing host binaries (Phil Sutter) [1754047] +- tests: monitor: Support testing host's nft binary (Phil Sutter) [1754047] +- tests: monitor: Support running individual test cases (Phil Sutter) [1754047] +- tests: json_echo: Support testing host binaries (Phil Sutter) [1754047] +- tests: json_echo: Fix for Python3 (Phil Sutter) [1754047] + +* Mon Jan 27 2020 Phil Sutter [0.9.3-9.el8] +- netlink: Avoid potential NULL-pointer deref in netlink_gen_payload_stmt() (Phil Sutter) [1793030] +- netlink: Fix leaks in netlink_parse_cmp() (Phil Sutter) [1793030] +- netlink: Fix leak in unterminated string deserializer (Phil Sutter) [1793030] + +* Fri Jan 17 2020 Phil Sutter [0.9.3-8.el8] +- cache: Fix for doubled output after reset command (Phil Sutter) [1790793] +- tests: shell: Search diff tool once and for all (Phil Sutter) [1790793] +- xfrm: spi is big-endian (Phil Sutter) [1790963] + +* Mon Jan 13 2020 Phil Sutter [0.9.3-7.el8] +- monitor: Fix output for ranges in anonymous sets (Phil Sutter) [1774742] + +* Fri Jan 10 2020 Phil Sutter [0.9.3-6.el8] +- monitor: Do not decompose non-anonymous sets (Phil Sutter) [1774742] +- main: restore --debug (Phil Sutter) [1778883] +- main: enforce options before commands (Phil Sutter) [1778883] + +* Fri Jan 10 2020 Phil Sutter [0.9.3-5.el8] +- Install an improved sample config (Phil Sutter) [1694723] + * Wed Dec 04 2019 Phil Sutter [0.9.3-4.el8] - Explicitly depend on newer libnftl version (Phil Sutter) [1643192]