Import rpm: c8s

This commit is contained in:
James Antill 2023-02-27 14:33:43 -05:00
parent 710da64155
commit ae04e27d85
91 changed files with 15117 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
SOURCES/nftables-0.9.3.tar.bz2
/nftables-0.9.3.tar.bz2

View File

@ -0,0 +1,244 @@
From 5fac849eac7ecfde4ca6f9c9c406ace030f358f2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <pablo@netfilter.org>
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 <pablo@netfilter.org>
---
src/main.c | 46 ++++++++++++++++++-
.../testcases/cache/0001_cache_handling_0 | 2 +-
.../testcases/chains/0016delete_handle_0 | 4 +-
.../testcases/chains/0039negative_priority_0 | 8 ++++
.../testcases/flowtable/0010delete_handle_0 | 2 +-
.../testcases/maps/0008interval_map_delete_0 | 2 +-
tests/shell/testcases/optionals/comments_0 | 2 +-
.../testcases/optionals/comments_handles_0 | 2 +-
.../optionals/delete_object_handles_0 | 4 +-
tests/shell/testcases/optionals/handles_0 | 2 +-
.../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 {
--
2.31.1

View File

@ -0,0 +1,50 @@
From 0c808b1ee29d4a0974f4cc5c0586138730361a41 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <pablo@netfilter.org>
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 <pablo@netfilter.org>
---
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;
--
2.31.1

View File

@ -0,0 +1,68 @@
From 13bd961c3ba83e4189dcffdcf570c5a4391fd5f9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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"}}]}}}
--
2.31.1

View File

@ -0,0 +1,80 @@
From 2e7cb6c2d46d9b8b91ff4b5d6797b7544c23ba44 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 13 Jan 2020 16:58:57 +0100
Subject: [PATCH] monitor: Fix output for ranges in anonymous sets
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1774742
Upstream Status: nftables commit ddbacd70d061e
commit ddbacd70d061eb1b6808f501969809bfb5d03001
Author: Phil Sutter <phil@nwl.cc>
Date: Mon Jan 13 14:53:24 2020 +0100
monitor: Fix output for ranges in anonymous sets
Previous fix for named interval sets was simply wrong: Instead of
limiting decomposing to anonymous interval sets, it effectively disabled
it entirely.
Since code needs to check for both interval and anonymous bits
separately, introduce set_is_interval() helper to keep the code
readable.
Also extend test case to assert ranges in anonymous sets are correctly
printed by echo or monitor modes. Without this fix, range boundaries are
printed as individual set elements.
Fixes: 5d57fa3e99bb9 ("monitor: Do not decompose non-anonymous sets")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/rule.h | 5 +++++
src/monitor.c | 2 +-
tests/monitor/testcases/set-interval.t | 5 +++++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/include/rule.h b/include/rule.h
index 0b2eba3..47eb29f 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -363,6 +363,11 @@ static inline bool set_is_meter(uint32_t set_flags)
return set_is_anonymous(set_flags) && (set_flags & NFT_SET_EVAL);
}
+static inline bool set_is_interval(uint32_t set_flags)
+{
+ return set_flags & NFT_SET_INTERVAL;
+}
+
#include <statement.h>
struct counter {
diff --git a/src/monitor.c b/src/monitor.c
index 0da9858..fb803cf 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -500,7 +500,7 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
static void rule_map_decompose_cb(struct set *s, void *data)
{
- if (s->flags & (NFT_SET_INTERVAL & NFT_SET_ANONYMOUS))
+ if (set_is_interval(s->flags) && set_is_anonymous(s->flags))
interval_map_decompose(s->init);
}
diff --git a/tests/monitor/testcases/set-interval.t b/tests/monitor/testcases/set-interval.t
index 59930c5..1fbcfe2 100644
--- a/tests/monitor/testcases/set-interval.t
+++ b/tests/monitor/testcases/set-interval.t
@@ -18,3 +18,8 @@ J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set"
I add rule ip t c tcp dport @s
O -
J {"add": {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"payload": {"protocol": "tcp", "field": "dport"}}, "right": "@s"}}]}}}
+
+# test anonymous interval sets as well
+I add rule ip t c tcp dport { 20, 30-40 }
+O -
+J {"add": {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"payload": {"protocol": "tcp", "field": "dport"}}, "right": {"set": [20, {"range": [30, 40]}]}}}]}}}
--
2.31.1

View File

@ -0,0 +1,51 @@
From ca4d1604b18abf7189ecfd5e06cb74abc3694076 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <fw@strlen.de>
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 <fw@strlen.de>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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 ]
--
2.31.1

View File

@ -0,0 +1,573 @@
From 8537751e48dfacee11d48ad3f050bdacc930284c Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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 +--
.../shell/testcases/maps/0003map_add_many_elements_0 | 3 +--
.../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 +--
.../testcases/optionals/delete_object_handles_0 | 3 +--
.../testcases/optionals/update_object_handles_0 | 3 +--
.../rule_management/0001addinsertposition_0 | 12 ++++--------
tests/shell/testcases/sets/0028delete_handle_0 | 3 +--
.../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
--
2.31.1

View File

@ -0,0 +1,85 @@
From a44bd9f4b6cf77cb75c5f596908100270893e8d5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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
--
2.31.1

View File

@ -0,0 +1,51 @@
From cc70f19e588a0a33ed86c4a059b56a8f5b0c7a82 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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)
--
2.31.1

View File

@ -0,0 +1,75 @@
From 6ecccc872b9cbed921af10e32d1a628eb6a74c01 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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,
--
2.31.1

View File

@ -0,0 +1,42 @@
From 55c537734f476d04c18f67083642b96bbead6219 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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);
--
2.31.1

View File

@ -0,0 +1,39 @@
From 04d0d2e685063d422ce73b67eb01d4803100d379 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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
--
2.31.1

View File

@ -0,0 +1,68 @@
From 0eb301a3f50fb70cb78d955692f3feea1ad8095e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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
--
2.31.1

View File

@ -0,0 +1,64 @@
From 67f168ebfbeb26a8d7e4f1b9284cc32f13ceff9b Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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:
#
--
2.31.1

View File

@ -0,0 +1,40 @@
From 18e1b545cbd2d055b16ec3bf5f481d8032dc5dbe Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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
--
2.31.1

View File

@ -0,0 +1,76 @@
From 74575c409bad2940470f31946c97430043c3195e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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
--
2.31.1

View File

@ -0,0 +1,43 @@
From d58192a8d2810271d5c6525dc66ba1e1ec3fd2b7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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"]
|==================
--
2.31.1

View File

@ -0,0 +1,39 @@
From 34ba60c0c2b6057e8b56a77e47899bbeccd88bfd Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
---
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 \/
--
2.31.1

View File

@ -0,0 +1,162 @@
From 160d84fb761c54a5f757aff907fc197d259196bd Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <fw@strlen.de>
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 <fw@strlen.de>
---
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);
}
;
--
2.31.1

View File

@ -0,0 +1,83 @@
From e872d169c189f363ebbdc39105510c1809b58276 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <sbrivio@redhat.com>
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 <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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,14 +300,28 @@ 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
*
@@ -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)
--
2.31.1

View File

@ -0,0 +1,181 @@
From c8a5da2f527c85ab7c392cd293ff37d02a3f93a7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <sbrivio@redhat.com>
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 <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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;
}
--
2.31.1

View File

@ -0,0 +1,577 @@
From 7b1f98e90a32865faca9a97f4348f20c753cd2f3 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <sbrivio@redhat.com>
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 <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
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 <statement.h>
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;
--
2.31.1

View File

@ -0,0 +1,119 @@
From 68392da523f43b9ae09f824fa68b04b20c9c88f5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Eric Garver <eric@garver.life>
---
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)) {
--
2.31.1

View File

@ -0,0 +1,51 @@
From f7a31d5c3277b29f104fd8ff48df24c8bc790f19 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Reviewed-by: Florian Westphal <fw@strlen.de>
---
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
--
2.31.1

View File

@ -0,0 +1,53 @@
From 58d8baa70172bb9862276ac5f542248c88d3faf4 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
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 <phil@nwl.cc>
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 <phil@nwl.cc>
Acked-by: Eric Garver <eric@garver.life>
---
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");
--
2.31.1

View File

@ -0,0 +1,42 @@
From ab62f33df5ef33f6eff8d88d9475a01822a2f625 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 30 Jun 2020 16:20:22 +0200
Subject: [PATCH] segtree: Fix missing expires value in prefixes
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1832235
Upstream Status: nftables commit 60ba9c22fecc0
commit 60ba9c22fecc0ca9bb2a61f6ad39bceed1aee38f
Author: Phil Sutter <phil@nwl.cc>
Date: Tue Apr 28 20:54:03 2020 +0200
segtree: Fix missing expires value in prefixes
This probable copy'n'paste bug prevented 'expiration' field from being
populated when turning a range into a prefix in
interval_map_decompose(). Consequently, interval sets with timeout did
print expiry value for ranges (such as 10.0.0.1-10.0.0.5) but not
prefixes (10.0.0.0/8, for instance).
Fixes: bb0e6d8a2851b ("segtree: incorrect handling of comments and timeouts with mapping")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/segtree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/segtree.c b/src/segtree.c
index e859f84..1ba4363 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -1086,7 +1086,7 @@ void interval_map_decompose(struct expr *set)
prefix->comment = xstrdup(low->comment);
if (low->timeout)
prefix->timeout = low->timeout;
- if (low->left->expiration)
+ if (low->expiration)
prefix->expiration = low->expiration;
}
--
2.31.1

View File

@ -0,0 +1,55 @@
From 119fbcbd8c37aac314d6ffa6225ab24ee4b0e31e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 30 Jun 2020 16:20:23 +0200
Subject: [PATCH] segtree: Use expr_clone in get_set_interval_*()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1832235
Upstream Status: nftables commit a2eedcc89d2ed
commit a2eedcc89d2ed40411c26d53579300c4f1ccb83d
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Apr 30 13:45:40 2020 +0200
segtree: Use expr_clone in get_set_interval_*()
Both functions perform interval set lookups with either start and end or
only start values as input. Interestingly, in practice they either see
values which are not contained or which match an existing range exactly.
Make use of the above and just return a clone of the matching entry
instead of creating a new one based on input data.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/segtree.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/segtree.c b/src/segtree.c
index 1ba4363..dc4db6b 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -695,9 +695,7 @@ static struct expr *get_set_interval_find(const struct table *table,
range_expr_value_high(high, i);
if (mpz_cmp(left->key->value, low) >= 0 &&
mpz_cmp(right->key->value, high) <= 0) {
- range = range_expr_alloc(&internal_location,
- expr_clone(left->key),
- expr_clone(right->key));
+ range = expr_clone(i->key);
goto out;
}
break;
@@ -729,9 +727,7 @@ static struct expr *get_set_interval_end(const struct table *table,
case EXPR_RANGE:
range_expr_value_low(low, i);
if (mpz_cmp(low, left->key->value) == 0) {
- range = range_expr_alloc(&internal_location,
- expr_clone(left->key),
- expr_clone(i->key->right));
+ range = expr_clone(i->key);
goto out;
}
break;
--
2.31.1

View File

@ -0,0 +1,131 @@
From 40cdcccf0fc6f4d0d4c2248d4bd9bf3193a922e9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 30 Jun 2020 16:20:23 +0200
Subject: [PATCH] segtree: Merge get_set_interval_find() and
get_set_interval_end()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1832235
Upstream Status: nftables commit f21e73d6700b8
commit f21e73d6700b873eb1a295f43bbad9caaca577e2
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Apr 30 13:57:35 2020 +0200
segtree: Merge get_set_interval_find() and get_set_interval_end()
Both functions were very similar already. Under the assumption that they
will always either see a range (or start of) that matches exactly or not
at all, reduce complexity and make get_set_interval_find() accept NULL
(left or) right values. This way it becomes a full replacement for
get_set_interval_end().
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/segtree.c | 63 +++++++++++++--------------------------------------
1 file changed, 16 insertions(+), 47 deletions(-)
diff --git a/src/segtree.c b/src/segtree.c
index dc4db6b..6e1f696 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -681,63 +681,31 @@ static struct expr *get_set_interval_find(const struct table *table,
{
struct expr *range = NULL;
struct set *set;
- mpz_t low, high;
struct expr *i;
+ mpz_t val;
set = set_lookup(table, set_name);
- mpz_init2(low, set->key->len);
- mpz_init2(high, set->key->len);
+ mpz_init2(val, set->key->len);
list_for_each_entry(i, &set->init->expressions, list) {
switch (i->key->etype) {
case EXPR_RANGE:
- range_expr_value_low(low, i);
- range_expr_value_high(high, i);
- if (mpz_cmp(left->key->value, low) >= 0 &&
- mpz_cmp(right->key->value, high) <= 0) {
- range = expr_clone(i->key);
- goto out;
- }
- break;
- default:
- break;
- }
- }
-out:
- mpz_clear(low);
- mpz_clear(high);
-
- return range;
-}
-
-static struct expr *get_set_interval_end(const struct table *table,
- const char *set_name,
- struct expr *left)
-{
- struct expr *i, *range = NULL;
- struct set *set;
- mpz_t low, high;
+ range_expr_value_low(val, i);
+ if (left && mpz_cmp(left->key->value, val))
+ break;
- set = set_lookup(table, set_name);
- mpz_init2(low, set->key->len);
- mpz_init2(high, set->key->len);
+ range_expr_value_high(val, i);
+ if (right && mpz_cmp(right->key->value, val))
+ break;
- list_for_each_entry(i, &set->init->expressions, list) {
- switch (i->key->etype) {
- case EXPR_RANGE:
- range_expr_value_low(low, i);
- if (mpz_cmp(low, left->key->value) == 0) {
- range = expr_clone(i->key);
- goto out;
- }
- break;
+ range = expr_clone(i->key);
+ goto out;
default:
break;
}
}
out:
- mpz_clear(low);
- mpz_clear(high);
+ mpz_clear(val);
return range;
}
@@ -767,9 +735,9 @@ int get_set_decompose(struct table *table, struct set *set)
left = NULL;
} else {
if (left) {
- range = get_set_interval_end(table,
- set->handle.set.name,
- left);
+ range = get_set_interval_find(table,
+ set->handle.set.name,
+ left, NULL);
if (range)
compound_expr_add(new_init, range);
else
@@ -780,7 +748,8 @@ int get_set_decompose(struct table *table, struct set *set)
}
}
if (left) {
- range = get_set_interval_end(table, set->handle.set.name, left);
+ range = get_set_interval_find(table, set->handle.set.name,
+ left, NULL);
if (range)
compound_expr_add(new_init, range);
else
--
2.31.1

View File

@ -0,0 +1,41 @@
From 4337d4eafe66b594b56b43261c8742d6b65d5ee8 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 30 Jun 2020 16:20:23 +0200
Subject: [PATCH] tests: 0034get_element_0: do not discard stderr
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1832235
Upstream Status: nftables commit ff29e6c09aed9
commit ff29e6c09aed922a42e0e0551c34dd5d87067512
Author: Florian Westphal <fw@strlen.de>
Date: Sat Feb 22 00:02:25 2020 +0100
tests: 0034get_element_0: do not discard stderr
run_tests.sh alreadty discards stderr by default, but will show it in
case the test script is run directly (passed as argument).
Discarding stderr also in the script prevents one from seeing
BUG() assertions and the like.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
tests/shell/testcases/sets/0034get_element_0 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/shell/testcases/sets/0034get_element_0 b/tests/shell/testcases/sets/0034get_element_0
index c7e7298..e23dbda 100755
--- a/tests/shell/testcases/sets/0034get_element_0
+++ b/tests/shell/testcases/sets/0034get_element_0
@@ -3,7 +3,7 @@
RC=0
check() { # (elems, expected)
- out=$($NFT get element ip t s "{ $1 }" 2>/dev/null)
+ out=$($NFT get element ip t s "{ $1 }")
out=$(grep "elements =" <<< "$out")
out="${out#* \{ }"
out="${out% \}}"
--
2.31.1

View File

@ -0,0 +1,135 @@
From 3a2016f539e46183965bada40946e259c33158d9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 30 Jun 2020 16:20:23 +0200
Subject: [PATCH] segtree: Fix get element command with prefixes
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1832235
Upstream Status: nftables commit 506fb113f7ca4
commit 506fb113f7ca4fbb3d6da09ef6f9dc2b31f54a1f
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Apr 30 14:02:44 2020 +0200
segtree: Fix get element command with prefixes
Code wasn't aware of prefix elements in interval sets. With previous
changes in place, they merely need to be accepted in
get_set_interval_find() - value comparison and expression duplication is
identical to ranges.
Extend sets/0034get_element_0 test to cover prefixes as well. While
being at it, also cover concatenated ranges.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/segtree.c | 1 +
tests/shell/testcases/sets/0034get_element_0 | 62 ++++++++++++++------
2 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/src/segtree.c b/src/segtree.c
index 6e1f696..073c6ec 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -689,6 +689,7 @@ static struct expr *get_set_interval_find(const struct table *table,
list_for_each_entry(i, &set->init->expressions, list) {
switch (i->key->etype) {
+ case EXPR_PREFIX:
case EXPR_RANGE:
range_expr_value_low(val, i);
if (left && mpz_cmp(left->key->value, val))
diff --git a/tests/shell/testcases/sets/0034get_element_0 b/tests/shell/testcases/sets/0034get_element_0
index e23dbda..3343529 100755
--- a/tests/shell/testcases/sets/0034get_element_0
+++ b/tests/shell/testcases/sets/0034get_element_0
@@ -2,43 +2,69 @@
RC=0
-check() { # (elems, expected)
- out=$($NFT get element ip t s "{ $1 }")
+check() { # (set, elems, expected)
+ out=$($NFT get element ip t $1 "{ $2 }")
out=$(grep "elements =" <<< "$out")
out="${out#* \{ }"
out="${out% \}}"
- [[ "$out" == "$2" ]] && return
- echo "ERROR: asked for '$1', expecting '$2' but got '$out'"
+ [[ "$out" == "$3" ]] && return
+ echo "ERROR: asked for '$2' in set $1, expecting '$3' but got '$out'"
((RC++))
}
RULESET="add table ip t
add set ip t s { type inet_service; flags interval; }
add element ip t s { 10, 20-30, 40, 50-60 }
+add set ip t ips { type ipv4_addr; flags interval; }
+add element ip t ips { 10.0.0.1, 10.0.0.5-10.0.0.8 }
+add element ip t ips { 10.0.0.128/25, 10.0.1.0/24, 10.0.2.3-10.0.2.12 }
+add set ip t cs { type ipv4_addr . inet_service; flags interval; }
+add element ip t cs { 10.0.0.1 . 22, 10.1.0.0/16 . 1-1024 }
+add element ip t cs { 10.2.0.1-10.2.0.8 . 1024-65535 }
"
$NFT -f - <<< "$RULESET"
# simple cases, (non-)existing values and ranges
-check 10 10
-check 11 ""
-check 20-30 20-30
-check 15-18 ""
+check s 10 10
+check s 11 ""
+check s 20-30 20-30
+check s 15-18 ""
# multiple single elements, ranges smaller than present
-check "10, 40" "10, 40"
-check "22-24, 26-28" "20-30, 20-30"
-check 21-29 20-30
+check s "10, 40" "10, 40"
+check s "22-24, 26-28" "20-30, 20-30"
+check s 21-29 20-30
# mixed single elements and ranges
-check "10, 20" "10, 20-30"
-check "10, 22" "10, 20-30"
-check "10, 22-24" "10, 20-30"
+check s "10, 20" "10, 20-30"
+check s "10, 22" "10, 20-30"
+check s "10, 22-24" "10, 20-30"
# non-existing ranges matching elements
-check 10-40 ""
-check 10-20 ""
-check 10-25 ""
-check 25-55 ""
+check s 10-40 ""
+check s 10-20 ""
+check s 10-25 ""
+check s 25-55 ""
+
+# playing with IPs, ranges and prefixes
+check ips 10.0.0.1 10.0.0.1
+check ips 10.0.0.2 ""
+check ips 10.0.1.0/24 10.0.1.0/24
+check ips 10.0.1.2/31 10.0.1.0/24
+check ips 10.0.1.0 10.0.1.0/24
+check ips 10.0.1.3 10.0.1.0/24
+check ips 10.0.1.255 10.0.1.0/24
+check ips 10.0.2.3-10.0.2.12 10.0.2.3-10.0.2.12
+check ips 10.0.2.10 10.0.2.3-10.0.2.12
+check ips 10.0.2.12 10.0.2.3-10.0.2.12
+
+# test concatenated ranges, i.e. Pi, Pa and Po
+check cs "10.0.0.1 . 22" "10.0.0.1 . 22"
+check cs "10.0.0.1 . 23" ""
+check cs "10.0.0.2 . 22" ""
+check cs "10.1.0.1 . 42" "10.1.0.0/16 . 1-1024"
+check cs "10.1.1.0/24 . 10-20" "10.1.0.0/16 . 1-1024"
+check cs "10.2.0.3 . 20000" "10.2.0.1-10.2.0.8 . 1024-65535"
exit $RC
--
2.31.1

View File

@ -0,0 +1,45 @@
From 77a93baa622f8aa33fa6182d72b380d980e39574 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Sat, 8 Aug 2020 00:09:06 +0200
Subject: [PATCH] include: Resync nf_tables.h cache copy
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820684
Upstream Status: nftables commit f1e5a0499c077
commit f1e5a0499c0773f18bc592dd0da0340120daa482
Author: Stefano Brivio <sbrivio@redhat.com>
Date: Mon Apr 13 21:48:02 2020 +0200
include: Resync nf_tables.h cache copy
Get this header in sync with nf.git as of commit ef516e8625dd.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter/nf_tables.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 1a99df3..9b54a86 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -274,6 +274,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_TIMEOUT: set uses timeouts
* @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects
+ * @NFT_SET_CONCAT: set contains a concatenation
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
@@ -283,6 +284,7 @@ enum nft_set_flags {
NFT_SET_TIMEOUT = 0x10,
NFT_SET_EVAL = 0x20,
NFT_SET_OBJECT = 0x40,
+ NFT_SET_CONCAT = 0x80,
};
/**
--
2.31.1

View File

@ -0,0 +1,72 @@
From 5566405cc171c8fa84e0a13ea96b89245a3fb512 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Sat, 8 Aug 2020 00:05:48 +0200
Subject: [PATCH] src: Set NFT_SET_CONCAT flag for sets with concatenated
ranges
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820684
Upstream Status: nftables commit 09441b5e92cee
commit 09441b5e92ceea60198a35cd657904fa7a10ee54
Author: Stefano Brivio <sbrivio@redhat.com>
Date: Mon Apr 13 21:48:03 2020 +0200
src: Set NFT_SET_CONCAT flag for sets with concatenated ranges
Pablo reports that nft, after commit 8ac2f3b2fca3 ("src: Add support
for concatenated set ranges"), crashes with older kernels (< 5.6)
without support for concatenated set ranges: those sets will be sent
to the kernel, which adds them without notion of the fact that
different concatenated fields are actually included, and nft crashes
while trying to list this kind of malformed concatenation.
Use the NFT_SET_CONCAT flag introduced by kernel commit ef516e8625dd
("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag") when
sets including concatenated ranges are sent to the kernel, so that
older kernels (with no knowledge of this flag itself) will refuse set
creation.
Note that, in expr_evaluate_set(), we have to check for the presence
of the flag, also on empty sets that might carry it in context data,
and actually set it in the actual set flags.
Reported-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 0c84816..f66251b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1360,10 +1360,16 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
set->size += i->size - 1;
set->set_flags |= i->set_flags;
expr_free(i);
- } else if (!expr_is_singleton(i))
+ } else if (!expr_is_singleton(i)) {
set->set_flags |= NFT_SET_INTERVAL;
+ if (i->key->etype == EXPR_CONCAT)
+ set->set_flags |= NFT_SET_CONCAT;
+ }
}
+ if (ctx->set && (ctx->set->flags & NFT_SET_CONCAT))
+ set->set_flags |= NFT_SET_CONCAT;
+
set->set_flags |= NFT_SET_CONSTANT;
datatype_set(set, ctx->ectx.dtype);
@@ -3336,6 +3342,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
memcpy(&set->desc.field_len, &set->key->field_len,
sizeof(set->desc.field_len));
set->desc.field_count = set->key->field_count;
+ set->flags |= NFT_SET_CONCAT;
}
if (set_is_datamap(set->flags)) {
--
2.31.1

View File

@ -0,0 +1,503 @@
From 19da892698f1dce2125a796ad86239711896978f Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:25:20 +0100
Subject: [PATCH] src: store expr, not dtype to track data in sets
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1877022
Upstream Status: nftables commit 343a51702656a
commit 343a51702656a6476e37cfb84609a82155c7fc5e
Author: Florian Westphal <fw@strlen.de>
Date: Tue Jul 16 19:03:55 2019 +0200
src: store expr, not dtype to track data in sets
This will be needed once we add support for the 'typeof' keyword to
handle maps that could e.g. store 'ct helper' "type" values.
Instead of:
set foo {
type ipv4_addr . mark;
this would allow
set foo {
typeof(ip saddr) . typeof(ct mark);
(exact syntax TBD).
This would be needed to allow sets that store variable-sized data types
(string, integer and the like) that can't be used at at the moment.
Adding special data types for everything is problematic due to the
large amount of different types needed.
For anonymous sets, e.g. "string" can be used because the needed size can
be inferred from the statement, e.g. 'osf name { "Windows", "Linux }',
but in case of named sets that won't work because 'type string' lacks the
context needed to derive the size information.
With 'typeof(osf name)' the context is there, but at the moment it won't
help because the expression is discarded instantly and only the data
type is retained.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/datatype.h | 1 -
include/netlink.h | 1 -
include/rule.h | 6 ++---
src/datatype.c | 5 ----
src/evaluate.c | 58 ++++++++++++++++++++++++++++++++--------------
src/expression.c | 2 +-
src/json.c | 4 ++--
src/mnl.c | 6 ++---
src/monitor.c | 2 +-
src/netlink.c | 32 ++++++++++++-------------
src/parser_bison.y | 3 +--
src/parser_json.c | 8 +++++--
src/rule.c | 8 +++----
src/segtree.c | 8 +++++--
14 files changed, 81 insertions(+), 63 deletions(-)
diff --git a/include/datatype.h b/include/datatype.h
index 49b8f60..04b4892 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -293,7 +293,6 @@ concat_subtype_lookup(uint32_t type, unsigned int n)
extern const struct datatype *
set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
-extern void set_datatype_destroy(const struct datatype *dtype);
extern void time_print(uint64_t msec, struct output_ctx *octx);
extern struct error_record *time_parse(const struct location *loc,
diff --git a/include/netlink.h b/include/netlink.h
index e694171..88d12ba 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -189,6 +189,5 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
struct netlink_mon_handler *monh);
enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type);
#endif /* NFTABLES_NETLINK_H */
diff --git a/include/rule.h b/include/rule.h
index 626973e..3637462 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -283,8 +283,7 @@ extern struct rule *rule_lookup_by_index(const struct chain *chain,
* @gc_int: garbage collection interval
* @timeout: default timeout value
* @key: key expression (data type, length))
- * @datatype: mapping data type
- * @datalen: mapping data len
+ * @data: mapping data expression
* @objtype: mapping object type
* @init: initializer
* @rg_cache: cached range element (left)
@@ -303,8 +302,7 @@ struct set {
uint32_t gc_int;
uint64_t timeout;
struct expr *key;
- const struct datatype *datatype;
- unsigned int datalen;
+ struct expr *data;
uint32_t objtype;
struct expr *init;
struct expr *rg_cache;
diff --git a/src/datatype.c b/src/datatype.c
index b9e167e..189e1b4 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -1190,11 +1190,6 @@ const struct datatype *set_datatype_alloc(const struct datatype *orig_dtype,
return dtype;
}
-void set_datatype_destroy(const struct datatype *dtype)
-{
- datatype_free(dtype);
-}
-
static struct error_record *time_unit_parse(const struct location *loc,
const char *str, uint64_t *unit)
{
diff --git a/src/evaluate.c b/src/evaluate.c
index f66251b..578dcae 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1383,6 +1383,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
{
struct expr_ctx ectx = ctx->ectx;
struct expr *map = *expr, *mappings;
+ const struct datatype *dtype;
struct expr *key;
expr_set_context(&ctx->ectx, NULL, 0);
@@ -1405,10 +1406,14 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
mappings = implicit_set_declaration(ctx, "__map%d",
key,
mappings);
- mappings->set->datatype =
- datatype_get(set_datatype_alloc(ectx.dtype,
- ectx.byteorder));
- mappings->set->datalen = ectx.len;
+
+ dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ dtype, dtype->byteorder,
+ ectx.len, NULL);
+ if (ectx.len && mappings->set->data->len != ectx.len)
+ BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
map->mappings = mappings;
@@ -1444,7 +1449,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
@@ -1474,7 +1479,12 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
"Key must be a constant");
mapping->flags |= mapping->left->flags & EXPR_F_SINGLETON;
- expr_set_context(&ctx->ectx, set->datatype, set->datalen);
+ if (set->data) {
+ expr_set_context(&ctx->ectx, set->data->dtype, set->data->len);
+ } else {
+ assert((set->flags & NFT_SET_MAP) == 0);
+ }
+
if (expr_evaluate(ctx, &mapping->right) < 0)
return -1;
if (!expr_is_constant(mapping->right))
@@ -2119,7 +2129,7 @@ static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
(*expr)->len);
else if ((*expr)->dtype->type != TYPE_INTEGER &&
!datatype_equal((*expr)->dtype, dtype))
- return stmt_binary_error(ctx, *expr, stmt,
+ return stmt_binary_error(ctx, *expr, stmt, /* verdict vs invalid? */
"datatype mismatch: expected %s, "
"expression has type %s",
dtype->desc, (*expr)->dtype->desc);
@@ -3113,9 +3123,9 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
"Key expression comments are not supported");
if (stmt_evaluate_arg(ctx, stmt,
- stmt->map.set->set->datatype,
- stmt->map.set->set->datalen,
- stmt->map.set->set->datatype->byteorder,
+ stmt->map.set->set->data->dtype,
+ stmt->map.set->set->data->len,
+ stmt->map.set->set->data->byteorder,
&stmt->map.data->key) < 0)
return -1;
if (expr_is_constant(stmt->map.data))
@@ -3161,8 +3171,12 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
mappings = implicit_set_declaration(ctx, "__objmap%d",
key, mappings);
- mappings->set->datatype = &string_type;
- mappings->set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
mappings->set->objtype = stmt->objref.type;
map->mappings = mappings;
@@ -3197,7 +3211,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
@@ -3346,17 +3360,25 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
}
if (set_is_datamap(set->flags)) {
- if (set->datatype == NULL)
+ if (set->data == NULL)
return set_error(ctx, set, "map definition does not "
"specify mapping data type");
- set->datalen = set->datatype->size;
- if (set->datalen == 0 && set->datatype->type != TYPE_VERDICT)
+ if (set->data->len == 0 && set->data->dtype->type != TYPE_VERDICT)
return set_error(ctx, set, "unqualified mapping data "
"type specified in map definition");
} else if (set_is_objmap(set->flags)) {
- set->datatype = &string_type;
- set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+ if (set->data) {
+ assert(set->data->etype == EXPR_VALUE);
+ assert(set->data->dtype == &string_type);
+ }
+
+ assert(set->data == NULL);
+ set->data = constant_expr_alloc(&netlink_location, &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
+
}
ctx->set = set;
diff --git a/src/expression.c b/src/expression.c
index 5070b10..6fa2f1d 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -1010,7 +1010,7 @@ static void map_expr_print(const struct expr *expr, struct output_ctx *octx)
{
expr_print(expr->map, octx);
if (expr->mappings->etype == EXPR_SET_REF &&
- expr->mappings->set->datatype->type == TYPE_VERDICT)
+ expr->mappings->set->data->dtype->type == TYPE_VERDICT)
nft_print(octx, " vmap ");
else
nft_print(octx, " map ");
diff --git a/src/json.c b/src/json.c
index 3498e24..1906e7d 100644
--- a/src/json.c
+++ b/src/json.c
@@ -82,7 +82,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
if (set_is_datamap(set->flags)) {
type = "map";
- datatype_ext = set->datatype->name;
+ datatype_ext = set->data->dtype->name;
} else if (set_is_objmap(set->flags)) {
type = "map";
datatype_ext = obj_type_name(set->objtype);
@@ -645,7 +645,7 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
const char *type = "map";
if (expr->mappings->etype == EXPR_SET_REF &&
- expr->mappings->set->datatype->type == TYPE_VERDICT)
+ expr->mappings->set->data->dtype->type == TYPE_VERDICT)
type = "vmap";
return json_pack("{s:{s:o, s:o}}", type,
diff --git a/src/mnl.c b/src/mnl.c
index 221ee05..23341e6 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -839,9 +839,9 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
div_round_up(set->key->len, BITS_PER_BYTE));
if (set_is_datamap(set->flags)) {
nftnl_set_set_u32(nls, NFTNL_SET_DATA_TYPE,
- dtype_map_to_kernel(set->datatype));
+ dtype_map_to_kernel(set->data->dtype));
nftnl_set_set_u32(nls, NFTNL_SET_DATA_LEN,
- set->datalen / BITS_PER_BYTE);
+ set->data->len / BITS_PER_BYTE);
}
if (set_is_objmap(set->flags))
nftnl_set_set_u32(nls, NFTNL_SET_OBJ_TYPE, set->objtype);
@@ -873,7 +873,7 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
if (set_is_datamap(set->flags) &&
!nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_DATABYTEORDER,
- set->datatype->byteorder))
+ set->data->byteorder))
memory_allocation_error();
if (set->automerge &&
diff --git a/src/monitor.c b/src/monitor.c
index fb803cf..7927b6f 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -401,7 +401,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
*/
dummyset = set_alloc(monh->loc);
dummyset->key = expr_clone(set->key);
- dummyset->datatype = set->datatype;
+ dummyset->data = set->data;
dummyset->flags = set->flags;
dummyset->init = set_expr_alloc(monh->loc, set);
diff --git a/src/netlink.c b/src/netlink.c
index e0ba903..64e51e5 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -575,7 +575,7 @@ enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype)
}
}
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
+static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
{
switch (type) {
case NFT_DATA_VERDICT:
@@ -622,10 +622,10 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
const struct nftnl_set *nls)
{
const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {};
- uint32_t flags, key, data, data_len, objtype = 0;
enum byteorder keybyteorder = BYTEORDER_INVALID;
enum byteorder databyteorder = BYTEORDER_INVALID;
- const struct datatype *keytype, *datatype;
+ const struct datatype *keytype, *datatype = NULL;
+ uint32_t flags, key, objtype = 0;
bool automerge = false;
const char *udata;
struct set *set;
@@ -659,6 +659,8 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
if (set_is_datamap(flags)) {
+ uint32_t data;
+
data = nftnl_set_get_u32(nls, NFTNL_SET_DATA_TYPE);
datatype = dtype_map_from_kernel(data);
if (datatype == NULL) {
@@ -667,8 +669,7 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
data);
return NULL;
}
- } else
- datatype = NULL;
+ }
if (set_is_objmap(flags)) {
objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
@@ -691,16 +692,13 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
set->objtype = objtype;
+ set->data = NULL;
if (datatype)
- set->datatype = datatype_get(set_datatype_alloc(datatype,
- databyteorder));
- else
- set->datatype = NULL;
-
- if (nftnl_set_is_set(nls, NFTNL_SET_DATA_LEN)) {
- data_len = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN);
- set->datalen = data_len * BITS_PER_BYTE;
- }
+ set->data = constant_expr_alloc(&netlink_location,
+ set_datatype_alloc(datatype, databyteorder),
+ databyteorder,
+ nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE,
+ NULL);
if (nftnl_set_is_set(nls, NFTNL_SET_TIMEOUT))
set->timeout = nftnl_set_get_u64(nls, NFTNL_SET_TIMEOUT);
@@ -897,10 +895,10 @@ key_end:
goto out;
data = netlink_alloc_data(&netlink_location, &nld,
- set->datatype->type == TYPE_VERDICT ?
+ set->data->dtype->type == TYPE_VERDICT ?
NFT_REG_VERDICT : NFT_REG_1);
- datatype_set(data, set->datatype);
- data->byteorder = set->datatype->byteorder;
+ datatype_set(data, set->data->dtype);
+ data->byteorder = set->data->byteorder;
if (data->byteorder == BYTEORDER_HOST_ENDIAN)
mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index ea83f52..4cca31b 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1749,9 +1749,8 @@ map_block : /* empty */ { $$ = $<set>-1; }
stmt_separator
{
$1->key = $3;
- $1->datatype = $5->dtype;
+ $1->data = $5;
- expr_free($5);
$1->flags |= NFT_SET_MAP;
$$ = $1;
}
diff --git a/src/parser_json.c b/src/parser_json.c
index ce8e566..ddc694f 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -2833,11 +2833,15 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
}
if (!json_unpack(root, "{s:s}", "map", &dtype_ext)) {
+ const struct datatype *dtype;
+
set->objtype = string_to_nft_object(dtype_ext);
if (set->objtype) {
set->flags |= NFT_SET_OBJECT;
- } else if (datatype_lookup_byname(dtype_ext)) {
- set->datatype = datatype_lookup_byname(dtype_ext);
+ } else if ((dtype = datatype_lookup_byname(dtype_ext))) {
+ set->data = constant_expr_alloc(&netlink_location,
+ dtype, dtype->byteorder,
+ dtype->size, NULL);
set->flags |= NFT_SET_MAP;
} else {
json_error(ctx, "Invalid map type '%s'.", dtype_ext);
diff --git a/src/rule.c b/src/rule.c
index e18237b..f7d888b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -332,8 +332,8 @@ struct set *set_clone(const struct set *set)
new_set->gc_int = set->gc_int;
new_set->timeout = set->timeout;
new_set->key = expr_clone(set->key);
- new_set->datatype = datatype_get(set->datatype);
- new_set->datalen = set->datalen;
+ if (set->data)
+ new_set->data = expr_clone(set->data);
new_set->objtype = set->objtype;
new_set->policy = set->policy;
new_set->automerge = set->automerge;
@@ -356,7 +356,7 @@ void set_free(struct set *set)
expr_free(set->init);
handle_free(&set->handle);
expr_free(set->key);
- set_datatype_destroy(set->datatype);
+ expr_free(set->data);
xfree(set);
}
@@ -469,7 +469,7 @@ static void set_print_declaration(const struct set *set,
nft_print(octx, "%s%stype %s",
opts->tab, opts->tab, set->key->dtype->name);
if (set_is_datamap(set->flags))
- nft_print(octx, " : %s", set->datatype->name);
+ nft_print(octx, " : %s", set->data->dtype->name);
else if (set_is_objmap(set->flags))
nft_print(octx, " : %s", obj_type_name(set->objtype));
diff --git a/src/segtree.c b/src/segtree.c
index 073c6ec..d6e3ce2 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -79,8 +79,12 @@ static void seg_tree_init(struct seg_tree *tree, const struct set *set,
tree->root = RB_ROOT;
tree->keytype = set->key->dtype;
tree->keylen = set->key->len;
- tree->datatype = set->datatype;
- tree->datalen = set->datalen;
+ tree->datatype = NULL;
+ tree->datalen = 0;
+ if (set->data) {
+ tree->datatype = set->data->dtype;
+ tree->datalen = set->data->len;
+ }
tree->byteorder = first->byteorder;
tree->debug_mask = debug_mask;
}
--
2.31.1

View File

@ -0,0 +1,120 @@
From 785823a1f607a7bcd32d4cb42655422c223fcad5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:25:20 +0100
Subject: [PATCH] evaluate: Perform set evaluation on implicitly declared
(anonymous) sets
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1877022
Upstream Status: nftables commit 7aa08d45031ec
commit 7aa08d45031ec7ce5dadb4979471d626367c09cd
Author: Stefano Brivio <sbrivio@redhat.com>
Date: Wed May 27 22:51:21 2020 +0200
evaluate: Perform set evaluation on implicitly declared (anonymous) sets
If a set is implicitly declared, set_evaluate() is not called as a
result of cmd_evaluate_add(), because we're adding in fact something
else (e.g. a rule). Expression-wise, evaluation still happens as the
implicit set expression is eventually found in the tree and handled
by expr_evaluate_set(), but context-wise evaluation (set_evaluate())
is skipped, and this might be relevant instead.
This is visible in the reported case of an anonymous set including
concatenated ranges:
# nft add rule t c ip saddr . tcp dport { 192.0.2.1 . 20-30 } accept
BUG: invalid range expression type concat
nft: expression.c:1160: range_expr_value_low: Assertion `0' failed.
Aborted
because we reach do_add_set() without properly evaluated flags and
set description, and eventually end up in expr_to_intervals(), which
can't handle that expression.
Explicitly call set_evaluate() as we add anonymous sets into the
context, and instruct the same function to:
- skip expression-wise set evaluation if the set is anonymous, as
that happens later anyway as part of the general tree evaluation
- skip the insertion in the set cache, as it makes no sense to have
sets that shouldn't be referenced there
For object maps, the allocation of the expression for set->data is
already handled by set_evaluate(), so we can now drop that from
stmt_evaluate_objref_map().
v2:
- skip insertion of set in cache (Pablo Neira Ayuso)
- drop double allocation of expression (and leak of the first
one) for object maps (Pablo Neira Ayuso)
Reported-by: Pablo Neira Ayuso <pablo@netfilter.org>
Reported-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 578dcae..fc45cef 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -75,6 +75,7 @@ static void key_fix_dtype_byteorder(struct expr *key)
datatype_set(key, set_datatype_alloc(dtype, key->byteorder));
}
+static int set_evaluate(struct eval_ctx *ctx, struct set *set);
static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
const char *name,
struct expr *key,
@@ -105,6 +106,8 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
list_add_tail(&cmd->list, &ctx->cmd->list);
}
+ set_evaluate(ctx, set);
+
return set_ref_expr_alloc(&expr->location, set);
}
@@ -3171,12 +3174,6 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
mappings = implicit_set_declaration(ctx, "__objmap%d",
key, mappings);
-
- mappings->set->data = constant_expr_alloc(&netlink_location,
- &string_type,
- BYTEORDER_HOST_ENDIAN,
- NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
- NULL);
mappings->set->objtype = stmt->objref.type;
map->mappings = mappings;
@@ -3381,6 +3378,13 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
}
+ /* Default timeout value implies timeout support */
+ if (set->timeout)
+ set->flags |= NFT_SET_TIMEOUT;
+
+ if (set_is_anonymous(set->flags))
+ return 0;
+
ctx->set = set;
if (set->init != NULL) {
expr_set_context(&ctx->ectx, set->key->dtype, set->key->len);
@@ -3392,10 +3396,6 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set_lookup(table, set->handle.set.name) == NULL)
set_add_hash(set_get(set), table);
- /* Default timeout value implies timeout support */
- if (set->timeout)
- set->flags |= NFT_SET_TIMEOUT;
-
return 0;
}
--
2.31.1

View File

@ -0,0 +1,167 @@
From 3193f74613b16a42d7784452ebf4d53ccd33b887 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 12 Jan 2021 10:34:35 +0100
Subject: [PATCH] evaluate: missing datatype definition in
implicit_set_declaration()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1877022
Upstream Status: nftables commit 54eb1e16cc478
commit 54eb1e16cc4787906fe8206858f0ea0bfb9c1209
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sun Jun 7 15:23:21 2020 +0200
evaluate: missing datatype definition in implicit_set_declaration()
set->data from implicit_set_declaration(), otherwise, set_evaluation()
bails out with:
# nft -f /etc/nftables/inet-filter.nft
/etc/nftables/inet-filter.nft:8:32-54: Error: map definition does not specify
mapping data type
tcp dport vmap { 22 : jump ssh_input }
^^^^^^^^^^^^^^^^^^^^^^^
/etc/nftables/inet-filter.nft:13:26-52: Error: map definition does not specify
mapping data type
iif vmap { "eth0" : jump wan_input }
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Add a test to cover this case.
Fixes: 7aa08d45031e ("evaluate: Perform set evaluation on implicitly declared (anonymous) sets")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=208093
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 22 +++++++++++----------
tests/shell/testcases/maps/0009vmap_0 | 19 ++++++++++++++++++
tests/shell/testcases/maps/dumps/0009vmap_0 | 13 ++++++++++++
3 files changed, 44 insertions(+), 10 deletions(-)
create mode 100755 tests/shell/testcases/maps/0009vmap_0
create mode 100644 tests/shell/testcases/maps/dumps/0009vmap_0
diff --git a/src/evaluate.c b/src/evaluate.c
index fc45cef..a966ed4 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -79,6 +79,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set);
static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
const char *name,
struct expr *key,
+ struct expr *data,
struct expr *expr)
{
struct cmd *cmd;
@@ -92,6 +93,7 @@ static struct expr *implicit_set_declaration(struct eval_ctx *ctx,
set->flags = NFT_SET_ANONYMOUS | expr->set_flags;
set->handle.set.name = xstrdup(name);
set->key = key;
+ set->data = data;
set->init = expr;
set->automerge = set->flags & NFT_SET_INTERVAL;
@@ -1387,7 +1389,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
struct expr_ctx ectx = ctx->ectx;
struct expr *map = *expr, *mappings;
const struct datatype *dtype;
- struct expr *key;
+ struct expr *key, *data;
expr_set_context(&ctx->ectx, NULL, 0);
if (expr_evaluate(ctx, &map->map) < 0)
@@ -1406,15 +1408,14 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
ctx->ectx.byteorder,
ctx->ectx.len, NULL);
+ dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
+ data = constant_expr_alloc(&netlink_location, dtype,
+ dtype->byteorder, ectx.len, NULL);
+
mappings = implicit_set_declaration(ctx, "__map%d",
- key,
+ key, data,
mappings);
- dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
-
- mappings->set->data = constant_expr_alloc(&netlink_location,
- dtype, dtype->byteorder,
- ectx.len, NULL);
if (ectx.len && mappings->set->data->len != ectx.len)
BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
@@ -1857,7 +1858,8 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
case EXPR_SET:
right = rel->right =
implicit_set_declaration(ctx, "__set%d",
- expr_get(left), right);
+ expr_get(left), NULL,
+ right);
/* fall through */
case EXPR_SET_REF:
/* Data for range lookups needs to be in big endian order */
@@ -2335,7 +2337,7 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
set->set_flags |= NFT_SET_TIMEOUT;
setref = implicit_set_declaration(ctx, stmt->meter.name,
- expr_get(key), set);
+ expr_get(key), NULL, set);
setref->set->desc.size = stmt->meter.size;
stmt->meter.set = setref;
@@ -3173,7 +3175,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
ctx->ectx.len, NULL);
mappings = implicit_set_declaration(ctx, "__objmap%d",
- key, mappings);
+ key, NULL, mappings);
mappings->set->objtype = stmt->objref.type;
map->mappings = mappings;
diff --git a/tests/shell/testcases/maps/0009vmap_0 b/tests/shell/testcases/maps/0009vmap_0
new file mode 100755
index 0000000..7627c81
--- /dev/null
+++ b/tests/shell/testcases/maps/0009vmap_0
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -e
+
+EXPECTED="table inet filter {
+ chain ssh_input {
+ }
+
+ chain wan_input {
+ tcp dport vmap { 22 : jump ssh_input }
+ }
+
+ chain prerouting {
+ type filter hook prerouting priority -300; policy accept;
+ iif vmap { "lo" : jump wan_input }
+ }
+}"
+
+$NFT -f - <<< "$EXPECTED"
diff --git a/tests/shell/testcases/maps/dumps/0009vmap_0 b/tests/shell/testcases/maps/dumps/0009vmap_0
new file mode 100644
index 0000000..540a8af
--- /dev/null
+++ b/tests/shell/testcases/maps/dumps/0009vmap_0
@@ -0,0 +1,13 @@
+table inet filter {
+ chain ssh_input {
+ }
+
+ chain wan_input {
+ tcp dport vmap { 22 : jump ssh_input }
+ }
+
+ chain prerouting {
+ type filter hook prerouting priority -300; policy accept;
+ iif vmap { "lo" : jump wan_input }
+ }
+}
--
2.31.1

View File

@ -0,0 +1,88 @@
From 9d67918643e7d17c433e82eb6cdb039cb103c50f Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:26:24 +0100
Subject: [PATCH] mergesort: unbreak listing with binops
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1891790
Upstream Status: nftables commit 3926a3369bb5a
commit 3926a3369bb5ada5c0706dadcbcf938517822a35
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu Aug 20 01:05:04 2020 +0200
mergesort: unbreak listing with binops
tcp flags == {syn, syn|ack}
tcp flags & (fin|syn|rst|psh|ack|urg) == {ack, psh|ack, fin, fin|psh|ack}
results in:
BUG: Unknown expression binop
nft: mergesort.c:47: expr_msort_cmp: Assertion `0' failed.
Aborted (core dumped)
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/mergesort.c | 2 ++
tests/py/inet/tcp.t | 2 ++
tests/py/inet/tcp.t.payload | 21 +++++++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/src/mergesort.c b/src/mergesort.c
index 649b780..02094b4 100644
--- a/src/mergesort.c
+++ b/src/mergesort.c
@@ -43,6 +43,8 @@ static int expr_msort_cmp(const struct expr *e1, const struct expr *e2)
return concat_expr_msort_cmp(e1, e2);
case EXPR_MAPPING:
return expr_msort_cmp(e1->left, e2->left);
+ case EXPR_BINOP:
+ return expr_msort_cmp(e1->left, e2->left);
default:
BUG("Unknown expression %s\n", expr_name(e1));
}
diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t
index e0a83e2..29f06f5 100644
--- a/tests/py/inet/tcp.t
+++ b/tests/py/inet/tcp.t
@@ -79,6 +79,8 @@ tcp flags != cwr;ok
tcp flags == syn;ok
tcp flags & (syn|fin) == (syn|fin);ok;tcp flags & (fin | syn) == fin | syn
tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff
+tcp flags { syn, syn | ack };ok
+tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack };ok
tcp window 22222;ok
tcp window 22;ok
diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload
index 55f1bc2..076e562 100644
--- a/tests/py/inet/tcp.t.payload
+++ b/tests/py/inet/tcp.t.payload
@@ -680,3 +680,24 @@ inet test-inet input
[ bitwise reg 1 = (reg=1 & 0x000000f0 ) ^ 0x00000000 ]
[ cmp eq reg 1 0x00000080 ]
+# tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000010 : 0 [end] element 00000018 : 0 [end] element 00000019 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = (reg=1 & 0x0000003f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp flags { syn, syn | ack }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000002 : 0 [end] element 00000012 : 0 [end]
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
--
2.31.1

View File

@ -0,0 +1,134 @@
From 876a1202351264f6d3b105258f10bde693870bd4 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:27:16 +0100
Subject: [PATCH] proto: add sctp crc32 checksum fixup
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1895804
Upstream Status: nftables commit 09a3b2ba0c822
commit 09a3b2ba0c8228d1c6bf0f030cae97addb397351
Author: Florian Westphal <fw@strlen.de>
Date: Tue Oct 6 23:16:32 2020 +0200
proto: add sctp crc32 checksum fixup
Stateless SCTP header mangling doesn't work reliably.
This tells the kernel to update the checksum field using
the sctp crc32 algorithm.
Note that this needs additional kernel support to work.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter/nf_tables.h | 2 ++
include/proto.h | 1 +
src/netlink_linearize.c | 2 +-
src/proto.c | 8 ++++++++
4 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 9b54a86..1328b8e 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -707,10 +707,12 @@ enum nft_payload_bases {
*
* @NFT_PAYLOAD_CSUM_NONE: no checksumming
* @NFT_PAYLOAD_CSUM_INET: internet checksum (RFC 791)
+ * @NFT_PAYLOAD_CSUM_SCTP: CRC-32c, for use in SCTP header (RFC 3309)
*/
enum nft_payload_csum_types {
NFT_PAYLOAD_CSUM_NONE,
NFT_PAYLOAD_CSUM_INET,
+ NFT_PAYLOAD_CSUM_SCTP,
};
enum nft_payload_csum_flags {
diff --git a/include/proto.h b/include/proto.h
index fab48c1..436cbe3 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -78,6 +78,7 @@ struct proto_hdr_template {
struct proto_desc {
const char *name;
enum proto_bases base;
+ enum nft_payload_csum_types checksum_type;
unsigned int checksum_key;
unsigned int protocol_key;
unsigned int length;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index cb1b7fe..606d97a 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -937,7 +937,7 @@ static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
expr->len / BITS_PER_BYTE);
if (csum_off) {
nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_CSUM_TYPE,
- NFT_PAYLOAD_CSUM_INET);
+ desc->checksum_type);
nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_CSUM_OFFSET,
csum_off / BITS_PER_BYTE);
}
diff --git a/src/proto.c b/src/proto.c
index 40ce590..8360abf 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -345,6 +345,7 @@ const struct proto_desc proto_icmp = {
.name = "icmp",
.base = PROTO_BASE_TRANSPORT_HDR,
.checksum_key = ICMPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[ICMPHDR_TYPE] = ICMPHDR_TYPE("type", &icmp_type_type, type),
[ICMPHDR_CODE] = ICMPHDR_TYPE("code", &icmp_code_type, code),
@@ -397,6 +398,7 @@ const struct proto_desc proto_igmp = {
.name = "igmp",
.base = PROTO_BASE_TRANSPORT_HDR,
.checksum_key = IGMPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[IGMPHDR_TYPE] = IGMPHDR_TYPE("type", &igmp_type_type, igmp_type),
[IGMPHDR_MRT] = IGMPHDR_FIELD("mrt", igmp_code),
@@ -417,6 +419,7 @@ const struct proto_desc proto_udp = {
.name = "udp",
.base = PROTO_BASE_TRANSPORT_HDR,
.checksum_key = UDPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[UDPHDR_SPORT] = INET_SERVICE("sport", struct udphdr, source),
[UDPHDR_DPORT] = INET_SERVICE("dport", struct udphdr, dest),
@@ -474,6 +477,7 @@ const struct proto_desc proto_tcp = {
.name = "tcp",
.base = PROTO_BASE_TRANSPORT_HDR,
.checksum_key = TCPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[TCPHDR_SPORT] = INET_SERVICE("sport", struct tcphdr, source),
[TCPHDR_DPORT] = INET_SERVICE("dport", struct tcphdr, dest),
@@ -553,6 +557,8 @@ const struct proto_desc proto_dccp = {
const struct proto_desc proto_sctp = {
.name = "sctp",
.base = PROTO_BASE_TRANSPORT_HDR,
+ .checksum_key = SCTPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_SCTP,
.templates = {
[SCTPHDR_SPORT] = INET_SERVICE("sport", struct sctphdr, source),
[SCTPHDR_DPORT] = INET_SERVICE("dport", struct sctphdr, dest),
@@ -650,6 +656,7 @@ const struct proto_desc proto_ip = {
.name = "ip",
.base = PROTO_BASE_NETWORK_HDR,
.checksum_key = IPHDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.protocols = {
PROTO_LINK(IPPROTO_ICMP, &proto_icmp),
PROTO_LINK(IPPROTO_IGMP, &proto_igmp),
@@ -746,6 +753,7 @@ const struct proto_desc proto_icmp6 = {
.name = "icmpv6",
.base = PROTO_BASE_TRANSPORT_HDR,
.checksum_key = ICMP6HDR_CHECKSUM,
+ .checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[ICMP6HDR_TYPE] = ICMP6HDR_TYPE("type", &icmp6_type_type, icmp6_type),
[ICMP6HDR_CODE] = ICMP6HDR_TYPE("code", &icmpv6_code_type, icmp6_code),
--
2.31.1

View File

@ -0,0 +1,233 @@
From 70dc225b23708c6ac96e2895488f3c6dea9e201d Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:28:27 +0100
Subject: [PATCH] proto: Fix ARP header field ordering
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1896334
Upstream Status: nftables commit f751753f92ea7
commit f751753f92ea76f582f7d5d1fef8b4d5677ba589
Author: Phil Sutter <phil@nwl.cc>
Date: Tue Nov 10 13:07:49 2020 +0100
proto: Fix ARP header field ordering
In ARP header, destination ether address sits between source IP and
destination IP addresses. Enum arp_hdr_fields had this wrong, which
in turn caused wrong ordering of entries in proto_arp->templates. When
expanding a combined payload expression, code assumes that template
entries are ordered by header offset, therefore the destination ether
address match was printed as raw if an earlier field was matched as
well:
| arp saddr ip 192.168.1.1 arp daddr ether 3e:d1:3f:d6:12:0b
was printed as:
| arp saddr ip 192.168.1.1 @nh,144,48 69068440080907
Note: Although strictly not necessary, reorder fields in
proto_arp->templates as well to match their actual ordering, just to
avoid confusion.
Fixes: 4b0f2a712b579 ("src: support for arp sender and target ethernet and IPv4 addresses")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
include/proto.h | 2 +-
src/proto.c | 2 +-
tests/py/arp/arp.t | 3 ++
tests/py/arp/arp.t.json | 56 +++++++++++++++++++++++++++++++
tests/py/arp/arp.t.json.output | 28 ++++++++++++++++
tests/py/arp/arp.t.payload | 10 ++++++
tests/py/arp/arp.t.payload.netdev | 14 ++++++++
7 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/include/proto.h b/include/proto.h
index 436cbe3..5a50059 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -184,8 +184,8 @@ enum arp_hdr_fields {
ARPHDR_PLN,
ARPHDR_OP,
ARPHDR_SADDR_ETHER,
- ARPHDR_DADDR_ETHER,
ARPHDR_SADDR_IP,
+ ARPHDR_DADDR_ETHER,
ARPHDR_DADDR_IP,
};
diff --git a/src/proto.c b/src/proto.c
index 8360abf..49c8c92 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -908,8 +908,8 @@ const struct proto_desc proto_arp = {
[ARPHDR_PLN] = ARPHDR_FIELD("plen", plen),
[ARPHDR_OP] = ARPHDR_TYPE("operation", &arpop_type, oper),
[ARPHDR_SADDR_ETHER] = ARPHDR_TYPE("saddr ether", &etheraddr_type, sha),
- [ARPHDR_DADDR_ETHER] = ARPHDR_TYPE("daddr ether", &etheraddr_type, tha),
[ARPHDR_SADDR_IP] = ARPHDR_TYPE("saddr ip", &ipaddr_type, spa),
+ [ARPHDR_DADDR_ETHER] = ARPHDR_TYPE("daddr ether", &etheraddr_type, tha),
[ARPHDR_DADDR_IP] = ARPHDR_TYPE("daddr ip", &ipaddr_type, tpa),
},
.format = {
diff --git a/tests/py/arp/arp.t b/tests/py/arp/arp.t
index 2540c0a..109d01d 100644
--- a/tests/py/arp/arp.t
+++ b/tests/py/arp/arp.t
@@ -61,4 +61,7 @@ arp daddr ip 4.3.2.1;ok
arp saddr ether aa:bb:cc:aa:bb:cc;ok
arp daddr ether aa:bb:cc:aa:bb:cc;ok
+arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee;ok
+arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1;ok;arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+
meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566;ok;iifname "invalid" arp htype 1 arp ptype ip arp hlen 6 arp plen 4 arp daddr ip 192.168.143.16 arp daddr ether set 11:22:33:44:55:66
diff --git a/tests/py/arp/arp.t.json b/tests/py/arp/arp.t.json
index 5f2f6cd..8508c17 100644
--- a/tests/py/arp/arp.t.json
+++ b/tests/py/arp/arp.t.json
@@ -901,6 +901,62 @@
}
]
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ }
+]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ }
+]
+
# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
[
{
diff --git a/tests/py/arp/arp.t.json.output b/tests/py/arp/arp.t.json.output
index b8507bf..afa75b2 100644
--- a/tests/py/arp/arp.t.json.output
+++ b/tests/py/arp/arp.t.json.output
@@ -66,6 +66,34 @@
}
]
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ }
+]
+
# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
[
{
diff --git a/tests/py/arp/arp.t.payload b/tests/py/arp/arp.t.payload
index 52c9932..f819853 100644
--- a/tests/py/arp/arp.t.payload
+++ b/tests/py/arp/arp.t.payload
@@ -307,3 +307,13 @@ arp test-arp input
[ payload load 6b @ network header + 18 => reg 1 ]
[ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+arp
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+arp
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
diff --git a/tests/py/arp/arp.t.payload.netdev b/tests/py/arp/arp.t.payload.netdev
index 667691f..f57610c 100644
--- a/tests/py/arp/arp.t.payload.netdev
+++ b/tests/py/arp/arp.t.payload.netdev
@@ -409,3 +409,17 @@ netdev test-netdev ingress
[ payload load 6b @ network header + 18 => reg 1 ]
[ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
--
2.31.1

View File

@ -0,0 +1,108 @@
From 26c4f15080663a12006abf8539ebf28bb223e6d9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:29:15 +0100
Subject: [PATCH] json: echo: Speedup seqnum_to_json()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1900565
Upstream Status: nftables commit 389a0e1edc89a
commit 389a0e1edc89a4048a272e569d3349b1d43bc567
Author: Phil Sutter <phil@nwl.cc>
Date: Fri Nov 20 20:01:59 2020 +0100
json: echo: Speedup seqnum_to_json()
Derek Dai reports:
"If there are a lot of command in JSON node, seqnum_to_json() will slow
down application (eg: firewalld) dramatically since it iterate whole
command list every time."
He sent a patch implementing a lookup table, but we can do better: Speed
this up by introducing a hash table to store the struct json_cmd_assoc
objects in, taking their netlink sequence number as key.
Quickly tested restoring a ruleset containing about 19k rules:
| # time ./before/nft -jeaf large_ruleset.json >/dev/null
| 4.85user 0.47system 0:05.48elapsed 97%CPU (0avgtext+0avgdata 69732maxresident)k
| 0inputs+0outputs (15major+16937minor)pagefaults 0swaps
| # time ./after/nft -jeaf large_ruleset.json >/dev/null
| 0.18user 0.44system 0:00.70elapsed 89%CPU (0avgtext+0avgdata 68484maxresident)k
| 0inputs+0outputs (15major+16645minor)pagefaults 0swaps
Bugzilla: https://bugzilla.netfilter.org/show_bug.cgi?id=1479
Reported-by: Derek Dai <daiderek@gmail.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_json.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/src/parser_json.c b/src/parser_json.c
index ddc694f..107dc38 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3646,42 +3646,50 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
}
struct json_cmd_assoc {
- struct json_cmd_assoc *next;
+ struct hlist_node hnode;
const struct cmd *cmd;
json_t *json;
};
-static struct json_cmd_assoc *json_cmd_list = NULL;
+#define CMD_ASSOC_HSIZE 512
+static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE];
static void json_cmd_assoc_free(void)
{
struct json_cmd_assoc *cur;
+ struct hlist_node *pos, *n;
+ int i;
- while (json_cmd_list) {
- cur = json_cmd_list;
- json_cmd_list = cur->next;
- free(cur);
+ for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
+ hlist_for_each_entry_safe(cur, pos, n,
+ &json_cmd_assoc_hash[i], hnode)
+ free(cur);
}
}
static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd)
{
struct json_cmd_assoc *new = xzalloc(sizeof *new);
+ int key = cmd->seqnum % CMD_ASSOC_HSIZE;
- new->next = json_cmd_list;
new->json = json;
new->cmd = cmd;
- json_cmd_list = new;
+
+ hlist_add_head(&new->hnode, &json_cmd_assoc_hash[key]);
}
static json_t *seqnum_to_json(const uint32_t seqnum)
{
- const struct json_cmd_assoc *cur;
+ int key = seqnum % CMD_ASSOC_HSIZE;
+ struct json_cmd_assoc *cur;
+ struct hlist_node *n;
- for (cur = json_cmd_list; cur; cur = cur->next) {
+
+ hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
if (cur->cmd->seqnum == seqnum)
return cur->json;
}
+
return NULL;
}
--
2.31.1

View File

@ -0,0 +1,116 @@
From 0dcfa1b0211fa50201d51d0f52869a8e2d93ba76 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 7 Dec 2020 18:29:15 +0100
Subject: [PATCH] json: Fix seqnum_to_json() functionality
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1900565
Upstream Status: nftables commit 299ec575faa6b
commit 299ec575faa6b070940b483dc517ecd883b9f1a4
Author: Phil Sutter <phil@nwl.cc>
Date: Wed Dec 2 23:07:11 2020 +0100
json: Fix seqnum_to_json() functionality
Introduction of json_cmd_assoc_hash missed that by the time the hash
table insert happens, the struct cmd object's 'seqnum' field which is
used as key is not initialized yet. This doesn't happen until
nft_netlink() prepares the batch object which records the lowest seqnum.
Therefore push all json_cmd_assoc objects into a temporary list until
the first lookup happens. At this time, all referenced cmd objects have
their seqnum set and the list entries can be moved into the hash table
for fast lookups.
To expose such problems in the future, make json_events_cb() emit an
error message if the passed message has a handle but no assoc entry is
found for its seqnum.
Fixes: 389a0e1edc89a ("json: echo: Speedup seqnum_to_json()")
Cc: Derek Dai <daiderek@gmail.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_json.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/parser_json.c b/src/parser_json.c
index 107dc38..785f0e7 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3646,6 +3646,7 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
}
struct json_cmd_assoc {
+ struct json_cmd_assoc *next;
struct hlist_node hnode;
const struct cmd *cmd;
json_t *json;
@@ -3653,6 +3654,7 @@ struct json_cmd_assoc {
#define CMD_ASSOC_HSIZE 512
static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE];
+static struct json_cmd_assoc *json_cmd_assoc_list;
static void json_cmd_assoc_free(void)
{
@@ -3660,6 +3662,12 @@ static void json_cmd_assoc_free(void)
struct hlist_node *pos, *n;
int i;
+ while (json_cmd_assoc_list) {
+ cur = json_cmd_assoc_list->next;
+ free(json_cmd_assoc_list);
+ json_cmd_assoc_list = cur;
+ }
+
for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
hlist_for_each_entry_safe(cur, pos, n,
&json_cmd_assoc_hash[i], hnode)
@@ -3670,21 +3678,29 @@ static void json_cmd_assoc_free(void)
static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd)
{
struct json_cmd_assoc *new = xzalloc(sizeof *new);
- int key = cmd->seqnum % CMD_ASSOC_HSIZE;
new->json = json;
new->cmd = cmd;
+ new->next = json_cmd_assoc_list;
- hlist_add_head(&new->hnode, &json_cmd_assoc_hash[key]);
+ json_cmd_assoc_list = new;
}
static json_t *seqnum_to_json(const uint32_t seqnum)
{
- int key = seqnum % CMD_ASSOC_HSIZE;
struct json_cmd_assoc *cur;
struct hlist_node *n;
+ int key;
+ while (json_cmd_assoc_list) {
+ cur = json_cmd_assoc_list;
+ json_cmd_assoc_list = cur->next;
+ key = cur->cmd->seqnum % CMD_ASSOC_HSIZE;
+ hlist_add_head(&cur->hnode, &json_cmd_assoc_hash[key]);
+ }
+
+ key = seqnum % CMD_ASSOC_HSIZE;
hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
if (cur->cmd->seqnum == seqnum)
return cur->json;
@@ -3865,8 +3881,11 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
return MNL_CB_OK;
json = seqnum_to_json(nlh->nlmsg_seq);
- if (!json)
+ if (!json) {
+ json_echo_error(monh, "No JSON command found with seqnum %lu\n",
+ nlh->nlmsg_seq);
return MNL_CB_OK;
+ }
tmp = json_object_get(json, "add");
if (!tmp)
--
2.31.1

View File

@ -0,0 +1,47 @@
From b7964157c40066f09411ac52547acb07d1966aee Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 12 Jan 2021 15:49:43 +0100
Subject: [PATCH] json: don't leave dangling pointers on hlist
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1900565
Upstream Status: nftables commit 48917d876d51c
commit 48917d876d51cd6ba5bff07172acef05c9e12474
Author: Florian Westphal <fw@strlen.de>
Date: Mon Dec 14 16:53:29 2020 +0100
json: don't leave dangling pointers on hlist
unshare -n tests/json_echo/run-test.py
[..]
Adding chain c
free(): double free detected in tcache 2
Aborted (core dumped)
The element must be deleted from the hlist prior to freeing it.
Fixes: 389a0e1edc89a ("json: echo: Speedup seqnum_to_json()")
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/parser_json.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/parser_json.c b/src/parser_json.c
index 785f0e7..986f128 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3670,8 +3670,10 @@ static void json_cmd_assoc_free(void)
for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
hlist_for_each_entry_safe(cur, pos, n,
- &json_cmd_assoc_hash[i], hnode)
+ &json_cmd_assoc_hash[i], hnode) {
+ hlist_del(&cur->hnode);
free(cur);
+ }
}
}
--
2.31.1

View File

@ -0,0 +1,46 @@
From 2b4da3af37ac10d96650da1b8642f82a3aa92e30 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Sat, 20 Feb 2021 09:52:59 +0100
Subject: [PATCH] json: init parser state for every new buffer/file
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1930873
Upstream Status: nftables commit 267338ec39234
commit 267338ec392346ef55ed51509e5f8e8354d6c19a
Author: Eric Garver <eric@garver.life>
Date: Fri Feb 19 10:11:26 2021 -0500
json: init parser state for every new buffer/file
Otherwise invalid error states cause subsequent json parsing to fail
when it should not.
Signed-off-by: Eric Garver <eric@garver.life>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_json.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/parser_json.c b/src/parser_json.c
index 986f128..662bb4b 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3777,6 +3777,7 @@ int nft_parse_json_buffer(struct nft_ctx *nft, const char *buf,
};
int ret;
+ parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_loads(buf, 0, NULL);
if (!nft->json_root)
return -EINVAL;
@@ -3805,6 +3806,7 @@ int nft_parse_json_filename(struct nft_ctx *nft, const char *filename,
json_error_t err;
int ret;
+ parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_load_file(filename, 0, &err);
if (!nft->json_root)
return -EINVAL;
--
2.31.1

View File

@ -0,0 +1,465 @@
From f9dca1704ce66be31eceac4d7317b825269b3d07 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 2 Mar 2021 17:06:06 +0100
Subject: [PATCH] tests: Disable tests known to fail on RHEL8
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
Upstream Status: RHEL-only
RHEL8 kernel does not support:
- ct timeout or expectation objects
- synproxy
- flowtables in families other than inet
- meta time
- bridge family-specific meta expressions (e.g. ibrvproto, ibrpvid)
- socket mark
- osf
- delete set elements from packet path
- update stateful objects
- explicitly setting set element expiration (commit 79ebb5bb4e3)
- flushing chains and deleting referenced objects in the same
transaction (upstream commits with 'bogus EBUSY' in subject)
Disable all related tests to make the testsuites pass.
---
tests/monitor/testcases/object.t | 14 +++---
tests/py/any/meta.t | 36 +++++++--------
tests/py/bridge/meta.t | 8 ++--
tests/py/inet/osf.t | 24 +++++-----
tests/py/inet/socket.t | 2 +-
tests/py/inet/synproxy.t | 12 ++---
tests/py/ip/objects.t | 46 +++++++++----------
tests/py/ip6/sets.t | 2 +-
.../flowtable/0002create_flowtable_0 | 8 ++--
.../testcases/flowtable/0003add_after_flush_0 | 8 ++--
.../flowtable/0004delete_after_add_0 | 6 +--
.../testcases/flowtable/0005delete_in_use_1 | 10 ++--
tests/shell/testcases/flowtable/0007prio_0 | 6 +--
tests/shell/testcases/flowtable/0008prio_1 | 4 +-
.../flowtable/0009deleteafterflush_0 | 12 ++---
tests/shell/testcases/listing/0013objects_0 | 2 +
.../testcases/nft-f/0017ct_timeout_obj_0 | 2 +
.../testcases/nft-f/0018ct_expectation_obj_0 | 2 +
....nft => 0017ct_timeout_obj_0.nft.disabled} | 0
.../optionals/update_object_handles_0 | 2 +
.../sets/0036add_set_element_expiration_0 | 2 +
tests/shell/testcases/transactions/0046set_0 | 2 +
22 files changed, 111 insertions(+), 99 deletions(-)
rename tests/shell/testcases/nft-f/dumps/{0017ct_timeout_obj_0.nft => 0017ct_timeout_obj_0.nft.disabled} (100%)
diff --git a/tests/monitor/testcases/object.t b/tests/monitor/testcases/object.t
index 2afe33c..1b30384 100644
--- a/tests/monitor/testcases/object.t
+++ b/tests/monitor/testcases/object.t
@@ -37,10 +37,10 @@ I delete ct helper ip t cth
O -
J {"delete": {"ct helper": {"family": "ip", "name": "cth", "table": "t", "handle": 0, "type": "sip", "protocol": "tcp", "l3proto": "ip"}}}
-I add ct timeout ip t ctt { protocol udp; l3proto ip; policy = { unreplied : 15, replied : 12 }; }
-O -
-J {"add": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
-
-I delete ct timeout ip t ctt
-O -
-J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
+# I add ct timeout ip t ctt { protocol udp; l3proto ip; policy = { unreplied : 15, replied : 12 }; }
+# O -
+# J {"add": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
+#
+# I delete ct timeout ip t ctt
+# O -
+# J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index 327f973..241b466 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -204,21 +204,21 @@ meta iif . meta oif vmap { "lo" . "lo" : drop };ok;iif . oif vmap { "lo" . "lo"
meta random eq 1;ok;meta random 1
meta random gt 1000000;ok;meta random > 1000000
-meta time "1970-05-23 21:07:14" drop;ok
-meta time 12341234 drop;ok;meta time "1970-05-23 22:07:14" drop
-meta time "2019-06-21 17:00:00" drop;ok
-meta time "2019-07-01 00:00:00" drop;ok
-meta time "2019-07-01 00:01:00" drop;ok
-meta time "2019-07-01 00:00:01" drop;ok
-meta day "Saturday" drop;ok
-meta day 6 drop;ok;meta day "Saturday" drop
-meta day "Satturday" drop;fail
-meta hour "17:00" drop;ok
-meta hour "17:00:00" drop;ok;meta hour "17:00" drop
-meta hour "17:00:01" drop;ok
-meta hour "00:00" drop;ok
-meta hour "00:01" drop;ok
-
-meta time "meh";fail
-meta hour "24:00" drop;fail
-meta day 7 drop;fail
+- meta time "1970-05-23 21:07:14" drop;ok
+- meta time 12341234 drop;ok;meta time "1970-05-23 22:07:14" drop
+- meta time "2019-06-21 17:00:00" drop;ok
+- meta time "2019-07-01 00:00:00" drop;ok
+- meta time "2019-07-01 00:01:00" drop;ok
+- meta time "2019-07-01 00:00:01" drop;ok
+- meta day "Saturday" drop;ok
+- meta day 6 drop;ok;meta day "Saturday" drop
+- meta day "Satturday" drop;fail
+- meta hour "17:00" drop;ok
+- meta hour "17:00:00" drop;ok;meta hour "17:00" drop
+- meta hour "17:00:01" drop;ok
+- meta hour "00:00" drop;ok
+- meta hour "00:01" drop;ok
+
+- meta time "meh";fail
+- meta hour "24:00" drop;fail
+- meta day 7 drop;fail
diff --git a/tests/py/bridge/meta.t b/tests/py/bridge/meta.t
index 94525f2..9f55cde 100644
--- a/tests/py/bridge/meta.t
+++ b/tests/py/bridge/meta.t
@@ -2,7 +2,7 @@
*bridge;test-bridge;input
-meta obrname "br0";ok
-meta ibrname "br0";ok
-meta ibrvproto vlan;ok
-meta ibrpvid 100;ok
+- meta obrname "br0";ok
+- meta ibrname "br0";ok
+- meta ibrvproto vlan;ok
+- meta ibrpvid 100;ok
diff --git a/tests/py/inet/osf.t b/tests/py/inet/osf.t
index c828541..5191e72 100644
--- a/tests/py/inet/osf.t
+++ b/tests/py/inet/osf.t
@@ -4,15 +4,15 @@
*ip6;osfip6;osfchain
*inet;osfinet;osfchain
-osf name "Linux";ok
-osf ttl loose name "Linux";ok
-osf ttl skip name "Linux";ok
-osf ttl skip version "Linux:3.0";ok
-osf ttl skip version "morethan:sixteenbytes";fail
-osf ttl nottl name "Linux";fail
-osf name "morethansixteenbytes";fail
-osf name ;fail
-osf name { "Windows", "MacOs" };ok
-osf version { "Windows:XP", "MacOs:Sierra" };ok
-ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 };ok
-ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 };ok
+- osf name "Linux";ok
+- osf ttl loose name "Linux";ok
+- osf ttl skip name "Linux";ok
+- osf ttl skip version "Linux:3.0";ok
+- osf ttl skip version "morethan:sixteenbytes";fail
+- osf ttl nottl name "Linux";fail
+- osf name "morethansixteenbytes";fail
+- osf name ;fail
+- osf name { "Windows", "MacOs" };ok
+- osf version { "Windows:XP", "MacOs:Sierra" };ok
+- ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 };ok
+- ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 };ok
diff --git a/tests/py/inet/socket.t b/tests/py/inet/socket.t
index 91846e8..dbc0554 100644
--- a/tests/py/inet/socket.t
+++ b/tests/py/inet/socket.t
@@ -8,4 +8,4 @@ socket transparent 0;ok
socket transparent 1;ok
socket transparent 2;fail
-socket mark 0x00000005;ok
+- socket mark 0x00000005;ok
diff --git a/tests/py/inet/synproxy.t b/tests/py/inet/synproxy.t
index 55a05e1..9c58239 100644
--- a/tests/py/inet/synproxy.t
+++ b/tests/py/inet/synproxy.t
@@ -4,10 +4,10 @@
*ip6;synproxyip6;synproxychain
*inet;synproxyinet;synproxychain
-synproxy;ok
-synproxy mss 1460 wscale 7;ok
-synproxy mss 1460 wscale 5 timestamp sack-perm;ok
-synproxy timestamp sack-perm;ok
-synproxy timestamp;ok
-synproxy sack-perm;ok
+-synproxy;ok
+-synproxy mss 1460 wscale 7;ok
+-synproxy mss 1460 wscale 5 timestamp sack-perm;ok
+-synproxy timestamp sack-perm;ok
+-synproxy timestamp;ok
+-synproxy sack-perm;ok
diff --git a/tests/py/ip/objects.t b/tests/py/ip/objects.t
index 4fcde7c..06e94f1 100644
--- a/tests/py/ip/objects.t
+++ b/tests/py/ip/objects.t
@@ -33,26 +33,26 @@ ip saddr 192.168.1.3 limit name "lim1";ok
ip saddr 192.168.1.3 limit name "lim3";fail
limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"};ok
-# ct timeout
-%cttime1 type ct timeout { protocol tcp; policy = { established:122 } ;};ok
-%cttime2 type ct timeout { protocol udp; policy = { syn_sent:122 } ;};fail
-%cttime3 type ct timeout { protocol tcp; policy = { established:132, close:16, close_wait:16 } ; l3proto ip ;};ok
-%cttime4 type ct timeout { protocol udp; policy = { replied:14, unreplied:19 } ;};ok
-%cttime5 type ct timeout {protocol tcp; policy = { estalbished:100 } ;};fail
-
-ct timeout set "cttime1";ok
-
-# ct expectation
-%ctexpect1 type ct expectation { protocol tcp; dport 1234; timeout 2m; size 12; };ok
-%ctexpect2 type ct expectation { protocol udp; };fail
-%ctexpect3 type ct expectation { protocol tcp; dport 4321; };fail
-%ctexpect4 type ct expectation { protocol tcp; dport 4321; timeout 2m; };fail
-%ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok
-
-ct expectation set "ctexpect1";ok
-
-# synproxy
-%synproxy1 type synproxy mss 1460 wscale 7;ok
-%synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok
-
-synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
+# # ct timeout
+# %cttime1 type ct timeout { protocol tcp; policy = { established:122 } ;};ok
+# %cttime2 type ct timeout { protocol udp; policy = { syn_sent:122 } ;};fail
+# %cttime3 type ct timeout { protocol tcp; policy = { established:132, close:16, close_wait:16 } ; l3proto ip ;};ok
+# %cttime4 type ct timeout { protocol udp; policy = { replied:14, unreplied:19 } ;};ok
+# %cttime5 type ct timeout {protocol tcp; policy = { estalbished:100 } ;};fail
+#
+# ct timeout set "cttime1";ok
+
+# # ct expectation
+# %ctexpect1 type ct expectation { protocol tcp; dport 1234; timeout 2m; size 12; };ok
+# %ctexpect2 type ct expectation { protocol udp; };fail
+# %ctexpect3 type ct expectation { protocol tcp; dport 4321; };fail
+# %ctexpect4 type ct expectation { protocol tcp; dport 4321; timeout 2m; };fail
+# %ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok
+#
+# ct expectation set "ctexpect1";ok
+
+# # synproxy
+# %synproxy1 type synproxy mss 1460 wscale 7;ok
+# %synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok
+#
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
diff --git a/tests/py/ip6/sets.t b/tests/py/ip6/sets.t
index add82eb..cc43aca 100644
--- a/tests/py/ip6/sets.t
+++ b/tests/py/ip6/sets.t
@@ -40,4 +40,4 @@ ip6 saddr != @set33 drop;fail
!set5 type ipv6_addr . ipv6_addr;ok
ip6 saddr . ip6 daddr @set5 drop;ok
add @set5 { ip6 saddr . ip6 daddr };ok
-delete @set5 { ip6 saddr . ip6 daddr };ok
+- delete @set5 { ip6 saddr . ip6 daddr };ok
diff --git a/tests/shell/testcases/flowtable/0002create_flowtable_0 b/tests/shell/testcases/flowtable/0002create_flowtable_0
index 4c85c3f..8b80e34 100755
--- a/tests/shell/testcases/flowtable/0002create_flowtable_0
+++ b/tests/shell/testcases/flowtable/0002create_flowtable_0
@@ -1,12 +1,12 @@
#!/bin/bash
set -e
-$NFT add table t
-$NFT add flowtable t f { hook ingress priority 10 \; devices = { lo }\; }
-if $NFT create flowtable t f { hook ingress priority 10 \; devices = { lo }\; } 2>/dev/null ; then
+$NFT add table inet t
+$NFT add flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; }
+if $NFT create flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; } 2>/dev/null ; then
echo "E: flowtable creation not failing on existing set" >&2
exit 1
fi
-$NFT add flowtable t f { hook ingress priority 10 \; devices = { lo }\; }
+$NFT add flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; }
exit 0
diff --git a/tests/shell/testcases/flowtable/0003add_after_flush_0 b/tests/shell/testcases/flowtable/0003add_after_flush_0
index 481c7ed..b4243bc 100755
--- a/tests/shell/testcases/flowtable/0003add_after_flush_0
+++ b/tests/shell/testcases/flowtable/0003add_after_flush_0
@@ -1,8 +1,8 @@
#!/bin/bash
set -e
-$NFT add table x
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
+$NFT add table inet x
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
$NFT flush ruleset
-$NFT add table x
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
+$NFT add table inet x
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
diff --git a/tests/shell/testcases/flowtable/0004delete_after_add_0 b/tests/shell/testcases/flowtable/0004delete_after_add_0
index 8d9a842..4618595 100755
--- a/tests/shell/testcases/flowtable/0004delete_after_add_0
+++ b/tests/shell/testcases/flowtable/0004delete_after_add_0
@@ -1,6 +1,6 @@
#!/bin/bash
set -e
-$NFT add table x
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
-$NFT delete flowtable x y
+$NFT add table inet x
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
+$NFT delete flowtable inet x y
diff --git a/tests/shell/testcases/flowtable/0005delete_in_use_1 b/tests/shell/testcases/flowtable/0005delete_in_use_1
index ef52620..eda1fb9 100755
--- a/tests/shell/testcases/flowtable/0005delete_in_use_1
+++ b/tests/shell/testcases/flowtable/0005delete_in_use_1
@@ -1,11 +1,11 @@
#!/bin/bash
set -e
-$NFT add table x
-$NFT add chain x x
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
-$NFT add rule x x flow add @y
+$NFT add table inet x
+$NFT add chain inet x x
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
+$NFT add rule inet x x flow add @y
-$NFT delete flowtable x y || exit 0
+$NFT delete flowtable inet x y || exit 0
echo "E: delete flowtable in use"
exit 1
diff --git a/tests/shell/testcases/flowtable/0007prio_0 b/tests/shell/testcases/flowtable/0007prio_0
index 49bbcac..0ea262f 100755
--- a/tests/shell/testcases/flowtable/0007prio_0
+++ b/tests/shell/testcases/flowtable/0007prio_0
@@ -15,10 +15,10 @@ format_offset () {
fi
}
-$NFT add table t
+$NFT add table inet t
for offset in -11 -10 0 10 11
do
- $NFT add flowtable t f "{ hook ingress priority filter `format_offset $offset`; devices = { lo }; }"
- $NFT delete flowtable t f
+ $NFT add flowtable inet t f "{ hook ingress priority filter `format_offset $offset`; devices = { lo }; }"
+ $NFT delete flowtable inet t f
done
diff --git a/tests/shell/testcases/flowtable/0008prio_1 b/tests/shell/testcases/flowtable/0008prio_1
index 48953d7..0d8cdff 100755
--- a/tests/shell/testcases/flowtable/0008prio_1
+++ b/tests/shell/testcases/flowtable/0008prio_1
@@ -1,9 +1,9 @@
#!/bin/bash
-$NFT add table t
+$NFT add table inet t
for prioname in raw mangle dstnar security srcnat out dummy
do
- $NFT add flowtable t f { hook ingress priority $prioname \; devices = { lo }\; }
+ $NFT add flowtable inet t f { hook ingress priority $prioname \; devices = { lo }\; }
if (($? == 0))
then
echo "E: $prioname should not be a valid priority name for flowtables" >&2
diff --git a/tests/shell/testcases/flowtable/0009deleteafterflush_0 b/tests/shell/testcases/flowtable/0009deleteafterflush_0
index 2cda563..061e22e 100755
--- a/tests/shell/testcases/flowtable/0009deleteafterflush_0
+++ b/tests/shell/testcases/flowtable/0009deleteafterflush_0
@@ -1,9 +1,9 @@
#!/bin/bash
set -e
-$NFT add table x
-$NFT add chain x y
-$NFT add flowtable x f { hook ingress priority 0\; devices = { lo }\;}
-$NFT add rule x y flow add @f
-$NFT flush chain x y
-$NFT delete flowtable x f
+$NFT add table inet x
+$NFT add chain inet x y
+$NFT add flowtable inet x f { hook ingress priority 0\; devices = { lo }\;}
+$NFT add rule inet x y flow add @f
+$NFT flush chain inet x y
+$NFT delete flowtable inet x f
diff --git a/tests/shell/testcases/listing/0013objects_0 b/tests/shell/testcases/listing/0013objects_0
index 4d39143..130d02c 100755
--- a/tests/shell/testcases/listing/0013objects_0
+++ b/tests/shell/testcases/listing/0013objects_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
# list table with all objects and chains
EXPECTED="table ip test {
diff --git a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
index 4f40779..e0f9e44 100755
--- a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
+++ b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
EXPECTED='table ip filter {
ct timeout cttime{
protocol tcp
diff --git a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
index 4f9872f..f518cf7 100755
--- a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
+++ b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
EXPECTED='table ip filter {
ct expectation ctexpect{
protocol tcp
diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled
similarity index 100%
rename from tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft
rename to tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled
diff --git a/tests/shell/testcases/optionals/update_object_handles_0 b/tests/shell/testcases/optionals/update_object_handles_0
index 8b12b8c..e11b4e7 100755
--- a/tests/shell/testcases/optionals/update_object_handles_0
+++ b/tests/shell/testcases/optionals/update_object_handles_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
set -e
$NFT add table test-ip
$NFT add counter test-ip traffic-counter
diff --git a/tests/shell/testcases/sets/0036add_set_element_expiration_0 b/tests/shell/testcases/sets/0036add_set_element_expiration_0
index 51ed0f2..043bb8f 100755
--- a/tests/shell/testcases/sets/0036add_set_element_expiration_0
+++ b/tests/shell/testcases/sets/0036add_set_element_expiration_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
set -e
RULESET="add table ip x
diff --git a/tests/shell/testcases/transactions/0046set_0 b/tests/shell/testcases/transactions/0046set_0
index 172e24d..1b24964 100755
--- a/tests/shell/testcases/transactions/0046set_0
+++ b/tests/shell/testcases/transactions/0046set_0
@@ -1,5 +1,7 @@
#!/bin/bash
+exit 0
+
RULESET='add table ip filter
add chain ip filter group_7933
add map ip filter group_7933 { type ipv4_addr : classid; flags interval; }
--
2.31.1

View File

@ -0,0 +1,41 @@
From 1490609a3d82e494168a390b34094bacc5e83c02 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 18 May 2021 18:06:50 +0200
Subject: [PATCH] monitor: Fix for use after free when printing map elements
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
Upstream Status: nftables commit 02174ffad484d
commit 02174ffad484d9711678e5d415c32307efc39857
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Jan 9 17:43:11 2020 +0100
monitor: Fix for use after free when printing map elements
When populating the dummy set, 'data' field must be cloned just like
'key' field.
Fixes: 343a51702656a ("src: store expr, not dtype to track data in sets")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/monitor.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/monitor.c b/src/monitor.c
index 7927b6f..142cc92 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -401,7 +401,8 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
*/
dummyset = set_alloc(monh->loc);
dummyset->key = expr_clone(set->key);
- dummyset->data = set->data;
+ if (set->data)
+ dummyset->data = expr_clone(set->data);
dummyset->flags = set->flags;
dummyset->init = set_expr_alloc(monh->loc, set);
--
2.31.1

View File

@ -0,0 +1,44 @@
From 4ee4ed8d54a8b9f0f0a2b195b3b95b892e4e79a3 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 18 May 2021 18:06:50 +0200
Subject: [PATCH] tests: monitor: use correct $nft value in EXIT trap
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
Upstream Status: nftables commit 990cbbf75c40b
commit 990cbbf75c40b92e6d6dc66721dfbedf33cacf8f
Author: Štěpán Němec <snemec@redhat.com>
Date: Wed Jan 27 15:02:03 2021 +0100
tests: monitor: use correct $nft value in EXIT trap
With double quotes, $nft was being expanded to the default value even
in presence of the -H option.
Signed-off-by: Štěpán Němec <snemec@redhat.com>
Helped-by: Tomáš Doležal <todoleza@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
tests/monitor/run-tests.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh
index ffb833a..c1cacb4 100755
--- a/tests/monitor/run-tests.sh
+++ b/tests/monitor/run-tests.sh
@@ -19,7 +19,7 @@ if [ ! -d $testdir ]; then
echo "Failed to create test directory" >&2
exit 1
fi
-trap "rm -rf $testdir; $nft flush ruleset" EXIT
+trap 'rm -rf $testdir; $nft flush ruleset' EXIT
command_file=$(mktemp -p $testdir)
output_file=$(mktemp -p $testdir)
--
2.31.1

View File

@ -0,0 +1,57 @@
From 805fe6f5c9c8f2af78d8e94bd6b5c33724df3c80 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 18 May 2021 18:16:21 +0200
Subject: [PATCH] evaluate: Reject quoted strings containing only wildcard
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1818117
Upstream Status: nftables commit 032c9f745c6da
commit 032c9f745c6daab8c27176a95963b1c32b0a5d12
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Sep 24 17:38:45 2020 +0200
evaluate: Reject quoted strings containing only wildcard
Fix for an assertion fail when trying to match against an all-wildcard
interface name:
| % nft add rule t c iifname '"*"'
| nft: expression.c:402: constant_expr_alloc: Assertion `(((len) + (8) - 1) / (8)) > 0' failed.
| zsh: abort nft add rule t c iifname '"*"'
Fix this by detecting the string in expr_evaluate_string() and returning
an error message:
| % nft add rule t c iifname '"*"'
| Error: All-wildcard strings are not supported
| add rule t c iifname "*"
| ^^^
While being at it, drop the 'datalen >= 1' clause from the following
conditional as together with the added check for 'datalen == 0', all
possible other values have been caught already.
---
src/evaluate.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index a966ed4..0181750 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -321,8 +321,11 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp)
return 0;
}
- if (datalen >= 1 &&
- data[datalen - 1] == '\\') {
+ if (datalen == 0)
+ return expr_error(ctx->msgs, expr,
+ "All-wildcard strings are not supported");
+
+ if (data[datalen - 1] == '\\') {
char unescaped_str[data_len];
memset(unescaped_str, 0, sizeof(unescaped_str));
--
2.31.1

View File

@ -0,0 +1,64 @@
From 64f34f34acedad6cce70f2dd91c82a814d4ffe34 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 19 May 2021 18:03:43 +0200
Subject: [PATCH] src: Support odd-sized payload matches
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1934926
Upstream Status: nftables commit 8a927c56d83ed
commit 8a927c56d83ed0f78785011bd92a53edc25a0ca0
Author: Phil Sutter <phil@nwl.cc>
Date: Tue Oct 27 17:05:25 2020 +0100
src: Support odd-sized payload matches
When expanding a payload match, don't disregard oversized templates at
the right offset. A more flexible user may extract less bytes from the
packet if only parts of a field are interesting, e.g. only the prefix of
source/destination address. Support that by using the template, but fix
the length. Later when creating a relational expression for it, detect
the unusually small payload expression length and turn the RHS value
into a prefix expression.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/netlink_delinearize.c | 6 ++++++
src/payload.c | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 88dbd5a..8bdee12 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1577,6 +1577,12 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
tmp = constant_expr_splice(right, left->len);
expr_set_type(tmp, left->dtype, left->byteorder);
+ if (left->payload.tmpl && (left->len < left->payload.tmpl->len)) {
+ mpz_lshift_ui(tmp->value, left->payload.tmpl->len - left->len);
+ tmp->len = left->payload.tmpl->len;
+ tmp = prefix_expr_alloc(&tmp->location, tmp, left->len);
+ }
+
nexpr = relational_expr_alloc(&expr->location, expr->op,
left, tmp);
if (expr->op == OP_EQ)
diff --git a/src/payload.c b/src/payload.c
index 3576400..45280ef 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -746,6 +746,11 @@ void payload_expr_expand(struct list_head *list, struct expr *expr,
expr->payload.offset += tmpl->len;
if (expr->len == 0)
return;
+ } else if (expr->len > 0) {
+ new = payload_expr_alloc(&expr->location, desc, i);
+ new->len = expr->len;
+ list_add_tail(&new->list, list);
+ return;
} else
break;
}
--
2.31.1

View File

@ -0,0 +1,241 @@
From 6fb6d8f15a82b3348184f6950a436becb06931cb Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 19 May 2021 18:03:43 +0200
Subject: [PATCH] src: Optimize prefix matches on byte-boundaries
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1934926
Upstream Status: nftables commit 25338cdb6c77a
Conflicts: There is a hidden dependency on commit ee4391d0ac1e7 ("nat:
transform range to prefix expression when possible").
Backport only the single chunk required to keep prefix
parsing intact to avoid having to backport 9599d9d25a6b3
("src: NAT support for intervals in maps") as a dependency
which is clearly oversized for the sake of this purpose.
commit 25338cdb6c77aa2f0977afbbb612571c9d325213
Author: Phil Sutter <phil@nwl.cc>
Date: Tue Oct 27 17:33:15 2020 +0100
src: Optimize prefix matches on byte-boundaries
If a prefix expression's length is on a byte-boundary, it is sufficient
to just reduce the length passed to "cmp" expression. No need for
explicit bitwise modification of data on LHS. The relevant code is
already there, used for string prefix matches. There is one exception
though, namely zero-length prefixes: Kernel doesn't accept zero-length
"cmp" expressions, so keep them in the old code-path for now.
This patch depends upon the previous one to correctly parse odd-sized
payload matches but has to extend support for non-payload LHS as well.
In practice, this is needed for "ct" expressions as they allow matching
against IP address prefixes, too.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/netlink_delinearize.c | 8 ++++++--
src/netlink_linearize.c | 4 +++-
tests/py/ip/ct.t.payload | 4 ----
tests/py/ip/ip.t.payload | 6 ++----
tests/py/ip/ip.t.payload.bridge | 6 ++----
tests/py/ip/ip.t.payload.inet | 6 ++----
tests/py/ip/ip.t.payload.netdev | 6 ++----
tests/py/ip6/ip6.t.payload.inet | 5 ++---
tests/py/ip6/ip6.t.payload.ip6 | 5 ++---
9 files changed, 21 insertions(+), 29 deletions(-)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 8bdee12..157a473 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -291,8 +291,9 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
if (left->len > right->len &&
expr_basetype(left) != &string_type) {
- netlink_error(ctx, loc, "Relational expression size mismatch");
- goto err_free;
+ mpz_lshift_ui(right->value, left->len - right->len);
+ right = prefix_expr_alloc(loc, right, right->len);
+ right->prefix->len = left->len;
} else if (left->len > 0 && left->len < right->len) {
expr_free(left);
left = netlink_parse_concat_expr(ctx, loc, sreg, right->len);
@@ -2164,6 +2165,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
expr_postprocess(ctx, &expr->left);
expr_postprocess(ctx, &expr->right);
break;
+ case EXPR_PREFIX:
+ expr_postprocess(ctx, &expr->prefix);
+ break;
case EXPR_SET_ELEM:
expr_postprocess(ctx, &expr->key);
break;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 606d97a..25be634 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -501,7 +501,9 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
return netlink_gen_flagcmp(ctx, expr, dreg);
case EXPR_PREFIX:
sreg = get_register(ctx, expr->left);
- if (expr_basetype(expr->left)->type != TYPE_STRING) {
+ if (expr_basetype(expr->left)->type != TYPE_STRING &&
+ (!expr->right->prefix_len ||
+ expr->right->prefix_len % BITS_PER_BYTE)) {
len = div_round_up(expr->right->len, BITS_PER_BYTE);
netlink_gen_expr(ctx, expr->left, sreg);
right = netlink_gen_prefix(ctx, expr, sreg);
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index d5faed4..a7e08f9 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -21,25 +21,21 @@ ip test-ip4 output
# ct original ip saddr 192.168.1.0/24
ip test-ip4 output
[ ct load src_ip => reg 1 , dir original ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct reply ip saddr 192.168.1.0/24
ip test-ip4 output
[ ct load src_ip => reg 1 , dir reply ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct original ip daddr 192.168.1.0/24
ip test-ip4 output
[ ct load dst_ip => reg 1 , dir original ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct reply ip daddr 192.168.1.0/24
ip test-ip4 output
[ ct load dst_ip => reg 1 , dir reply ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct l3proto ipv4
diff --git a/tests/py/ip/ip.t.payload b/tests/py/ip/ip.t.payload
index d627b22..825c0f0 100644
--- a/tests/py/ip/ip.t.payload
+++ b/tests/py/ip/ip.t.payload
@@ -358,14 +358,12 @@ ip test-ip4 input
# ip saddr 192.168.2.0/24
ip test-ip4 input
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp eq reg 1 0x0002a8c0 ]
# ip saddr != 192.168.2.0/24
ip test-ip4 input
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp neq reg 1 0x0002a8c0 ]
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
diff --git a/tests/py/ip/ip.t.payload.bridge b/tests/py/ip/ip.t.payload.bridge
index 91a4fde..e958a5b 100644
--- a/tests/py/ip/ip.t.payload.bridge
+++ b/tests/py/ip/ip.t.payload.bridge
@@ -466,16 +466,14 @@ bridge test-bridge input
bridge test-bridge input
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp eq reg 1 0x0002a8c0 ]
# ip saddr != 192.168.2.0/24
bridge test-bridge input
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp neq reg 1 0x0002a8c0 ]
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
diff --git a/tests/py/ip/ip.t.payload.inet b/tests/py/ip/ip.t.payload.inet
index b9cb28a..6501473 100644
--- a/tests/py/ip/ip.t.payload.inet
+++ b/tests/py/ip/ip.t.payload.inet
@@ -466,16 +466,14 @@ inet test-inet input
inet test-inet input
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp eq reg 1 0x0002a8c0 ]
# ip saddr != 192.168.2.0/24
inet test-inet input
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp neq reg 1 0x0002a8c0 ]
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
diff --git a/tests/py/ip/ip.t.payload.netdev b/tests/py/ip/ip.t.payload.netdev
index 588e5ca..58ae358 100644
--- a/tests/py/ip/ip.t.payload.netdev
+++ b/tests/py/ip/ip.t.payload.netdev
@@ -379,16 +379,14 @@ netdev test-netdev ingress
netdev test-netdev ingress
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp eq reg 1 0x0002a8c0 ]
# ip saddr != 192.168.2.0/24
netdev test-netdev ingress
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
[ cmp neq reg 1 0x0002a8c0 ]
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
index d015c8e..ffc9b9f 100644
--- a/tests/py/ip6/ip6.t.payload.inet
+++ b/tests/py/ip6/ip6.t.payload.inet
@@ -604,9 +604,8 @@ inet test-inet input
inet test-inet input
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x0000000a ]
- [ payload load 16b @ network header + 8 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
- [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
+ [ payload load 8b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
# ip6 saddr ::1 ip6 daddr ::2
inet test-inet input
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
index b2e8363..18b8bcb 100644
--- a/tests/py/ip6/ip6.t.payload.ip6
+++ b/tests/py/ip6/ip6.t.payload.ip6
@@ -452,9 +452,8 @@ ip6 test-ip6 input
# ip6 saddr ::/64
ip6 test-ip6 input
- [ payload load 16b @ network header + 8 => reg 1 ]
- [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
- [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
+ [ payload load 8b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
# ip6 saddr ::1 ip6 daddr ::2
ip6 test-ip6 input
--
2.31.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,294 @@
From f87960ecc2ed04c803b27bb6a9c42ecd0ba0bc96 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] parser: merge sack-perm/sack-permitted and maxseg/mss
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 2a9aea6f2dfb6
commit 2a9aea6f2dfb6ee61528809af98860e06b38762b
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 2 00:27:04 2020 +0100
parser: merge sack-perm/sack-permitted and maxseg/mss
One was added by the tcp option parsing ocde, the other by synproxy.
So we have:
synproxy ... sack-perm
synproxy ... mss
and
tcp option maxseg
tcp option sack-permitted
This kills the extra tokens on the scanner/parser side,
so sack-perm and sack-permitted can both be used.
Likewise, 'synproxy maxseg' and 'tcp option mss size 42' will work too.
On the output side, the shorter form is now preferred, i.e. sack-perm
and mss.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
doc/payload-expression.txt | 8 ++++----
src/parser_bison.y | 12 +++++-------
src/scanner.l | 8 ++++----
src/tcpopt.c | 2 +-
tests/py/any/tcpopt.t | 4 ++--
tests/py/any/tcpopt.t.json | 8 ++++----
tests/py/any/tcpopt.t.payload | 12 ++++++------
7 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index dba42fd..3d7057c 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -525,13 +525,13 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC
*dst* {*nexthdr* | *hdrlength*}
*mh* {*nexthdr* | *hdrlength* | *checksum* | *type*}
*srh* {*flags* | *tag* | *sid* | *seg-left*}
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
+*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
*ip option* { lsrr | ra | rr | ssrr } 'ip_option_field'
The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only:
[verse]
*exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*}
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
+*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
*ip option* { lsrr | ra | rr | ssrr }
.IPv6 extension headers
@@ -568,7 +568,7 @@ kind, length, size
|window|
TCP Window Scaling |
kind, length, count
-|sack-permitted|
+|sack-perm |
TCP SACK permitted |
kind, length
|sack|
@@ -611,7 +611,7 @@ type, length, ptr, addr
.finding TCP options
--------------------
-filter input tcp option sack-permitted kind 1 counter
+filter input tcp option sack-perm kind 1 counter
--------------------
.matching IPv6 exthdr
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 4cca31b..56d26e3 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -221,7 +221,6 @@ int nft_lex(void *, void *, void *);
%token SYNPROXY "synproxy"
%token MSS "mss"
%token WSCALE "wscale"
-%token SACKPERM "sack-perm"
%token HOOK "hook"
%token DEVICE "device"
@@ -385,14 +384,13 @@ int nft_lex(void *, void *, void *);
%token OPTION "option"
%token ECHO "echo"
%token EOL "eol"
-%token MAXSEG "maxseg"
%token NOOP "noop"
%token SACK "sack"
%token SACK0 "sack0"
%token SACK1 "sack1"
%token SACK2 "sack2"
%token SACK3 "sack3"
-%token SACK_PERMITTED "sack-permitted"
+%token SACK_PERM "sack-permitted"
%token TIMESTAMP "timestamp"
%token KIND "kind"
%token COUNT "count"
@@ -2889,7 +2887,7 @@ synproxy_arg : MSS NUM
{
$<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_TIMESTAMP;
}
- | SACKPERM
+ | SACK_PERM
{
$<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_SACK_PERM;
}
@@ -2944,7 +2942,7 @@ synproxy_ts : /* empty */ { $$ = 0; }
;
synproxy_sack : /* empty */ { $$ = 0; }
- | SACKPERM
+ | SACK_PERM
{
$$ = NF_SYNPROXY_OPT_SACK_PERM;
}
@@ -4736,9 +4734,9 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; }
| NOOP { $$ = TCPOPTHDR_NOOP; }
- | MAXSEG { $$ = TCPOPTHDR_MAXSEG; }
+ | MSS { $$ = TCPOPTHDR_MAXSEG; }
| WINDOW { $$ = TCPOPTHDR_WINDOW; }
- | SACK_PERMITTED { $$ = TCPOPTHDR_SACK_PERMITTED; }
+ | SACK_PERM { $$ = TCPOPTHDR_SACK_PERMITTED; }
| SACK { $$ = TCPOPTHDR_SACK0; }
| SACK0 { $$ = TCPOPTHDR_SACK0; }
| SACK1 { $$ = TCPOPTHDR_SACK1; }
diff --git a/src/scanner.l b/src/scanner.l
index 7daf5c1..a369802 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -419,14 +419,16 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"echo" { return ECHO; }
"eol" { return EOL; }
-"maxseg" { return MAXSEG; }
+"maxseg" { return MSS; }
+"mss" { return MSS; }
"noop" { return NOOP; }
"sack" { return SACK; }
"sack0" { return SACK0; }
"sack1" { return SACK1; }
"sack2" { return SACK2; }
"sack3" { return SACK3; }
-"sack-permitted" { return SACK_PERMITTED; }
+"sack-permitted" { return SACK_PERM; }
+"sack-perm" { return SACK_PERM; }
"timestamp" { return TIMESTAMP; }
"time" { return TIME; }
@@ -562,9 +564,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"osf" { return OSF; }
"synproxy" { return SYNPROXY; }
-"mss" { return MSS; }
"wscale" { return WSCALE; }
-"sack-perm" { return SACKPERM; }
"notrack" { return NOTRACK; }
diff --git a/src/tcpopt.c b/src/tcpopt.c
index ec305d9..6dbaa9e 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -55,7 +55,7 @@ static const struct exthdr_desc tcpopt_window = {
};
static const struct exthdr_desc tcpopt_sack_permitted = {
- .name = "sack-permitted",
+ .name = "sack-perm",
.type = TCPOPT_SACK_PERMITTED,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
index 08b1dcb..5f21d49 100644
--- a/tests/py/any/tcpopt.t
+++ b/tests/py/any/tcpopt.t
@@ -12,8 +12,8 @@ tcp option maxseg size 1;ok
tcp option window kind 1;ok
tcp option window length 1;ok
tcp option window count 1;ok
-tcp option sack-permitted kind 1;ok
-tcp option sack-permitted length 1;ok
+tcp option sack-perm kind 1;ok
+tcp option sack-perm length 1;ok
tcp option sack kind 1;ok
tcp option sack length 1;ok
tcp option sack left 1;ok
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
index 48eb339..2c6236a 100644
--- a/tests/py/any/tcpopt.t.json
+++ b/tests/py/any/tcpopt.t.json
@@ -126,14 +126,14 @@
}
]
-# tcp option sack-permitted kind 1
+# tcp option sack-perm kind 1
[
{
"match": {
"left": {
"tcp option": {
"field": "kind",
- "name": "sack-permitted"
+ "name": "sack-perm"
}
},
"op": "==",
@@ -142,14 +142,14 @@
}
]
-# tcp option sack-permitted length 1
+# tcp option sack-perm length 1
[
{
"match": {
"left": {
"tcp option": {
"field": "length",
- "name": "sack-permitted"
+ "name": "sack-perm"
}
},
"op": "==",
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
index 63751cf..f63076a 100644
--- a/tests/py/any/tcpopt.t.payload
+++ b/tests/py/any/tcpopt.t.payload
@@ -166,42 +166,42 @@ inet
[ exthdr load tcpopt 1b @ 3 + 2 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted kind 1
+# tcp option sack-perm kind 1
ip
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted kind 1
+# tcp option sack-perm kind 1
ip6
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted kind 1
+# tcp option sack-perm kind 1
inet
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted length 1
+# tcp option sack-perm length 1
ip
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 4 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted length 1
+# tcp option sack-perm length 1
ip6
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 4 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option sack-permitted length 1
+# tcp option sack-perm length 1
inet
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
--
2.31.1

View File

@ -0,0 +1,387 @@
From 0aa694acf7c233f9426e48d0644b29ddec4fb16d Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] tcpopts: clean up parser -> tcpopt.c plumbing
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 41158e0388ac5
commit 41158e0388ac56380fc0ee301f0d43f95ec43fab
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 2 14:53:26 2020 +0100
tcpopts: clean up parser -> tcpopt.c plumbing
tcpopt template mapping is asymmetric:
one mapping is to match dumped netlink exthdr expression to the original
tcp option template.
This struct is indexed by the raw, on-write kind/type number.
The other mapping maps parsed options to the tcp option template.
Remove the latter. The parser is changed to translate the textual
option name, e.g. "maxseg" to the on-wire number.
This avoids the second mapping, it will also allow to more easily
support raw option matching in a followup patch.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
doc/payload-expression.txt | 4 +-
include/tcpopt.h | 35 ++++++++-------
src/parser_bison.y | 26 +++++------
src/parser_json.c | 10 ++---
src/scanner.l | 3 +-
src/tcpopt.c | 92 +++++++++++++++-----------------------
6 files changed, 75 insertions(+), 95 deletions(-)
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index 3d7057c..27145c3 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -525,13 +525,13 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC
*dst* {*nexthdr* | *hdrlength*}
*mh* {*nexthdr* | *hdrlength* | *checksum* | *type*}
*srh* {*flags* | *tag* | *sid* | *seg-left*}
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
+*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
*ip option* { lsrr | ra | rr | ssrr } 'ip_option_field'
The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only:
[verse]
*exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*}
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
+*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
*ip option* { lsrr | ra | rr | ssrr }
.IPv6 extension headers
diff --git a/include/tcpopt.h b/include/tcpopt.h
index ffdbcb0..7f3fbb8 100644
--- a/include/tcpopt.h
+++ b/include/tcpopt.h
@@ -6,7 +6,7 @@
#include <statement.h>
extern struct expr *tcpopt_expr_alloc(const struct location *loc,
- uint8_t type, uint8_t field);
+ unsigned int kind, unsigned int field);
extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
unsigned int offset, unsigned int len,
@@ -15,21 +15,22 @@ extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
extern bool tcpopt_find_template(struct expr *expr, const struct expr *mask,
unsigned int *shift);
-enum tcpopt_hdr_types {
- TCPOPTHDR_INVALID,
- TCPOPTHDR_EOL,
- TCPOPTHDR_NOOP,
- TCPOPTHDR_MAXSEG,
- TCPOPTHDR_WINDOW,
- TCPOPTHDR_SACK_PERMITTED,
- TCPOPTHDR_SACK0,
- TCPOPTHDR_SACK1,
- TCPOPTHDR_SACK2,
- TCPOPTHDR_SACK3,
- TCPOPTHDR_TIMESTAMP,
- TCPOPTHDR_ECHO,
- TCPOPTHDR_ECHO_REPLY,
- __TCPOPTHDR_MAX
+/* TCP option numbers used on wire */
+enum tcpopt_kind {
+ TCPOPT_KIND_EOL = 0,
+ TCPOPT_KIND_NOP = 1,
+ TCPOPT_KIND_MAXSEG = 2,
+ TCPOPT_KIND_WINDOW = 3,
+ TCPOPT_KIND_SACK_PERMITTED = 4,
+ TCPOPT_KIND_SACK = 5,
+ TCPOPT_KIND_TIMESTAMP = 8,
+ TCPOPT_KIND_ECHO = 8,
+ __TCPOPT_KIND_MAX,
+
+ /* extra oob info, internal to nft */
+ TCPOPT_KIND_SACK1 = 256,
+ TCPOPT_KIND_SACK2 = 257,
+ TCPOPT_KIND_SACK3 = 258,
};
enum tcpopt_hdr_fields {
@@ -44,6 +45,6 @@ enum tcpopt_hdr_fields {
TCPOPTHDR_FIELD_TSECR,
};
-extern const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX];
+extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX];
#endif /* NFTABLES_TCPOPT_H */
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 56d26e3..8f77766 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -384,7 +384,7 @@ int nft_lex(void *, void *, void *);
%token OPTION "option"
%token ECHO "echo"
%token EOL "eol"
-%token NOOP "noop"
+%token NOP "nop"
%token SACK "sack"
%token SACK0 "sack0"
%token SACK1 "sack1"
@@ -4732,18 +4732,18 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
| URGPTR { $$ = TCPHDR_URGPTR; }
;
-tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; }
- | NOOP { $$ = TCPOPTHDR_NOOP; }
- | MSS { $$ = TCPOPTHDR_MAXSEG; }
- | WINDOW { $$ = TCPOPTHDR_WINDOW; }
- | SACK_PERM { $$ = TCPOPTHDR_SACK_PERMITTED; }
- | SACK { $$ = TCPOPTHDR_SACK0; }
- | SACK0 { $$ = TCPOPTHDR_SACK0; }
- | SACK1 { $$ = TCPOPTHDR_SACK1; }
- | SACK2 { $$ = TCPOPTHDR_SACK2; }
- | SACK3 { $$ = TCPOPTHDR_SACK3; }
- | ECHO { $$ = TCPOPTHDR_ECHO; }
- | TIMESTAMP { $$ = TCPOPTHDR_TIMESTAMP; }
+tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
+ | NOP { $$ = TCPOPT_KIND_NOP; }
+ | MSS { $$ = TCPOPT_KIND_MAXSEG; }
+ | WINDOW { $$ = TCPOPT_KIND_WINDOW; }
+ | SACK_PERM { $$ = TCPOPT_KIND_SACK_PERMITTED; }
+ | SACK { $$ = TCPOPT_KIND_SACK; }
+ | SACK0 { $$ = TCPOPT_KIND_SACK; }
+ | SACK1 { $$ = TCPOPT_KIND_SACK1; }
+ | SACK2 { $$ = TCPOPT_KIND_SACK2; }
+ | SACK3 { $$ = TCPOPT_KIND_SACK3; }
+ | ECHO { $$ = TCPOPT_KIND_ECHO; }
+ | TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
;
tcp_hdr_option_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; }
diff --git a/src/parser_json.c b/src/parser_json.c
index 662bb4b..44b58a0 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -456,9 +456,9 @@ static int json_parse_tcp_option_type(const char *name, int *val)
{
unsigned int i;
- for (i = 0; i < array_size(tcpopthdr_protocols); i++) {
- if (tcpopthdr_protocols[i] &&
- !strcmp(tcpopthdr_protocols[i]->name, name)) {
+ for (i = 0; i < array_size(tcpopt_protocols); i++) {
+ if (tcpopt_protocols[i] &&
+ !strcmp(tcpopt_protocols[i]->name, name)) {
if (val)
*val = i;
return 0;
@@ -467,7 +467,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
/* special case for sack0 - sack3 */
if (sscanf(name, "sack%u", &i) == 1 && i < 4) {
if (val)
- *val = TCPOPTHDR_SACK0 + i;
+ *val = TCPOPT_KIND_SACK + i;
return 0;
}
return 1;
@@ -476,7 +476,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
static int json_parse_tcp_option_field(int type, const char *name, int *val)
{
unsigned int i;
- const struct exthdr_desc *desc = tcpopthdr_protocols[type];
+ const struct exthdr_desc *desc = tcpopt_protocols[type];
for (i = 0; i < array_size(desc->templates); i++) {
if (desc->templates[i].token &&
diff --git a/src/scanner.l b/src/scanner.l
index a369802..20b1b2d 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -421,7 +421,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"eol" { return EOL; }
"maxseg" { return MSS; }
"mss" { return MSS; }
-"noop" { return NOOP; }
+"nop" { return NOP; }
+"noop" { return NOP; }
"sack" { return SACK; }
"sack0" { return SACK0; }
"sack1" { return SACK1; }
diff --git a/src/tcpopt.c b/src/tcpopt.c
index 6dbaa9e..8d5bdec 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -20,7 +20,7 @@ static const struct proto_hdr_template tcpopt_unknown_template =
__offset, __len)
static const struct exthdr_desc tcpopt_eol = {
.name = "eol",
- .type = TCPOPT_EOL,
+ .type = TCPOPT_KIND_EOL,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
},
@@ -28,7 +28,7 @@ static const struct exthdr_desc tcpopt_eol = {
static const struct exthdr_desc tcpopt_nop = {
.name = "noop",
- .type = TCPOPT_NOP,
+ .type = TCPOPT_KIND_NOP,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
},
@@ -36,7 +36,7 @@ static const struct exthdr_desc tcpopt_nop = {
static const struct exthdr_desc tcptopt_maxseg = {
.name = "maxseg",
- .type = TCPOPT_MAXSEG,
+ .type = TCPOPT_KIND_MAXSEG,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -46,7 +46,7 @@ static const struct exthdr_desc tcptopt_maxseg = {
static const struct exthdr_desc tcpopt_window = {
.name = "window",
- .type = TCPOPT_WINDOW,
+ .type = TCPOPT_KIND_WINDOW,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -56,7 +56,7 @@ static const struct exthdr_desc tcpopt_window = {
static const struct exthdr_desc tcpopt_sack_permitted = {
.name = "sack-perm",
- .type = TCPOPT_SACK_PERMITTED,
+ .type = TCPOPT_KIND_SACK_PERMITTED,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -65,7 +65,7 @@ static const struct exthdr_desc tcpopt_sack_permitted = {
static const struct exthdr_desc tcpopt_sack = {
.name = "sack",
- .type = TCPOPT_SACK,
+ .type = TCPOPT_KIND_SACK,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -76,7 +76,7 @@ static const struct exthdr_desc tcpopt_sack = {
static const struct exthdr_desc tcpopt_timestamp = {
.name = "timestamp",
- .type = TCPOPT_TIMESTAMP,
+ .type = TCPOPT_KIND_TIMESTAMP,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -86,19 +86,14 @@ static const struct exthdr_desc tcpopt_timestamp = {
};
#undef PHT
-#define TCPOPT_OBSOLETE ((struct exthdr_desc *)NULL)
-#define TCPOPT_ECHO 6
-#define TCPOPT_ECHO_REPLY 7
-static const struct exthdr_desc *tcpopt_protocols[] = {
- [TCPOPT_EOL] = &tcpopt_eol,
- [TCPOPT_NOP] = &tcpopt_nop,
- [TCPOPT_MAXSEG] = &tcptopt_maxseg,
- [TCPOPT_WINDOW] = &tcpopt_window,
- [TCPOPT_SACK_PERMITTED] = &tcpopt_sack_permitted,
- [TCPOPT_SACK] = &tcpopt_sack,
- [TCPOPT_ECHO] = TCPOPT_OBSOLETE,
- [TCPOPT_ECHO_REPLY] = TCPOPT_OBSOLETE,
- [TCPOPT_TIMESTAMP] = &tcpopt_timestamp,
+const struct exthdr_desc *tcpopt_protocols[] = {
+ [TCPOPT_KIND_EOL] = &tcpopt_eol,
+ [TCPOPT_KIND_NOP] = &tcpopt_nop,
+ [TCPOPT_KIND_MAXSEG] = &tcptopt_maxseg,
+ [TCPOPT_KIND_WINDOW] = &tcpopt_window,
+ [TCPOPT_KIND_SACK_PERMITTED] = &tcpopt_sack_permitted,
+ [TCPOPT_KIND_SACK] = &tcpopt_sack,
+ [TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
};
static unsigned int calc_offset(const struct exthdr_desc *desc,
@@ -136,51 +131,34 @@ static unsigned int calc_offset_reverse(const struct exthdr_desc *desc,
}
}
-const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX] = {
- [TCPOPTHDR_EOL] = &tcpopt_eol,
- [TCPOPTHDR_NOOP] = &tcpopt_nop,
- [TCPOPTHDR_MAXSEG] = &tcptopt_maxseg,
- [TCPOPTHDR_WINDOW] = &tcpopt_window,
- [TCPOPTHDR_SACK_PERMITTED] = &tcpopt_sack_permitted,
- [TCPOPTHDR_SACK0] = &tcpopt_sack,
- [TCPOPTHDR_SACK1] = &tcpopt_sack,
- [TCPOPTHDR_SACK2] = &tcpopt_sack,
- [TCPOPTHDR_SACK3] = &tcpopt_sack,
- [TCPOPTHDR_ECHO] = TCPOPT_OBSOLETE,
- [TCPOPTHDR_ECHO_REPLY] = TCPOPT_OBSOLETE,
- [TCPOPTHDR_TIMESTAMP] = &tcpopt_timestamp,
-};
-
-static uint8_t tcpopt_optnum[] = {
- [TCPOPTHDR_SACK0] = 0,
- [TCPOPTHDR_SACK1] = 1,
- [TCPOPTHDR_SACK2] = 2,
- [TCPOPTHDR_SACK3] = 3,
-};
-
-static uint8_t tcpopt_find_optnum(uint8_t optnum)
-{
- if (optnum > TCPOPTHDR_SACK3)
- return 0;
-
- return tcpopt_optnum[optnum];
-}
-
-struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type,
- uint8_t field)
+struct expr *tcpopt_expr_alloc(const struct location *loc,
+ unsigned int kind,
+ unsigned int field)
{
const struct proto_hdr_template *tmpl;
const struct exthdr_desc *desc;
+ uint8_t optnum = 0;
struct expr *expr;
- uint8_t optnum;
- desc = tcpopthdr_protocols[type];
+ switch (kind) {
+ case TCPOPT_KIND_SACK1:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 1;
+ break;
+ case TCPOPT_KIND_SACK2:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 2;
+ break;
+ case TCPOPT_KIND_SACK3:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 3;
+ }
+
+ desc = tcpopt_protocols[kind];
tmpl = &desc->templates[field];
if (!tmpl)
return NULL;
- optnum = tcpopt_find_optnum(type);
-
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
BYTEORDER_BIG_ENDIAN, tmpl->len);
expr->exthdr.desc = desc;
@@ -206,7 +184,7 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
assert(type < array_size(tcpopt_protocols));
expr->exthdr.desc = tcpopt_protocols[type];
expr->exthdr.flags = flags;
- assert(expr->exthdr.desc != TCPOPT_OBSOLETE);
+ assert(expr->exthdr.desc != NULL);
for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
tmpl = &expr->exthdr.desc->templates[i];
--
2.31.1

View File

@ -0,0 +1,118 @@
From f4476f9428a79c5d6d8fe284f0da91c2d4177e66 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] tcpopt: rename noop to nop
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 8f591eba561ac
commit 8f591eba561aceeef605283c693b659a708d1cd3
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 2 14:58:41 2020 +0100
tcpopt: rename noop to nop
'nop' is the tcp padding "option". "noop" is retained for compatibility
on parser side.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
doc/payload-expression.txt | 4 ++--
src/tcpopt.c | 2 +-
tests/py/any/tcpopt.t | 2 +-
tests/py/any/tcpopt.t.json | 4 ++--
tests/py/any/tcpopt.t.payload | 16 +---------------
5 files changed, 7 insertions(+), 21 deletions(-)
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index 27145c3..3a07321 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -559,8 +559,8 @@ Segment Routing Header
|eol|
End if option list|
kind
-|noop|
-1 Byte TCP No-op options |
+|nop|
+1 Byte TCP Nop padding option |
kind
|maxseg|
TCP Maximum Segment Size|
diff --git a/src/tcpopt.c b/src/tcpopt.c
index 8d5bdec..17cb580 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -27,7 +27,7 @@ static const struct exthdr_desc tcpopt_eol = {
};
static const struct exthdr_desc tcpopt_nop = {
- .name = "noop",
+ .name = "nop",
.type = TCPOPT_KIND_NOP,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
index 5f21d49..1d42de8 100644
--- a/tests/py/any/tcpopt.t
+++ b/tests/py/any/tcpopt.t
@@ -5,7 +5,7 @@
*inet;test-inet;input
tcp option eol kind 1;ok
-tcp option noop kind 1;ok
+tcp option nop kind 1;ok
tcp option maxseg kind 1;ok
tcp option maxseg length 1;ok
tcp option maxseg size 1;ok
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
index 2c6236a..b15e36e 100644
--- a/tests/py/any/tcpopt.t.json
+++ b/tests/py/any/tcpopt.t.json
@@ -14,14 +14,14 @@
}
]
-# tcp option noop kind 1
+# tcp option nop kind 1
[
{
"match": {
"left": {
"tcp option": {
"field": "kind",
- "name": "noop"
+ "name": "nop"
}
},
"op": "==",
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
index f63076a..9c480c8 100644
--- a/tests/py/any/tcpopt.t.payload
+++ b/tests/py/any/tcpopt.t.payload
@@ -19,21 +19,7 @@ inet
[ exthdr load tcpopt 1b @ 0 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option noop kind 1
-ip
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 1 + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
-
-# tcp option noop kind 1
-ip6
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 1 + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
-
-# tcp option noop kind 1
+# tcp option nop kind 1
inet
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
--
2.31.1

View File

@ -0,0 +1,538 @@
From 9697436145bf374093dc61e3ad857f7122de08ee Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] tcpopt: split tcpopt_hdr_fields into per-option enum
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 2e1f821d713aa
commit 2e1f821d713aa44717b38901ee80cac8e2aa0335
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 2 15:22:40 2020 +0100
tcpopt: split tcpopt_hdr_fields into per-option enum
Currently we're limited to ten template fields in exthdr_desc struct.
Using a single enum for all tpc option fields thus won't work
indefinitely (TCPOPTHDR_FIELD_TSECR is 9) when new option templates get
added.
Fortunately we can just use one enum per tcp option to avoid this.
As a side effect this also allows to simplify the sack offset
calculations. Rather than computing that on-the-fly, just add extra
fields to the SACK template.
expr->exthdr.offset now holds the 'raw' value, filled in from the option
template. This would ease implementation of 'raw option matching'
using offset and length to load from the option.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/tcpopt.h | 46 +++++++++++----
src/evaluate.c | 16 ++---
src/exthdr.c | 1 +
src/ipopt.c | 2 +-
src/netlink_delinearize.c | 2 +-
src/netlink_linearize.c | 4 +-
src/parser_bison.y | 18 +++---
src/parser_json.c | 36 ++++++++++--
src/tcpopt.c | 119 ++++++++++++++++----------------------
9 files changed, 139 insertions(+), 105 deletions(-)
diff --git a/include/tcpopt.h b/include/tcpopt.h
index 7f3fbb8..667c8a7 100644
--- a/include/tcpopt.h
+++ b/include/tcpopt.h
@@ -33,16 +33,42 @@ enum tcpopt_kind {
TCPOPT_KIND_SACK3 = 258,
};
-enum tcpopt_hdr_fields {
- TCPOPTHDR_FIELD_INVALID,
- TCPOPTHDR_FIELD_KIND,
- TCPOPTHDR_FIELD_LENGTH,
- TCPOPTHDR_FIELD_SIZE,
- TCPOPTHDR_FIELD_COUNT,
- TCPOPTHDR_FIELD_LEFT,
- TCPOPTHDR_FIELD_RIGHT,
- TCPOPTHDR_FIELD_TSVAL,
- TCPOPTHDR_FIELD_TSECR,
+/* Internal identifiers */
+enum tcpopt_common {
+ TCPOPT_COMMON_KIND,
+ TCPOPT_COMMON_LENGTH,
+};
+
+enum tcpopt_maxseg {
+ TCPOPT_MAXSEG_KIND,
+ TCPOPT_MAXSEG_LENGTH,
+ TCPOPT_MAXSEG_SIZE,
+};
+
+enum tcpopt_timestamp {
+ TCPOPT_TS_KIND,
+ TCPOPT_TS_LENGTH,
+ TCPOPT_TS_TSVAL,
+ TCPOPT_TS_TSECR,
+};
+
+enum tcpopt_windowscale {
+ TCPOPT_WINDOW_KIND,
+ TCPOPT_WINDOW_LENGTH,
+ TCPOPT_WINDOW_COUNT,
+};
+
+enum tcpopt_hdr_field_sack {
+ TCPOPT_SACK_KIND,
+ TCPOPT_SACK_LENGTH,
+ TCPOPT_SACK_LEFT,
+ TCPOPT_SACK_RIGHT,
+ TCPOPT_SACK_LEFT1,
+ TCPOPT_SACK_RIGHT1,
+ TCPOPT_SACK_LEFT2,
+ TCPOPT_SACK_RIGHT2,
+ TCPOPT_SACK_LEFT3,
+ TCPOPT_SACK_RIGHT3,
};
extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX];
diff --git a/src/evaluate.c b/src/evaluate.c
index 0181750..99a66c2 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -474,7 +474,7 @@ static void expr_evaluate_bits(struct eval_ctx *ctx, struct expr **exprp)
&extra_len);
break;
case EXPR_EXTHDR:
- shift = expr_offset_shift(expr, expr->exthdr.tmpl->offset,
+ shift = expr_offset_shift(expr, expr->exthdr.offset,
&extra_len);
break;
default:
@@ -526,18 +526,16 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
if (expr_evaluate_primary(ctx, exprp) < 0)
return -1;
- if (expr->exthdr.tmpl->offset % BITS_PER_BYTE != 0 ||
+ if (expr->exthdr.offset % BITS_PER_BYTE != 0 ||
expr->len % BITS_PER_BYTE != 0)
expr_evaluate_bits(ctx, exprp);
switch (expr->exthdr.op) {
case NFT_EXTHDR_OP_TCPOPT: {
static const unsigned int max_tcpoptlen = (15 * 4 - 20) * BITS_PER_BYTE;
- unsigned int totlen = 0;
+ unsigned int totlen;
- totlen += expr->exthdr.tmpl->offset;
- totlen += expr->exthdr.tmpl->len;
- totlen += expr->exthdr.offset;
+ totlen = expr->exthdr.tmpl->len + expr->exthdr.offset;
if (totlen > max_tcpoptlen)
return expr_error(ctx->msgs, expr,
@@ -547,11 +545,9 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
}
case NFT_EXTHDR_OP_IPV4: {
static const unsigned int max_ipoptlen = 40 * BITS_PER_BYTE;
- unsigned int totlen = 0;
+ unsigned int totlen;
- totlen += expr->exthdr.tmpl->offset;
- totlen += expr->exthdr.tmpl->len;
- totlen += expr->exthdr.offset;
+ totlen = expr->exthdr.offset + expr->exthdr.tmpl->len;
if (totlen > max_ipoptlen)
return expr_error(ctx->msgs, expr,
diff --git a/src/exthdr.c b/src/exthdr.c
index e1ec6f3..c28213f 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -99,6 +99,7 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
BYTEORDER_BIG_ENDIAN, tmpl->len);
expr->exthdr.desc = desc;
expr->exthdr.tmpl = tmpl;
+ expr->exthdr.offset = tmpl->offset;
return expr;
}
diff --git a/src/ipopt.c b/src/ipopt.c
index b3d0279..7ecb8b9 100644
--- a/src/ipopt.c
+++ b/src/ipopt.c
@@ -102,7 +102,7 @@ struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type,
expr->exthdr.desc = desc;
expr->exthdr.tmpl = tmpl;
expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
- expr->exthdr.offset = calc_offset(desc, tmpl, ptr);
+ expr->exthdr.offset = tmpl->offset + calc_offset(desc, tmpl, ptr);
return expr;
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 157a473..790336a 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -727,8 +727,8 @@ static void netlink_parse_numgen(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
- enum nft_registers dreg;
uint32_t type, until, offset;
+ enum nft_registers dreg;
struct expr *expr;
type = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_TYPE);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 25be634..9d1a064 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -168,7 +168,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
const struct expr *expr,
enum nft_registers dreg)
{
- unsigned int offset = expr->exthdr.tmpl->offset + expr->exthdr.offset;
+ unsigned int offset = expr->exthdr.offset;
struct nftnl_expr *nle;
nle = alloc_nft_expr("exthdr");
@@ -896,7 +896,7 @@ static void netlink_gen_exthdr_stmt(struct netlink_linearize_ctx *ctx,
expr = stmt->exthdr.expr;
- offset = expr->exthdr.tmpl->offset + expr->exthdr.offset;
+ offset = expr->exthdr.offset;
nle = alloc_nft_expr("exthdr");
netlink_put_register(nle, NFTNL_EXPR_EXTHDR_SREG, sreg);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 8f77766..114b289 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4715,7 +4715,7 @@ tcp_hdr_expr : TCP tcp_hdr_field
}
| TCP OPTION tcp_hdr_option_type
{
- $$ = tcpopt_expr_alloc(&@$, $3, TCPOPTHDR_FIELD_KIND);
+ $$ = tcpopt_expr_alloc(&@$, $3, TCPOPT_COMMON_KIND);
$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
}
;
@@ -4746,14 +4746,14 @@ tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
| TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
;
-tcp_hdr_option_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; }
- | LENGTH { $$ = TCPOPTHDR_FIELD_LENGTH; }
- | SIZE { $$ = TCPOPTHDR_FIELD_SIZE; }
- | COUNT { $$ = TCPOPTHDR_FIELD_COUNT; }
- | LEFT { $$ = TCPOPTHDR_FIELD_LEFT; }
- | RIGHT { $$ = TCPOPTHDR_FIELD_RIGHT; }
- | TSVAL { $$ = TCPOPTHDR_FIELD_TSVAL; }
- | TSECR { $$ = TCPOPTHDR_FIELD_TSECR; }
+tcp_hdr_option_field : KIND { $$ = TCPOPT_COMMON_KIND; }
+ | LENGTH { $$ = TCPOPT_COMMON_LENGTH; }
+ | SIZE { $$ = TCPOPT_MAXSEG_SIZE; }
+ | COUNT { $$ = TCPOPT_WINDOW_COUNT; }
+ | LEFT { $$ = TCPOPT_SACK_LEFT; }
+ | RIGHT { $$ = TCPOPT_SACK_RIGHT; }
+ | TSVAL { $$ = TCPOPT_TS_TSVAL; }
+ | TSECR { $$ = TCPOPT_TS_TSECR; }
;
dccp_hdr_expr : DCCP dccp_hdr_field
diff --git a/src/parser_json.c b/src/parser_json.c
index 44b58a0..ab2375f 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -466,8 +466,10 @@ static int json_parse_tcp_option_type(const char *name, int *val)
}
/* special case for sack0 - sack3 */
if (sscanf(name, "sack%u", &i) == 1 && i < 4) {
- if (val)
- *val = TCPOPT_KIND_SACK + i;
+ if (val && i == 0)
+ *val = TCPOPT_KIND_SACK;
+ else if (val && i > 0)
+ *val = TCPOPT_KIND_SACK1 + i - 1;
return 0;
}
return 1;
@@ -475,12 +477,38 @@ static int json_parse_tcp_option_type(const char *name, int *val)
static int json_parse_tcp_option_field(int type, const char *name, int *val)
{
+ const struct exthdr_desc *desc;
+ unsigned int block = 0;
unsigned int i;
- const struct exthdr_desc *desc = tcpopt_protocols[type];
+
+ switch (type) {
+ case TCPOPT_KIND_SACK1:
+ type = TCPOPT_KIND_SACK;
+ block = 1;
+ break;
+ case TCPOPT_KIND_SACK2:
+ type = TCPOPT_KIND_SACK;
+ block = 2;
+ break;
+ case TCPOPT_KIND_SACK3:
+ type = TCPOPT_KIND_SACK;
+ block = 3;
+ break;
+ }
+
+ if (type < 0 || type >= (int)array_size(tcpopt_protocols))
+ return 1;
+
+ desc = tcpopt_protocols[type];
for (i = 0; i < array_size(desc->templates); i++) {
if (desc->templates[i].token &&
!strcmp(desc->templates[i].token, name)) {
+ if (block) {
+ block--;
+ continue;
+ }
+
if (val)
*val = i;
return 0;
@@ -585,7 +613,7 @@ static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
if (json_unpack(root, "{s:s}", "field", &field)) {
expr = tcpopt_expr_alloc(int_loc, descval,
- TCPOPTHDR_FIELD_KIND);
+ TCPOPT_COMMON_KIND);
expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
return expr;
diff --git a/src/tcpopt.c b/src/tcpopt.c
index 17cb580..d1dd13b 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -22,7 +22,7 @@ static const struct exthdr_desc tcpopt_eol = {
.name = "eol",
.type = TCPOPT_KIND_EOL,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
},
};
@@ -30,7 +30,7 @@ static const struct exthdr_desc tcpopt_nop = {
.name = "nop",
.type = TCPOPT_KIND_NOP,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
},
};
@@ -38,9 +38,9 @@ static const struct exthdr_desc tcptopt_maxseg = {
.name = "maxseg",
.type = TCPOPT_KIND_MAXSEG,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
- [TCPOPTHDR_FIELD_SIZE] = PHT("size", 16, 16),
+ [TCPOPT_MAXSEG_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_MAXSEG_LENGTH] = PHT("length", 8, 8),
+ [TCPOPT_MAXSEG_SIZE] = PHT("size", 16, 16),
},
};
@@ -48,9 +48,9 @@ static const struct exthdr_desc tcpopt_window = {
.name = "window",
.type = TCPOPT_KIND_WINDOW,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
- [TCPOPTHDR_FIELD_COUNT] = PHT("count", 16, 8),
+ [TCPOPT_WINDOW_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_WINDOW_LENGTH] = PHT("length", 8, 8),
+ [TCPOPT_WINDOW_COUNT] = PHT("count", 16, 8),
},
};
@@ -58,8 +58,8 @@ static const struct exthdr_desc tcpopt_sack_permitted = {
.name = "sack-perm",
.type = TCPOPT_KIND_SACK_PERMITTED,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_COMMON_LENGTH] = PHT("length", 8, 8),
},
};
@@ -67,10 +67,16 @@ static const struct exthdr_desc tcpopt_sack = {
.name = "sack",
.type = TCPOPT_KIND_SACK,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
- [TCPOPTHDR_FIELD_LEFT] = PHT("left", 16, 32),
- [TCPOPTHDR_FIELD_RIGHT] = PHT("right", 48, 32),
+ [TCPOPT_SACK_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_SACK_LENGTH] = PHT("length", 8, 8),
+ [TCPOPT_SACK_LEFT] = PHT("left", 16, 32),
+ [TCPOPT_SACK_RIGHT] = PHT("right", 48, 32),
+ [TCPOPT_SACK_LEFT1] = PHT("left", 80, 32),
+ [TCPOPT_SACK_RIGHT1] = PHT("right", 112, 32),
+ [TCPOPT_SACK_LEFT2] = PHT("left", 144, 32),
+ [TCPOPT_SACK_RIGHT2] = PHT("right", 176, 32),
+ [TCPOPT_SACK_LEFT3] = PHT("left", 208, 32),
+ [TCPOPT_SACK_RIGHT3] = PHT("right", 240, 32),
},
};
@@ -78,12 +84,13 @@ static const struct exthdr_desc tcpopt_timestamp = {
.name = "timestamp",
.type = TCPOPT_KIND_TIMESTAMP,
.templates = {
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
- [TCPOPTHDR_FIELD_TSVAL] = PHT("tsval", 16, 32),
- [TCPOPTHDR_FIELD_TSECR] = PHT("tsecr", 48, 32),
+ [TCPOPT_TS_KIND] = PHT("kind", 0, 8),
+ [TCPOPT_TS_LENGTH] = PHT("length", 8, 8),
+ [TCPOPT_TS_TSVAL] = PHT("tsval", 16, 32),
+ [TCPOPT_TS_TSECR] = PHT("tsecr", 48, 32),
},
};
+
#undef PHT
const struct exthdr_desc *tcpopt_protocols[] = {
@@ -96,65 +103,43 @@ const struct exthdr_desc *tcpopt_protocols[] = {
[TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
};
-static unsigned int calc_offset(const struct exthdr_desc *desc,
- const struct proto_hdr_template *tmpl,
- unsigned int num)
-{
- if (!desc || tmpl == &tcpopt_unknown_template)
- return 0;
-
- switch (desc->type) {
- case TCPOPT_SACK:
- /* Make sure, offset calculations only apply to left and right
- * fields
- */
- return (tmpl->offset < 16) ? 0 : num * 64;
- default:
- return 0;
- }
-}
-
-
-static unsigned int calc_offset_reverse(const struct exthdr_desc *desc,
- const struct proto_hdr_template *tmpl,
- unsigned int offset)
-{
- if (!desc || tmpl == &tcpopt_unknown_template)
- return offset;
-
- switch (desc->type) {
- case TCPOPT_SACK:
- /* We can safely ignore the first left/right field */
- return offset < 80 ? offset : (offset % 64);
- default:
- return offset;
- }
-}
-
struct expr *tcpopt_expr_alloc(const struct location *loc,
unsigned int kind,
unsigned int field)
{
const struct proto_hdr_template *tmpl;
- const struct exthdr_desc *desc;
- uint8_t optnum = 0;
+ const struct exthdr_desc *desc = NULL;
struct expr *expr;
switch (kind) {
case TCPOPT_KIND_SACK1:
kind = TCPOPT_KIND_SACK;
- optnum = 1;
+ if (field == TCPOPT_SACK_LEFT)
+ field = TCPOPT_SACK_LEFT1;
+ else if (field == TCPOPT_SACK_RIGHT)
+ field = TCPOPT_SACK_RIGHT1;
break;
case TCPOPT_KIND_SACK2:
kind = TCPOPT_KIND_SACK;
- optnum = 2;
+ if (field == TCPOPT_SACK_LEFT)
+ field = TCPOPT_SACK_LEFT2;
+ else if (field == TCPOPT_SACK_RIGHT)
+ field = TCPOPT_SACK_RIGHT2;
break;
case TCPOPT_KIND_SACK3:
kind = TCPOPT_KIND_SACK;
- optnum = 3;
+ if (field == TCPOPT_SACK_LEFT)
+ field = TCPOPT_SACK_LEFT3;
+ else if (field == TCPOPT_SACK_RIGHT)
+ field = TCPOPT_SACK_RIGHT3;
+ break;
}
- desc = tcpopt_protocols[kind];
+ if (kind < array_size(tcpopt_protocols))
+ desc = tcpopt_protocols[kind];
+
+ if (!desc)
+ return NULL;
tmpl = &desc->templates[field];
if (!tmpl)
return NULL;
@@ -164,34 +149,32 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
expr->exthdr.desc = desc;
expr->exthdr.tmpl = tmpl;
expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
- expr->exthdr.offset = calc_offset(desc, tmpl, optnum);
+ expr->exthdr.offset = tmpl->offset;
return expr;
}
-void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
+void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
unsigned int len, uint32_t flags)
{
const struct proto_hdr_template *tmpl;
- unsigned int i, off;
+ unsigned int i;
assert(expr->etype == EXPR_EXTHDR);
expr->len = len;
expr->exthdr.flags = flags;
- expr->exthdr.offset = offset;
+ expr->exthdr.offset = off;
+
+ if (type >= array_size(tcpopt_protocols))
+ return;
- assert(type < array_size(tcpopt_protocols));
expr->exthdr.desc = tcpopt_protocols[type];
expr->exthdr.flags = flags;
assert(expr->exthdr.desc != NULL);
for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
tmpl = &expr->exthdr.desc->templates[i];
- /* We have to reverse calculate the offset for the sack options
- * at this point
- */
- off = calc_offset_reverse(expr->exthdr.desc, tmpl, offset);
if (tmpl->offset != off || tmpl->len != len)
continue;
--
2.31.1

View File

@ -0,0 +1,336 @@
From 8a4b6cbf58e965d67b0337ba1736bd3691a49890 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] tcpopt: allow to check for presence of any tcp option
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 24d8da3083422
commit 24d8da3083422da8336eeed2ee23b2ccf598ba5a
Author: Florian Westphal <fw@strlen.de>
Date: Wed Oct 21 23:54:17 2020 +0200
tcpopt: allow to check for presence of any tcp option
nft currently doesn't allow to check for presence of arbitrary tcp options.
Only known options where nft provides a template can be tested for.
This allows to test for presence of raw protocol values as well.
Example:
tcp option 42 exists
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/expression.h | 3 +-
src/exthdr.c | 12 ++++++++
src/ipopt.c | 1 +
src/netlink_linearize.c | 2 +-
src/parser_bison.y | 7 +++++
src/tcpopt.c | 42 +++++++++++++++++++++++----
tests/py/any/tcpopt.t | 2 ++
tests/py/any/tcpopt.t.payload | 53 +++--------------------------------
8 files changed, 65 insertions(+), 57 deletions(-)
diff --git a/include/expression.h b/include/expression.h
index 2e41aa0..b50183d 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -299,7 +299,8 @@ struct expr {
/* EXPR_EXTHDR */
const struct exthdr_desc *desc;
const struct proto_hdr_template *tmpl;
- unsigned int offset;
+ uint16_t offset;
+ uint8_t raw_type;
enum nft_exthdr_op op;
unsigned int flags;
} exthdr;
diff --git a/src/exthdr.c b/src/exthdr.c
index c28213f..68d5aa5 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -32,6 +32,13 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
*/
unsigned int offset = expr->exthdr.offset / 64;
+ if (expr->exthdr.desc == NULL &&
+ expr->exthdr.offset == 0 &&
+ expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
+ nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
+ return;
+ }
+
nft_print(octx, "tcp option %s", expr->exthdr.desc->name);
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
return;
@@ -59,6 +66,7 @@ static bool exthdr_expr_cmp(const struct expr *e1, const struct expr *e2)
return e1->exthdr.desc == e2->exthdr.desc &&
e1->exthdr.tmpl == e2->exthdr.tmpl &&
e1->exthdr.op == e2->exthdr.op &&
+ e1->exthdr.raw_type == e2->exthdr.raw_type &&
e1->exthdr.flags == e2->exthdr.flags;
}
@@ -69,6 +77,7 @@ static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
new->exthdr.offset = expr->exthdr.offset;
new->exthdr.op = expr->exthdr.op;
new->exthdr.flags = expr->exthdr.flags;
+ new->exthdr.raw_type = expr->exthdr.raw_type;
}
const struct expr_ops exthdr_expr_ops = {
@@ -98,6 +107,7 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
BYTEORDER_BIG_ENDIAN, tmpl->len);
expr->exthdr.desc = desc;
+ expr->exthdr.raw_type = desc ? desc->type : 0;
expr->exthdr.tmpl = tmpl;
expr->exthdr.offset = tmpl->offset;
return expr;
@@ -176,6 +186,8 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
unsigned int i;
assert(expr->etype == EXPR_EXTHDR);
+ expr->exthdr.raw_type = type;
+
if (op == NFT_EXTHDR_OP_TCPOPT)
return tcpopt_init_raw(expr, type, offset, len, flags);
if (op == NFT_EXTHDR_OP_IPV4)
diff --git a/src/ipopt.c b/src/ipopt.c
index 7ecb8b9..5f9f908 100644
--- a/src/ipopt.c
+++ b/src/ipopt.c
@@ -103,6 +103,7 @@ struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type,
expr->exthdr.tmpl = tmpl;
expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
expr->exthdr.offset = tmpl->offset + calc_offset(desc, tmpl, ptr);
+ expr->exthdr.raw_type = desc->type;
return expr;
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 9d1a064..28b0e6a 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -174,7 +174,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
nle = alloc_nft_expr("exthdr");
netlink_put_register(nle, NFTNL_EXPR_EXTHDR_DREG, dreg);
nftnl_expr_set_u8(nle, NFTNL_EXPR_EXTHDR_TYPE,
- expr->exthdr.desc->type);
+ expr->exthdr.raw_type);
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OFFSET, offset / BITS_PER_BYTE);
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
div_round_up(expr->len, BITS_PER_BYTE));
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 114b289..4ea9364 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4744,6 +4744,13 @@ tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
| SACK3 { $$ = TCPOPT_KIND_SACK3; }
| ECHO { $$ = TCPOPT_KIND_ECHO; }
| TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
+ | NUM {
+ if ($1 > 255) {
+ erec_queue(error(&@1, "value too large"), state->msgs);
+ YYERROR;
+ }
+ $$ = $1;
+ }
;
tcp_hdr_option_field : KIND { $$ = TCPOPT_COMMON_KIND; }
diff --git a/src/tcpopt.c b/src/tcpopt.c
index d1dd13b..1cf97a5 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -103,6 +103,19 @@ const struct exthdr_desc *tcpopt_protocols[] = {
[TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
};
+/**
+ * tcpopt_expr_alloc - allocate tcp option extension expression
+ *
+ * @loc: location from parser
+ * @kind: raw tcp option value to find in packet
+ * @field: highlevel field to find in the option if @kind is present in packet
+ *
+ * Allocate a new tcp option expression.
+ * @kind is the raw option value to find in the packet.
+ * Exception: SACK may use extra OOB data that is mangled here.
+ *
+ * @field is the optional field to extract from the @type option.
+ */
struct expr *tcpopt_expr_alloc(const struct location *loc,
unsigned int kind,
unsigned int field)
@@ -138,8 +151,22 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
if (kind < array_size(tcpopt_protocols))
desc = tcpopt_protocols[kind];
- if (!desc)
- return NULL;
+ if (!desc) {
+ if (field != TCPOPT_COMMON_KIND || kind > 255)
+ return NULL;
+
+ expr = expr_alloc(loc, EXPR_EXTHDR, &integer_type,
+ BYTEORDER_BIG_ENDIAN, 8);
+
+ desc = tcpopt_protocols[TCPOPT_NOP];
+ tmpl = &desc->templates[field];
+ expr->exthdr.desc = desc;
+ expr->exthdr.tmpl = tmpl;
+ expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
+ expr->exthdr.raw_type = kind;
+ return expr;
+ }
+
tmpl = &desc->templates[field];
if (!tmpl)
return NULL;
@@ -149,6 +176,7 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
expr->exthdr.desc = desc;
expr->exthdr.tmpl = tmpl;
expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
+ expr->exthdr.raw_type = desc->type;
expr->exthdr.offset = tmpl->offset;
return expr;
@@ -165,6 +193,10 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
expr->len = len;
expr->exthdr.flags = flags;
expr->exthdr.offset = off;
+ expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
+
+ if (flags & NFT_EXTHDR_F_PRESENT)
+ datatype_set(expr, &boolean_type);
if (type >= array_size(tcpopt_protocols))
return;
@@ -178,12 +210,10 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
if (tmpl->offset != off || tmpl->len != len)
continue;
- if (flags & NFT_EXTHDR_F_PRESENT)
- datatype_set(expr, &boolean_type);
- else
+ if ((flags & NFT_EXTHDR_F_PRESENT) == 0)
datatype_set(expr, tmpl->dtype);
+
expr->exthdr.tmpl = tmpl;
- expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
break;
}
}
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
index 1d42de8..7b17014 100644
--- a/tests/py/any/tcpopt.t
+++ b/tests/py/any/tcpopt.t
@@ -30,6 +30,7 @@ tcp option timestamp kind 1;ok
tcp option timestamp length 1;ok
tcp option timestamp tsval 1;ok
tcp option timestamp tsecr 1;ok
+tcp option 255 missing;ok
tcp option foobar;fail
tcp option foo bar;fail
@@ -38,6 +39,7 @@ tcp option eol left 1;fail
tcp option eol left 1;fail
tcp option sack window;fail
tcp option sack window 1;fail
+tcp option 256 exists;fail
tcp option window exists;ok
tcp option window missing;ok
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
index 9c480c8..34f8e26 100644
--- a/tests/py/any/tcpopt.t.payload
+++ b/tests/py/any/tcpopt.t.payload
@@ -509,20 +509,6 @@ inet
[ exthdr load tcpopt 4b @ 8 + 2 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
-# tcp option timestamp tsecr 1
-ip
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
- [ cmp eq reg 1 0x01000000 ]
-
-# tcp option timestamp tsecr 1
-ip6
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
- [ cmp eq reg 1 0x01000000 ]
-
# tcp option timestamp tsecr 1
inet
[ meta load l4proto => reg 1 ]
@@ -530,19 +516,12 @@ inet
[ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
-# tcp option window exists
-ip
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
-
-# tcp option window exists
-ip6
+# tcp option 255 missing
+inet
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
+ [ exthdr load tcpopt 1b @ 255 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
# tcp option window exists
inet
@@ -551,20 +530,6 @@ inet
[ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
-# tcp option window missing
-ip
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
- [ cmp eq reg 1 0x00000000 ]
-
-# tcp option window missing
-ip6
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
- [ cmp eq reg 1 0x00000000 ]
-
# tcp option window missing
inet
[ meta load l4proto => reg 1 ]
@@ -572,16 +537,6 @@ inet
[ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
[ cmp eq reg 1 0x00000000 ]
-# tcp option maxseg size set 1360
-ip
- [ immediate reg 1 0x00005005 ]
- [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
-
-# tcp option maxseg size set 1360
-ip6
- [ immediate reg 1 0x00005005 ]
- [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
-
# tcp option maxseg size set 1360
inet
[ immediate reg 1 0x00005005 ]
--
2.31.1

View File

@ -0,0 +1,137 @@
From 267d86b62132a009badd57b2ffcffed6ae682a1e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] tcp: add raw tcp option match support
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 881d8cb21c0b9
commit 881d8cb21c0b9168787b932f41b801593bde2216
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 2 20:10:25 2020 +0100
tcp: add raw tcp option match support
tcp option @42,16,4 (@kind,offset,length).
Signed-off-by: Florian Westphal <fw@strlen.de>
---
doc/payload-expression.txt | 6 ++++++
src/exthdr.c | 13 +++++++++----
src/parser_bison.y | 5 +++++
src/tcpopt.c | 2 ++
tests/py/any/tcpopt.t | 2 ++
tests/py/any/tcpopt.t.payload | 7 +++++++
6 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index 3a07321..b6d2a28 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -591,6 +591,12 @@ TCP Timestamps |
kind, length, tsval, tsecr
|============================
+TCP option matching also supports raw expression syntax to access arbitrary options:
+[verse]
+*tcp option*
+[verse]
+*tcp option* *@*'number'*,*'offset'*,*'length'
+
.IP Options
[options="header"]
|==================
diff --git a/src/exthdr.c b/src/exthdr.c
index 68d5aa5..5c75720 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -32,10 +32,15 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
*/
unsigned int offset = expr->exthdr.offset / 64;
- if (expr->exthdr.desc == NULL &&
- expr->exthdr.offset == 0 &&
- expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
- nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
+ if (expr->exthdr.desc == NULL) {
+ if (expr->exthdr.offset == 0 &&
+ expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
+ nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
+ return;
+ }
+
+ nft_print(octx, "tcp option @%u,%u,%u", expr->exthdr.raw_type,
+ expr->exthdr.offset, expr->len);
return;
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 4ea9364..5aedc55 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4718,6 +4718,11 @@ tcp_hdr_expr : TCP tcp_hdr_field
$$ = tcpopt_expr_alloc(&@$, $3, TCPOPT_COMMON_KIND);
$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
}
+ | TCP OPTION AT tcp_hdr_option_type COMMA NUM COMMA NUM
+ {
+ $$ = tcpopt_expr_alloc(&@$, $4, 0);
+ tcpopt_init_raw($$, $4, $6, $8, 0);
+ }
;
tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
diff --git a/src/tcpopt.c b/src/tcpopt.c
index 1cf97a5..05b5ee6 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -197,6 +197,8 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
if (flags & NFT_EXTHDR_F_PRESENT)
datatype_set(expr, &boolean_type);
+ else
+ datatype_set(expr, &integer_type);
if (type >= array_size(tcpopt_protocols))
return;
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
index 7b17014..e759ac6 100644
--- a/tests/py/any/tcpopt.t
+++ b/tests/py/any/tcpopt.t
@@ -31,6 +31,7 @@ tcp option timestamp length 1;ok
tcp option timestamp tsval 1;ok
tcp option timestamp tsecr 1;ok
tcp option 255 missing;ok
+tcp option @255,8,8 255;ok
tcp option foobar;fail
tcp option foo bar;fail
@@ -40,6 +41,7 @@ tcp option eol left 1;fail
tcp option sack window;fail
tcp option sack window 1;fail
tcp option 256 exists;fail
+tcp option @255,8,8 256;fail
tcp option window exists;ok
tcp option window missing;ok
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
index 34f8e26..cddba61 100644
--- a/tests/py/any/tcpopt.t.payload
+++ b/tests/py/any/tcpopt.t.payload
@@ -523,6 +523,13 @@ inet
[ exthdr load tcpopt 1b @ 255 + 0 present => reg 1 ]
[ cmp eq reg 1 0x00000000 ]
+# tcp option @255,8,8 255
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ exthdr load tcpopt 1b @ 255 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
# tcp option window exists
inet
[ meta load l4proto => reg 1 ]
--
2.31.1

View File

@ -0,0 +1,199 @@
From ad566e27398e81ed803c4225179bb8df4718a2e9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 17:44:08 +0200
Subject: [PATCH] json: tcp: add raw tcp option match support
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit cb21869649208
commit cb21869649208118ed61354e2674858e4ff6c23c
Author: Florian Westphal <fw@strlen.de>
Date: Tue Nov 3 12:04:20 2020 +0100
json: tcp: add raw tcp option match support
To similar change as in previous one, this time for the
jason (de)serialization.
Re-uses the raw payload match syntax, i.e. base,offset,length.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/json.c | 22 ++++++++--------
src/parser_json.c | 52 ++++++++++++++++++++++++++------------
tests/py/any/tcpopt.t.json | 34 +++++++++++++++++++++++++
3 files changed, 82 insertions(+), 26 deletions(-)
diff --git a/src/json.c b/src/json.c
index 1906e7d..b77c6d2 100644
--- a/src/json.c
+++ b/src/json.c
@@ -656,30 +656,32 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
{
const char *desc = expr->exthdr.desc ?
- expr->exthdr.desc->name :
- "unknown-exthdr";
+ expr->exthdr.desc->name : NULL;
const char *field = expr->exthdr.tmpl->token;
json_t *root;
bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT;
if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
+ static const char *offstrs[] = { "", "1", "2", "3" };
unsigned int offset = expr->exthdr.offset / 64;
+ const char *offstr = "";
- if (offset) {
- const char *offstrs[] = { "0", "1", "2", "3" };
- const char *offstr = "";
-
+ if (desc) {
if (offset < 4)
offstr = offstrs[offset];
root = json_pack("{s:s+}", "name", desc, offstr);
+
+ if (!is_exists)
+ json_object_set_new(root, "field", json_string(field));
} else {
- root = json_pack("{s:s}", "name", desc);
+ root = json_pack("{s:i, s:i, s:i}",
+ "base", expr->exthdr.raw_type,
+ "offset", expr->exthdr.offset,
+ "len", expr->len);
+ is_exists = false;
}
- if (!is_exists)
- json_object_set_new(root, "field", json_string(field));
-
return json_pack("{s:o}", "tcp option", root);
}
if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
diff --git a/src/parser_json.c b/src/parser_json.c
index ab2375f..fbf7db5 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -500,6 +500,8 @@ static int json_parse_tcp_option_field(int type, const char *name, int *val)
return 1;
desc = tcpopt_protocols[type];
+ if (!desc)
+ return 1;
for (i = 0; i < array_size(desc->templates); i++) {
if (desc->templates[i].token &&
@@ -599,30 +601,48 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx,
static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
const char *type, json_t *root)
{
+ int fieldval, kind, offset, len;
const char *desc, *field;
- int descval, fieldval;
struct expr *expr;
- if (json_unpack_err(ctx, root, "{s:s}", "name", &desc))
- return NULL;
-
- if (json_parse_tcp_option_type(desc, &descval)) {
- json_error(ctx, "Unknown tcp option name '%s'.", desc);
- return NULL;
- }
+ if (!json_unpack(root, "{s:i, s:i, s:i}",
+ "base", &kind, "offset", &offset, "len", &len)) {
+ uint32_t flag = 0;
- if (json_unpack(root, "{s:s}", "field", &field)) {
- expr = tcpopt_expr_alloc(int_loc, descval,
+ expr = tcpopt_expr_alloc(int_loc, kind,
TCPOPT_COMMON_KIND);
- expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+ if (kind < 0 || kind > 255)
+ return NULL;
+
+ if (offset == TCPOPT_COMMON_KIND && len == 8)
+ flag = NFT_EXTHDR_F_PRESENT;
+
+ tcpopt_init_raw(expr, kind, offset, len, flag);
return expr;
+ } else if (!json_unpack(root, "{s:s}", "name", &desc)) {
+ if (json_parse_tcp_option_type(desc, &kind)) {
+ json_error(ctx, "Unknown tcp option name '%s'.", desc);
+ return NULL;
+ }
+
+ if (json_unpack(root, "{s:s}", "field", &field)) {
+ expr = tcpopt_expr_alloc(int_loc, kind,
+ TCPOPT_COMMON_KIND);
+ expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+ return expr;
+ }
+
+ if (json_parse_tcp_option_field(kind, field, &fieldval)) {
+ json_error(ctx, "Unknown tcp option field '%s'.", field);
+ return NULL;
+ }
+
+ return tcpopt_expr_alloc(int_loc, kind, fieldval);
}
- if (json_parse_tcp_option_field(descval, field, &fieldval)) {
- json_error(ctx, "Unknown tcp option field '%s'.", field);
- return NULL;
- }
- return tcpopt_expr_alloc(int_loc, descval, fieldval);
+
+ json_error(ctx, "Invalid tcp option expression properties.");
+ return NULL;
}
static int json_parse_ip_option_type(const char *name, int *val)
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
index b15e36e..139e97d 100644
--- a/tests/py/any/tcpopt.t.json
+++ b/tests/py/any/tcpopt.t.json
@@ -414,6 +414,40 @@
}
]
+# tcp option 255 missing
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "base": 255,
+ "len": 8,
+ "offset": 0
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# tcp option @255,8,8 255
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "base": 255,
+ "len": 8,
+ "offset": 8
+ }
+ },
+ "op": "==",
+ "right": 255
+ }
+ }
+]
+
# tcp option window exists
[
{
--
2.31.1

View File

@ -0,0 +1,57 @@
From 2026f7d056679508f8506fbba7f578aa15af7c05 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 16:32:27 +0200
Subject: [PATCH] json: Simplify non-tcpopt exthdr printing a bit
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit fd81d3ec3ae8b
commit fd81d3ec3ae8b8d1d54a708d63b2dab2c8508c90
Author: Phil Sutter <phil@nwl.cc>
Date: Tue May 4 13:18:11 2021 +0200
json: Simplify non-tcpopt exthdr printing a bit
This was just duplicate code apart from the object's name.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/json.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/src/json.c b/src/json.c
index b77c6d2..a6d0716 100644
--- a/src/json.c
+++ b/src/json.c
@@ -684,21 +684,17 @@ json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
return json_pack("{s:o}", "tcp option", root);
}
- if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
- root = json_pack("{s:s}", "name", desc);
- if (!is_exists)
- json_object_set_new(root, "field", json_string(field));
-
- return json_pack("{s:o}", "ip option", root);
- }
-
- root = json_pack("{s:s}",
- "name", desc);
+ root = json_pack("{s:s}", "name", desc);
if (!is_exists)
json_object_set_new(root, "field", json_string(field));
- return json_pack("{s:o}", "exthdr", root);
+ switch (expr->exthdr.op) {
+ case NFT_EXTHDR_OP_IPV4:
+ return json_pack("{s:o}", "ip option", root);
+ default:
+ return json_pack("{s:o}", "exthdr", root);
+ }
}
json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx)
--
2.31.1

View File

@ -0,0 +1,175 @@
From c724812d9561021fb6a80c817d411d9ba2de5dbd Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 13 Jul 2021 13:54:12 +0200
Subject: [PATCH] scanner: introduce start condition stack
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 5896772fe3c5f
commit 5896772fe3c5f01696188ea04957a825ee601b12
Author: Florian Westphal <fw@strlen.de>
Date: Mon Mar 8 18:18:33 2021 +0100
scanner: introduce start condition stack
Add a small initial chunk of flex start conditionals.
This starts with two low-hanging fruits, numgen and j/symhash.
NUMGEN and HASH start conditions are entered from flex when
the corresponding expression token is encountered.
Flex returns to the INIT condition when the bison parser
has seen a complete numgen/hash statement.
This intentionally uses a stack rather than BEGIN()
to eventually support nested states.
The scanner_pop_start_cond() function argument is not used yet, but
will need to be used later to deal with nesting.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/parser.h | 8 ++++++++
src/parser_bison.y | 11 +++++++----
src/scanner.l | 36 +++++++++++++++++++++++++++++-------
3 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/include/parser.h b/include/parser.h
index 949284d..1d293f5 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -28,6 +28,12 @@ struct parser_state {
struct list_head *cmds;
};
+enum startcond_type {
+ PARSER_SC_BEGIN,
+ PARSER_SC_EXPR_HASH,
+ PARSER_SC_EXPR_NUMGEN,
+};
+
struct mnl_socket;
extern void parser_init(struct nft_ctx *nft, struct parser_state *state,
@@ -47,4 +53,6 @@ extern void scanner_push_buffer(void *scanner,
const struct input_descriptor *indesc,
const char *buffer);
+extern void scanner_pop_start_cond(void *scanner, enum startcond_type sc);
+
#endif /* NFTABLES_PARSER_H */
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 5aedc55..9a9447f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -840,6 +840,9 @@ opt_newline : NEWLINE
| /* empty */
;
+close_scope_hash : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HASH); };
+close_scope_numgen : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_NUMGEN); };
+
common_block : INCLUDE QUOTED_STRING stmt_separator
{
if (scanner_include_file(nft, scanner, $2, &@$) < 0) {
@@ -4249,7 +4252,7 @@ numgen_type : INC { $$ = NFT_NG_INCREMENTAL; }
| RANDOM { $$ = NFT_NG_RANDOM; }
;
-numgen_expr : NUMGEN numgen_type MOD NUM offset_opt
+numgen_expr : NUMGEN numgen_type MOD NUM offset_opt close_scope_numgen
{
$$ = numgen_expr_alloc(&@$, $2, $4, $5);
}
@@ -4306,17 +4309,17 @@ xfrm_expr : IPSEC xfrm_dir xfrm_spnum xfrm_state_key
}
;
-hash_expr : JHASH expr MOD NUM SEED NUM offset_opt
+hash_expr : JHASH expr MOD NUM SEED NUM offset_opt close_scope_hash
{
$$ = hash_expr_alloc(&@$, $4, true, $6, $7, NFT_HASH_JENKINS);
$$->hash.expr = $2;
}
- | JHASH expr MOD NUM offset_opt
+ | JHASH expr MOD NUM offset_opt close_scope_hash
{
$$ = hash_expr_alloc(&@$, $4, false, 0, $5, NFT_HASH_JENKINS);
$$->hash.expr = $2;
}
- | SYMHASH MOD NUM offset_opt
+ | SYMHASH MOD NUM offset_opt close_scope_hash
{
$$ = hash_expr_alloc(&@$, $3, false, 0, $4, NFT_HASH_SYM);
}
diff --git a/src/scanner.l b/src/scanner.l
index 20b1b2d..68fe988 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -98,6 +98,8 @@ static void reset_pos(struct parser_state *state, struct location *loc)
state->indesc->column = 1;
}
+static void scanner_push_start_cond(void *scanner, enum startcond_type type);
+
#define YY_USER_ACTION { \
update_pos(yyget_extra(yyscanner), yylloc, yyleng); \
update_offset(yyget_extra(yyscanner), yylloc, yyleng); \
@@ -193,6 +195,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
%option yylineno
%option nodefault
%option warn
+%option stack
+%s SCANSTATE_EXPR_HASH
+%s SCANSTATE_EXPR_NUMGEN
%%
@@ -548,15 +553,21 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"state" { return STATE; }
"status" { return STATUS; }
-"numgen" { return NUMGEN; }
-"inc" { return INC; }
-"mod" { return MOD; }
-"offset" { return OFFSET; }
+"numgen" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_NUMGEN); return NUMGEN; }
+<SCANSTATE_EXPR_NUMGEN>{
+ "inc" { return INC; }
+}
-"jhash" { return JHASH; }
-"symhash" { return SYMHASH; }
-"seed" { return SEED; }
+"jhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return JHASH; }
+"symhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return SYMHASH; }
+<SCANSTATE_EXPR_HASH>{
+ "seed" { return SEED; }
+}
+<SCANSTATE_EXPR_HASH,SCANSTATE_EXPR_NUMGEN>{
+ "mod" { return MOD; }
+ "offset" { return OFFSET; }
+}
"dup" { return DUP; }
"fwd" { return FWD; }
@@ -949,3 +960,14 @@ void scanner_destroy(struct nft_ctx *nft)
input_descriptor_list_destroy(state);
yylex_destroy(nft->scanner);
}
+
+static void scanner_push_start_cond(void *scanner, enum startcond_type type)
+{
+ yy_push_state((int)type, scanner);
+}
+
+void scanner_pop_start_cond(void *scanner, enum startcond_type t)
+{
+ yy_pop_state(scanner);
+ (void)yy_top_state(scanner); /* suppress gcc warning wrt. unused function */
+}
--
2.31.1

View File

@ -0,0 +1,96 @@
From 595e79b1ccdfa6b11cd6c2b1c8eda0161b58d22a Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 13 Jul 2021 13:54:12 +0200
Subject: [PATCH] scanner: sctp: Move to own scope
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 0925d7e214825
Conflicts: Context change due to missing other scopes.
commit 0925d7e214825628e7db4a86d5ebbad578ab0777
Author: Phil Sutter <phil@nwl.cc>
Date: Tue May 4 13:06:32 2021 +0200
scanner: sctp: Move to own scope
This isolates only "vtag" token for now.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Florian Westphal <fw@strlen.de>
---
include/parser.h | 1 +
src/parser_bison.y | 5 +++--
src/scanner.l | 8 ++++++--
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/parser.h b/include/parser.h
index 1d293f5..2e6ef4d 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -30,6 +30,7 @@ struct parser_state {
enum startcond_type {
PARSER_SC_BEGIN,
+ PARSER_SC_SCTP,
PARSER_SC_EXPR_HASH,
PARSER_SC_EXPR_NUMGEN,
};
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9a9447f..beb5995 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -842,6 +842,7 @@ opt_newline : NEWLINE
close_scope_hash : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HASH); };
close_scope_numgen : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_NUMGEN); };
+close_scope_sctp : { scanner_pop_start_cond(nft->scanner, PARSER_SC_SCTP); };
common_block : INCLUDE QUOTED_STRING stmt_separator
{
@@ -4059,7 +4060,7 @@ primary_rhs_expr : symbol_expr { $$ = $1; }
BYTEORDER_HOST_ENDIAN,
sizeof(data) * BITS_PER_BYTE, &data);
}
- | SCTP
+ | SCTP close_scope_sctp
{
uint8_t data = IPPROTO_SCTP;
$$ = constant_expr_alloc(&@$, &inet_protocol_type,
@@ -4782,7 +4783,7 @@ dccp_hdr_field : SPORT { $$ = DCCPHDR_SPORT; }
| TYPE { $$ = DCCPHDR_TYPE; }
;
-sctp_hdr_expr : SCTP sctp_hdr_field
+sctp_hdr_expr : SCTP sctp_hdr_field close_scope_sctp
{
$$ = payload_expr_alloc(&@$, &proto_sctp, $2);
}
diff --git a/src/scanner.l b/src/scanner.l
index 68fe988..b79ae55 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -196,6 +196,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
%option nodefault
%option warn
%option stack
+%s SCANSTATE_SCTP
%s SCANSTATE_EXPR_HASH
%s SCANSTATE_EXPR_NUMGEN
@@ -488,8 +489,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"dccp" { return DCCP; }
-"sctp" { return SCTP; }
-"vtag" { return VTAG; }
+"sctp" { scanner_push_start_cond(yyscanner, SCANSTATE_SCTP); return SCTP; }
+
+<SCANSTATE_SCTP>{
+ "vtag" { return VTAG; }
+}
"rt" { return RT; }
"rt0" { return RT0; }
--
2.31.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
From 7ba8ea2cf06230e647b096f40d3006abec45f801 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 16:33:20 +0200
Subject: [PATCH] include: missing sctp_chunk.h in Makefile.am
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
Upstream Status: nftables commit 117ceb4f52711
commit 117ceb4f527119a6d44bf5e23f2ff7a8d116658a
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue May 25 14:04:36 2021 +0200
include: missing sctp_chunk.h in Makefile.am
Fix make distcheck.
Fixes: 0e3871cfd9a1 ("exthdr: Implement SCTP Chunk matching")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/Makefile.am | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/Makefile.am b/include/Makefile.am
index 04a4a61..4ee5124 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -30,6 +30,7 @@ noinst_HEADERS = cli.h \
osf.h \
parser.h \
proto.h \
+ sctp_chunk.h \
socket.h \
rule.h \
rt.h \
--
2.31.1

View File

@ -0,0 +1,71 @@
From 5a735f26b0c6617b2851a7399c8ad118e89deba8 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 12 Jul 2021 16:34:38 +0200
Subject: [PATCH] doc: nft.8: Extend monitor description by trace
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820365
Upstream Status: nftables commit 2acf8b2caea19
commit 2acf8b2caea19d8abd46d475a908f8d6afb33aa0
Author: Phil Sutter <phil@nwl.cc>
Date: Wed May 19 13:12:48 2021 +0200
doc: nft.8: Extend monitor description by trace
Briefly describe 'nft monitor trace' command functionality.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
doc/nft.txt | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/doc/nft.txt b/doc/nft.txt
index abb9260..9cc35ee 100644
--- a/doc/nft.txt
+++ b/doc/nft.txt
@@ -734,13 +734,26 @@ These are some additional commands included in nft.
MONITOR
~~~~~~~~
The monitor command allows you to listen to Netlink events produced by the
-nf_tables subsystem, related to creation and deletion of objects. When they
+nf_tables subsystem. These are either related to creation and deletion of
+objects or to packets for which *meta nftrace* was enabled. When they
occur, nft will print to stdout the monitored events in either JSON or
native nft format. +
-To filter events related to a concrete object, use one of the keywords 'tables', 'chains', 'sets', 'rules', 'elements', 'ruleset'. +
+[verse]
+____
+*monitor* [*new* | *destroy*] 'MONITOR_OBJECT'
+*monitor* *trace*
+
+'MONITOR_OBJECT' := *tables* | *chains* | *sets* | *rules* | *elements* | *ruleset*
+____
+
+To filter events related to a concrete object, use one of the keywords in
+'MONITOR_OBJECT'.
-To filter events related to a concrete action, use keyword 'new' or 'destroy'.
+To filter events related to a concrete action, use keyword *new* or *destroy*.
+
+The second form of invocation takes no further options and exclusively prints
+events generated for packets with *nftrace* enabled.
Hit ^C to finish the monitor operation.
@@ -764,6 +777,12 @@ Hit ^C to finish the monitor operation.
% nft monitor ruleset
---------------------
+.Trace incoming packets from host 10.0.0.1
+------------------------------------------
+% nft add rule filter input ip saddr 10.0.0.1 meta nftrace set 1
+% nft monitor trace
+------------------------------------------
+
ERROR REPORTING
---------------
When an error is detected, nft shows the line(s) containing the error, the
--
2.31.1

View File

@ -0,0 +1,44 @@
From e8300966510001e38f2b6530607bac2a93de5c2e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 2 Aug 2021 14:35:08 +0200
Subject: [PATCH] tests: shell: Fix bogus testsuite failure with 100Hz
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
Upstream Status: nftables commit c9c5b5f621c37
commit c9c5b5f621c37d17140dac682d211825ef321093
Author: Phil Sutter <phil@nwl.cc>
Date: Mon Jul 26 15:27:32 2021 +0200
tests: shell: Fix bogus testsuite failure with 100Hz
On kernels with CONFIG_HZ=100, clock granularity does not allow tracking
timeouts in single digit ms range. Change sets/0031set_timeout_size_0 to
not expose this detail.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Florian Westphal <fw@strlen.de>
---
tests/shell/testcases/sets/0031set_timeout_size_0 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/shell/testcases/sets/0031set_timeout_size_0 b/tests/shell/testcases/sets/0031set_timeout_size_0
index 9edd5f6..796640d 100755
--- a/tests/shell/testcases/sets/0031set_timeout_size_0
+++ b/tests/shell/testcases/sets/0031set_timeout_size_0
@@ -3,10 +3,10 @@
RULESET="add table x
add set x y { type ipv4_addr; size 128; timeout 30s; flags dynamic; }
add chain x test
-add rule x test set update ip saddr timeout 1d2h3m4s8ms @y
+add rule x test set update ip saddr timeout 1d2h3m4s10ms @y
add rule x test set update ip daddr timeout 100ms @y"
set -e
$NFT -f - <<< "$RULESET"
-$NFT list chain x test | grep -q 'update @y { ip saddr timeout 1d2h3m4s8ms }'
+$NFT list chain x test | grep -q 'update @y { ip saddr timeout 1d2h3m4s10ms }'
$NFT list chain x test | grep -q 'update @y { ip daddr timeout 100ms }'
--
2.31.1

View File

@ -0,0 +1,100 @@
From 8cb078a2f9f69259325c10f479c198349ef01ef2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 6 Oct 2021 17:24:44 +0200
Subject: [PATCH] parser_json: Fix error reporting for invalid syntax
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1994141
Upstream Status: nftables commit 9fe5d1bc18cfa
commit 9fe5d1bc18cfaed2ecf717e3dd9a97ff5b0e183c
Author: Phil Sutter <phil@nwl.cc>
Date: Wed Sep 1 16:41:44 2021 +0200
parser_json: Fix error reporting for invalid syntax
Errors emitted by the JSON parser caused BUG() in erec_print() due to
input descriptor values being bogus.
Due to lack of 'include' support, JSON parser uses a single input
descriptor only and it lived inside the json_ctx object on stack of
nft_parse_json_*() functions.
By the time errors are printed though, that scope is not valid anymore.
Move the static input descriptor object to avoid this.
Fixes: 586ad210368b7 ("libnftables: Implement JSON parser")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_json.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/parser_json.c b/src/parser_json.c
index a069a89..ef4d4fb 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -44,7 +44,6 @@
#define CTX_F_CONCAT (1 << 8) /* inside concat_expr */
struct json_ctx {
- struct input_descriptor indesc;
struct nft_ctx *nft;
struct list_head *msgs;
struct list_head *cmds;
@@ -107,11 +106,12 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root);
/* parsing helpers */
const struct location *int_loc = &internal_location;
+static struct input_descriptor json_indesc;
static void json_lib_error(struct json_ctx *ctx, json_error_t *err)
{
struct location loc = {
- .indesc = &ctx->indesc,
+ .indesc = &json_indesc,
.line_offset = err->position - err->column,
.first_line = err->line,
.last_line = err->line,
@@ -3864,16 +3864,15 @@ int nft_parse_json_buffer(struct nft_ctx *nft, const char *buf,
struct list_head *msgs, struct list_head *cmds)
{
struct json_ctx ctx = {
- .indesc = {
- .type = INDESC_BUFFER,
- .data = buf,
- },
.nft = nft,
.msgs = msgs,
.cmds = cmds,
};
int ret;
+ json_indesc.type = INDESC_BUFFER;
+ json_indesc.data = buf;
+
parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_loads(buf, 0, NULL);
if (!nft->json_root)
@@ -3892,10 +3891,6 @@ int nft_parse_json_filename(struct nft_ctx *nft, const char *filename,
struct list_head *msgs, struct list_head *cmds)
{
struct json_ctx ctx = {
- .indesc = {
- .type = INDESC_FILE,
- .name = filename,
- },
.nft = nft,
.msgs = msgs,
.cmds = cmds,
@@ -3903,6 +3898,9 @@ int nft_parse_json_filename(struct nft_ctx *nft, const char *filename,
json_error_t err;
int ret;
+ json_indesc.type = INDESC_FILE;
+ json_indesc.name = filename;
+
parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_load_file(filename, 0, &err);
if (!nft->json_root)
--
2.31.1

View File

@ -0,0 +1,37 @@
From bb4718fa421938c4a501b9a55df68de16a572f23 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 6 Oct 2021 17:32:04 +0200
Subject: [PATCH] parser_bison: Fix for implicit declaration of isalnum
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999059
Upstream Status: nftables commit 7c3b2a7acbdc7
commit 7c3b2a7acbdc793b822a230ec0c28086c7d0365d
Author: Phil Sutter <phil@nwl.cc>
Date: Fri Jun 11 16:03:32 2021 +0200
parser_bison: Fix for implicit declaration of isalnum
Have to include ctype.h to make it known.
Fixes: e76bb37940181 ("src: allow for variables in the log prefix string")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_bison.y | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 5ab5744..d38ec30 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -10,6 +10,7 @@
%{
+#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <inttypes.h>
--
2.31.1

View File

@ -0,0 +1,46 @@
From 99d51194569f2784261f452ee821c42c3a7a6808 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 6 Oct 2021 17:32:04 +0200
Subject: [PATCH] parser_json: Fix for memleak in tcp option error path
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999059
Upstream Status: nftables commit f7b0eef8391ae
commit f7b0eef8391ae7f89a3a82f6eeecaebe199224d7
Author: Phil Sutter <phil@nwl.cc>
Date: Fri Jun 11 16:07:02 2021 +0200
parser_json: Fix for memleak in tcp option error path
If 'kind' value is invalid, the function returned without freeing 'expr'
first. Fix this by performing the check before allocation.
Fixes: cb21869649208 ("json: tcp: add raw tcp option match support")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/parser_json.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/parser_json.c b/src/parser_json.c
index ef4d4fb..2250be9 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -610,12 +610,12 @@ static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
"base", &kind, "offset", &offset, "len", &len)) {
uint32_t flag = 0;
- expr = tcpopt_expr_alloc(int_loc, kind,
- TCPOPT_COMMON_KIND);
-
if (kind < 0 || kind > 255)
return NULL;
+ expr = tcpopt_expr_alloc(int_loc, kind,
+ TCPOPT_COMMON_KIND);
+
if (offset == TCPOPT_COMMON_KIND && len == 8)
flag = NFT_EXTHDR_F_PRESENT;
--
2.31.1

View File

@ -0,0 +1,37 @@
From 5f30a3447d28381fdf534ff4ed90167455d1283b Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 6 Oct 2021 17:32:04 +0200
Subject: [PATCH] json: Drop pointless assignment in exthdr_expr_json()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999059
Upstream Status: nftables commit c1616dfd1ce40
commit c1616dfd1ce40bac197924c8947e1c646e915dca
Author: Phil Sutter <phil@nwl.cc>
Date: Fri Jun 11 16:23:22 2021 +0200
json: Drop pointless assignment in exthdr_expr_json()
The updated value of 'is_exists' is no longer read at this point.
Fixes: cb21869649208 ("json: tcp: add raw tcp option match support")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/json.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/json.c b/src/json.c
index dfc9031..ecec51c 100644
--- a/src/json.c
+++ b/src/json.c
@@ -679,7 +679,6 @@ json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
"base", expr->exthdr.raw_type,
"offset", expr->exthdr.offset,
"len", expr->len);
- is_exists = false;
}
return json_pack("{s:o}", "tcp option", root);
--
2.31.1

View File

@ -0,0 +1,69 @@
From 36cf5177c724540aea5a42f9dc6ef5476f86179a Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 5 Nov 2021 16:06:45 +0100
Subject: [PATCH] segtree: Fix segfault when restoring a huge interval set
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1908127
Upstream Status: nftables commit baecd1cf26851
commit baecd1cf26851a4c5b7d469206a488f14fe5b147
Author: Phil Sutter <phil@nwl.cc>
Date: Wed Jun 9 15:49:52 2021 +0200
segtree: Fix segfault when restoring a huge interval set
Restoring a set of IPv4 prefixes with about 1.1M elements crashes nft as
set_to_segtree() exhausts the stack. Prevent this by allocating the
pointer array on heap and make sure it is freed before returning to
caller.
With this patch in place, restoring said set succeeds with allocation of
about 3GB of memory, according to valgrind.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/segtree.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/segtree.c b/src/segtree.c
index d6e3ce2..b852961 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -414,10 +414,10 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
struct expr *init, struct seg_tree *tree,
bool add, bool merge)
{
- struct elementary_interval *intervals[init->size];
+ struct elementary_interval **intervals;
struct expr *i, *next;
unsigned int n;
- int err;
+ int err = 0;
/* We are updating an existing set with new elements, check if the new
* interval overlaps with any of the existing ones.
@@ -428,6 +428,7 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
return err;
}
+ intervals = xmalloc_array(init->size, sizeof(intervals[0]));
n = expr_to_intervals(init, tree->keylen, intervals);
list_for_each_entry_safe(i, next, &init->expressions, list) {
@@ -446,10 +447,11 @@ static int set_to_segtree(struct list_head *msgs, struct set *set,
for (n = 0; n < init->size; n++) {
err = ei_insert(msgs, tree, intervals[n], merge);
if (err < 0)
- return err;
+ break;
}
- return 0;
+ xfree(intervals);
+ return err;
}
static bool segtree_needs_first_segment(const struct set *set,
--
2.31.1

View File

@ -0,0 +1,74 @@
From cc6c59e683c503b461b4a80526f4bc9cbb0660bf Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 5 Nov 2021 16:06:45 +0100
Subject: [PATCH] tests: cover baecd1cf2685 ("segtree: Fix segfault when
restoring a huge interval set")
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1908127
Upstream Status: nftables commit d8ccad2a2b73c
commit d8ccad2a2b73c4189934eb5fd0e3d096699b5043
Author: Štěpán Němec <snemec@redhat.com>
Date: Wed Oct 20 14:42:20 2021 +0200
tests: cover baecd1cf2685 ("segtree: Fix segfault when restoring a huge interval set")
Test inspired by [1] with both the set and stack size reduced by the
same power of 2, to preserve the (pre-baecd1cf2685) segfault on one
hand, and make the test successfully complete (post-baecd1cf2685) in a
few seconds even on weaker hardware on the other.
(The reason I stopped at 128kB stack size is that with 64kB I was
getting segfaults even with baecd1cf2685 applied.)
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1908127
Signed-off-by: Štěpán Němec <snemec@redhat.com>
Helped-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
.../sets/0068interval_stack_overflow_0 | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100755 tests/shell/testcases/sets/0068interval_stack_overflow_0
diff --git a/tests/shell/testcases/sets/0068interval_stack_overflow_0 b/tests/shell/testcases/sets/0068interval_stack_overflow_0
new file mode 100755
index 0000000..134282d
--- /dev/null
+++ b/tests/shell/testcases/sets/0068interval_stack_overflow_0
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -e
+
+ruleset_file=$(mktemp)
+
+trap 'rm -f "$ruleset_file"' EXIT
+
+{
+ echo 'define big_set = {'
+ for ((i = 1; i < 255; i++)); do
+ for ((j = 1; j < 80; j++)); do
+ echo "10.0.$i.$j,"
+ done
+ done
+ echo '10.1.0.0/24 }'
+} >"$ruleset_file"
+
+cat >>"$ruleset_file" <<\EOF
+table inet test68_table {
+ set test68_set {
+ type ipv4_addr
+ flags interval
+ elements = { $big_set }
+ }
+}
+EOF
+
+( ulimit -s 128 && "$NFT" -f "$ruleset_file" )
--
2.31.1

View File

@ -0,0 +1,58 @@
From ea4457d5c329c8930c610ef3002cfe42bf8a263f Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 8 Dec 2021 14:10:31 +0100
Subject: [PATCH] tests: shell: $NFT needs to be invoked unquoted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1908127
Upstream Status: nftables commit dad3338f1f76a
Conflicts: Context change in README due to missing other commits.
commit dad3338f1f76a4a5bd782bae9c6b48941dfb1e31
Author: Štěpán Němec <snemec@redhat.com>
Date: Fri Nov 5 12:39:11 2021 +0100
tests: shell: $NFT needs to be invoked unquoted
The variable has to undergo word splitting, otherwise the shell tries
to find the variable value as an executable, which breaks in cases that
7c8a44b25c22 ("tests: shell: Allow wrappers to be passed as nft command")
intends to support.
Mention this in the shell tests README.
Fixes: d8ccad2a2b73 ("tests: cover baecd1cf2685 ("segtree: Fix segfault when restoring a huge interval set")")
Signed-off-by: Štěpán Němec <snemec@redhat.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
tests/shell/README | 3 +++
tests/shell/testcases/sets/0068interval_stack_overflow_0 | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/shell/README b/tests/shell/README
index e0279bb..aee50e3 100644
--- a/tests/shell/README
+++ b/tests/shell/README
@@ -25,4 +25,7 @@ path to the nftables binary being tested.
You can pass an arbitrary $NFT value as well:
# NFT=/usr/local/sbin/nft ./run-tests.sh
+Note that, to support usage such as NFT='valgrind nft', tests must
+invoke $NFT unquoted.
+
By default the tests are run with the nft binary at '../../src/nft'
diff --git a/tests/shell/testcases/sets/0068interval_stack_overflow_0 b/tests/shell/testcases/sets/0068interval_stack_overflow_0
index 134282d..6620572 100755
--- a/tests/shell/testcases/sets/0068interval_stack_overflow_0
+++ b/tests/shell/testcases/sets/0068interval_stack_overflow_0
@@ -26,4 +26,4 @@ table inet test68_table {
}
EOF
-( ulimit -s 128 && "$NFT" -f "$ruleset_file" )
+( ulimit -s 128 && $NFT -f "$ruleset_file" )
--
2.31.1

View File

@ -0,0 +1,59 @@
From b297f75275737de3e16b5d14916efe35535b6279 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 8 Dec 2021 14:10:54 +0100
Subject: [PATCH] tests: shell: better parameters for the interval stack
overflow test
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1908127
Upstream Status: nftables commit 7b81d9cb094ff
commit 7b81d9cb094ffa96ad821528cf19269dc348f617
Author: Štěpán Němec <snemec@redhat.com>
Date: Wed Dec 1 12:12:00 2021 +0100
tests: shell: better parameters for the interval stack overflow test
Wider testing has shown that 128 kB stack is too low (e.g. for systems
with 64 kB page size), leading to false failures in some environments.
Based on results from a matrix of RHEL 8 and RHEL 9 systems across
x86_64, aarch64, ppc64le and s390x architectures as well as some
anecdotal testing of other Linux distros on x86_64 machines, 400 kB
seems safe: the normal nft stack (which should stay constant during
this test) on all tested systems doesn't exceed 200 kB (stays around
100 kB on typical systems with 4 kB page size), while always growing
beyond 500 kB in the failing case (nftables before baecd1cf2685) with
the increased set size.
Fixes: d8ccad2a2b73 ("tests: cover baecd1cf2685 ("segtree: Fix segfault when restoring a huge interval set")")
Signed-off-by: Štěpán Němec <snemec@redhat.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
tests/shell/testcases/sets/0068interval_stack_overflow_0 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/shell/testcases/sets/0068interval_stack_overflow_0 b/tests/shell/testcases/sets/0068interval_stack_overflow_0
index 6620572..2cbc986 100755
--- a/tests/shell/testcases/sets/0068interval_stack_overflow_0
+++ b/tests/shell/testcases/sets/0068interval_stack_overflow_0
@@ -9,7 +9,7 @@ trap 'rm -f "$ruleset_file"' EXIT
{
echo 'define big_set = {'
for ((i = 1; i < 255; i++)); do
- for ((j = 1; j < 80; j++)); do
+ for ((j = 1; j < 255; j++)); do
echo "10.0.$i.$j,"
done
done
@@ -26,4 +26,4 @@ table inet test68_table {
}
EOF
-( ulimit -s 128 && $NFT -f "$ruleset_file" )
+( ulimit -s 400 && $NFT -f "$ruleset_file" )
--
2.31.1

View File

@ -0,0 +1,134 @@
From cf85778a263a34aa2aeee565f3e046693164a097 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Thu, 13 Jan 2022 20:37:56 +0100
Subject: [PATCH] netlink: remove unused parameter from
netlink_gen_stmt_stateful()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594
Upstream Status: nftables commit 3f3e897f42965
commit 3f3e897f429659ff6c8387245d0d4115952a6c31
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed Mar 11 13:02:26 2020 +0100
netlink: remove unused parameter from netlink_gen_stmt_stateful()
Remove context from netlink_gen_stmt_stateful().
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/netlink_linearize.c | 36 +++++++++++++-----------------------
1 file changed, 13 insertions(+), 23 deletions(-)
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 28b0e6a..f5c6116 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -780,9 +780,7 @@ static void netlink_gen_objref_stmt(struct netlink_linearize_ctx *ctx,
nftnl_rule_add_expr(ctx->nlr, nle);
}
-static struct nftnl_expr *
-netlink_gen_connlimit_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
+static struct nftnl_expr *netlink_gen_connlimit_stmt(const struct stmt *stmt)
{
struct nftnl_expr *nle;
@@ -795,9 +793,7 @@ netlink_gen_connlimit_stmt(struct netlink_linearize_ctx *ctx,
return nle;
}
-static struct nftnl_expr *
-netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
+static struct nftnl_expr *netlink_gen_counter_stmt(const struct stmt *stmt)
{
struct nftnl_expr *nle;
@@ -814,9 +810,7 @@ netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx,
return nle;
}
-static struct nftnl_expr *
-netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
+static struct nftnl_expr *netlink_gen_limit_stmt(const struct stmt *stmt)
{
struct nftnl_expr *nle;
@@ -832,9 +826,7 @@ netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
return nle;
}
-static struct nftnl_expr *
-netlink_gen_quota_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
+static struct nftnl_expr *netlink_gen_quota_stmt(const struct stmt *stmt)
{
struct nftnl_expr *nle;
@@ -846,19 +838,17 @@ netlink_gen_quota_stmt(struct netlink_linearize_ctx *ctx,
return nle;
}
-static struct nftnl_expr *
-netlink_gen_stmt_stateful(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
+static struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt)
{
switch (stmt->ops->type) {
case STMT_CONNLIMIT:
- return netlink_gen_connlimit_stmt(ctx, stmt);
+ return netlink_gen_connlimit_stmt(stmt);
case STMT_COUNTER:
- return netlink_gen_counter_stmt(ctx, stmt);
+ return netlink_gen_counter_stmt(stmt);
case STMT_LIMIT:
- return netlink_gen_limit_stmt(ctx, stmt);
+ return netlink_gen_limit_stmt(stmt);
case STMT_QUOTA:
- return netlink_gen_quota_stmt(ctx, stmt);
+ return netlink_gen_quota_stmt(stmt);
default:
BUG("unknown stateful statement type %s\n", stmt->ops->name);
}
@@ -1307,7 +1297,7 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
if (stmt->set.stmt)
nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
- netlink_gen_stmt_stateful(ctx, stmt->set.stmt), 0);
+ netlink_gen_stmt_stateful(stmt->set.stmt), 0);
}
static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
@@ -1337,7 +1327,7 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
if (stmt->map.stmt)
nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
- netlink_gen_stmt_stateful(ctx, stmt->map.stmt), 0);
+ netlink_gen_stmt_stateful(stmt->map.stmt), 0);
nftnl_rule_add_expr(ctx->nlr, nle);
}
@@ -1369,7 +1359,7 @@ static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx,
nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name);
nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
- netlink_gen_stmt_stateful(ctx, stmt->meter.stmt), 0);
+ netlink_gen_stmt_stateful(stmt->meter.stmt), 0);
nftnl_rule_add_expr(ctx->nlr, nle);
}
@@ -1415,7 +1405,7 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
case STMT_COUNTER:
case STMT_LIMIT:
case STMT_QUOTA:
- nle = netlink_gen_stmt_stateful(ctx, stmt);
+ nle = netlink_gen_stmt_stateful(stmt);
nftnl_rule_add_expr(ctx->nlr, nle);
break;
case STMT_NOTRACK:
--
2.31.1

View File

@ -0,0 +1,150 @@
From 0db42cc2d2647ec61441e29445c9f6e0f8946613 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Thu, 13 Jan 2022 20:37:56 +0100
Subject: [PATCH] src: support for restoring element counters
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594
Upstream Status: nftables commit 1fe6089ddd87e
commit 1fe6089ddd87ee7869d24c0f8849951220cc9b85
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed Mar 11 13:00:01 2020 +0100
src: support for restoring element counters
This patch allows you to restore counters in dynamic sets:
table ip test {
set test {
type ipv4_addr
size 65535
flags dynamic,timeout
timeout 30d
gc-interval 1d
elements = { 192.168.10.13 expires 19d23h52m27s576ms counter packets 51 bytes 17265 }
}
chain output {
type filter hook output priority 0;
update @test { ip saddr }
}
}
You can also add counters to elements from the control place, ie.
table ip test {
set test {
type ipv4_addr
size 65535
elements = { 192.168.2.1 counter packets 75 bytes 19043 }
}
chain output {
type filter hook output priority filter; policy accept;
ip daddr @test
}
}
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/netlink.h | 1 +
src/netlink.c | 3 +++
src/netlink_linearize.c | 2 +-
src/parser_bison.y | 36 +++++++++++++++++++++++++++++++++++-
4 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/include/netlink.h b/include/netlink.h
index 88d12ba..059092e 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -97,6 +97,7 @@ extern void netlink_gen_data(const struct expr *expr,
extern void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder,
unsigned int len,
struct nft_data_linearize *data);
+extern struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt);
extern struct expr *netlink_alloc_value(const struct location *loc,
const struct nft_data_delinearize *nld);
diff --git a/src/netlink.c b/src/netlink.c
index 64e51e5..825c2cc 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -136,6 +136,9 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
if (elem->expiration)
nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION,
elem->expiration);
+ if (elem->stmt)
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_EXPR,
+ netlink_gen_stmt_stateful(elem->stmt), 0);
if (elem->comment || expr->elem_flags) {
udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
if (!udbuf)
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index f5c6116..3fa1339 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -838,7 +838,7 @@ static struct nftnl_expr *netlink_gen_quota_stmt(const struct stmt *stmt)
return nle;
}
-static struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt)
+struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt)
{
switch (stmt->ops->type) {
case STMT_CONNLIMIT:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d38ec30..2cdf8ec 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -3654,7 +3654,7 @@ meter_key_expr_alloc : concat_expr
;
set_elem_expr : set_elem_expr_alloc
- | set_elem_expr_alloc set_elem_options
+ | set_elem_expr_alloc set_elem_expr_options
;
set_elem_expr_alloc : set_lhs_expr
@@ -3684,6 +3684,40 @@ set_elem_option : TIMEOUT time_spec
}
;
+set_elem_expr_options : set_elem_expr_option
+ {
+ $<expr>$ = $<expr>0;
+ }
+ | set_elem_expr_options set_elem_expr_option
+ ;
+
+set_elem_expr_option : TIMEOUT time_spec
+ {
+ $<expr>0->timeout = $2;
+ }
+ | EXPIRES time_spec
+ {
+ $<expr>0->expiration = $2;
+ }
+ | COUNTER
+ {
+ $<expr>0->stmt = counter_stmt_alloc(&@$);
+ }
+ | COUNTER PACKETS NUM BYTES NUM
+ {
+ struct stmt *stmt;
+
+ stmt = counter_stmt_alloc(&@$);
+ stmt->counter.packets = $3;
+ stmt->counter.bytes = $5;
+ $<expr>0->stmt = stmt;
+ }
+ | comment_spec
+ {
+ $<expr>0->comment = $1;
+ }
+ ;
+
set_lhs_expr : concat_rhs_expr
| wildcard_expr
;
--
2.31.1

View File

@ -0,0 +1,127 @@
From 48021b277a1ab92480c43e1fa7573b00e33f5212 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 14 Jan 2022 11:39:17 +0100
Subject: [PATCH] evaluate: attempt to set_eval flag if dynamic updates
requested
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594
Upstream Status: nftables commit 8d443adfcc8c1
Conflicts:
* Context change due to missing commit 242965f452e64
("src: add support for multi-statement in dynamic sets and maps")
* Adjusted test-case: Due to missing kernel commit 7b1394892de8d
("netfilter: nft_dynset: relax superfluous check on set updates"),
'update' statement is allowed only if timeout flag is present
commit 8d443adfcc8c19effd6be9a9c903ee96e374f2e8
Author: Florian Westphal <fw@strlen.de>
Date: Tue Jan 11 12:08:59 2022 +0100
evaluate: attempt to set_eval flag if dynamic updates requested
When passing no upper size limit, the dynset expression forces
an internal 64k upperlimit.
In some cases, this can result in 'nft -f' to restore the ruleset.
Avoid this by always setting the EVAL flag on a set definition when
we encounter packet-path update attempt in the batch.
Reported-by: Yi Chen <yiche@redhat.com>
Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/evaluate.c | 11 +++++++
.../testcases/sets/dumps/dynset_missing.nft | 12 +++++++
tests/shell/testcases/sets/dynset_missing | 32 +++++++++++++++++++
3 files changed, 55 insertions(+)
create mode 100644 tests/shell/testcases/sets/dumps/dynset_missing.nft
create mode 100755 tests/shell/testcases/sets/dynset_missing
diff --git a/src/evaluate.c b/src/evaluate.c
index 00ec20b..9381f23 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3076,6 +3076,8 @@ static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt)
static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
{
+ struct set *this_set;
+
expr_set_context(&ctx->ectx, NULL, 0);
if (expr_evaluate(ctx, &stmt->set.set) < 0)
return -1;
@@ -3103,6 +3105,15 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
"meter statement must be stateful");
}
+ this_set = stmt->set.set->set;
+
+ /* Make sure EVAL flag is set on set definition so that kernel
+ * picks a set that allows updates from the packet path.
+ *
+ * Alternatively we could error out in case 'flags dynamic' was
+ * not given, but we can repair this here.
+ */
+ this_set->flags |= NFT_SET_EVAL;
return 0;
}
diff --git a/tests/shell/testcases/sets/dumps/dynset_missing.nft b/tests/shell/testcases/sets/dumps/dynset_missing.nft
new file mode 100644
index 0000000..fdb1b97
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/dynset_missing.nft
@@ -0,0 +1,12 @@
+table ip test {
+ set dlist {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ }
+
+ chain output {
+ type filter hook output priority filter; policy accept;
+ udp dport 1234 update @dlist { ip daddr } counter packets 0 bytes 0
+ }
+}
diff --git a/tests/shell/testcases/sets/dynset_missing b/tests/shell/testcases/sets/dynset_missing
new file mode 100755
index 0000000..89afcd5
--- /dev/null
+++ b/tests/shell/testcases/sets/dynset_missing
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+$NFT -f /dev/stdin <<EOF
+table ip test {
+ chain output { type filter hook output priority 0;
+ }
+}
+EOF
+
+# misses 'flags dynamic'
+$NFT 'add set ip test dlist {type ipv4_addr; flags timeout; }'
+
+# picks rhash backend because 'size' was also missing.
+$NFT 'add rule ip test output udp dport 1234 update @dlist { ip daddr } counter'
+
+tmpfile=$(mktemp)
+
+trap "rm -rf $tmpfile" EXIT
+
+# kernel has forced an 64k upper size, i.e. this restore file
+# has 'size 65536' but no 'flags dynamic'.
+$NFT list ruleset > $tmpfile
+
+# this restore works, because set is still the rhash backend.
+$NFT -f $tmpfile # success
+$NFT flush ruleset
+
+# fails without commit 'attempt to set_eval flag if dynamic updates requested',
+# because set in $tmpfile has 'size x' but no 'flags dynamic'.
+$NFT -f $tmpfile
--
2.31.1

View File

@ -0,0 +1,49 @@
From 1fe92af5a03608b94e8e1e2ff26e24adfe2ea09a Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 21 Jan 2022 12:35:39 +0100
Subject: [PATCH] evaluate: fix inet nat with no layer 3 info
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2030773
Upstream Status: nftables commit 9a36033ce5063
commit 9a36033ce50638a403d1421935cdd1287ee5de6b
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue Jul 20 18:59:44 2021 +0200
evaluate: fix inet nat with no layer 3 info
nft currently reports:
Error: Could not process rule: Protocol error
add rule inet x y meta l4proto tcp dnat to :80
^^^^
default to NFPROTO_INET family, otherwise kernel bails out EPROTO when
trying to load the conntrack helper.
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1428
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 9381f23..e495faf 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2757,9 +2757,10 @@ static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt)
stmt->nat.family = ctx->pctx.family;
return 0;
case NFPROTO_INET:
- if (!stmt->nat.addr)
+ if (!stmt->nat.addr) {
+ stmt->nat.family = NFPROTO_INET;
return 0;
-
+ }
if (stmt->nat.family != NFPROTO_UNSPEC)
return 0;
--
2.31.1

View File

@ -0,0 +1,86 @@
From eeba2cd956485d3059dabf86a7ad8dd59ee682dd Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 4 Feb 2022 14:18:44 +0100
Subject: [PATCH] tests: py: add dnat to port without defining destination
address
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2030773
Upstream Status: nftables commit 0f27e258b37a5
Conflicts: Context changes due to missing commit ae1d822630e6d
("src: context tracking for multiple transport protocols")
commit 0f27e258b37a592233d6ad5381cd1fae65e57514
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu Jul 22 17:43:56 2021 +0200
tests: py: add dnat to port without defining destination address
Add a test to cover dnat to port without destination address.
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1428
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
tests/py/inet/dnat.t | 1 +
tests/py/inet/dnat.t.json | 20 ++++++++++++++++++++
tests/py/inet/dnat.t.payload | 8 ++++++++
3 files changed, 29 insertions(+)
diff --git a/tests/py/inet/dnat.t b/tests/py/inet/dnat.t
index fcdf943..6beceda 100644
--- a/tests/py/inet/dnat.t
+++ b/tests/py/inet/dnat.t
@@ -6,6 +6,7 @@ iifname "foo" tcp dport 80 redirect to :8080;ok
iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2;ok
iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443;ok
+meta l4proto tcp dnat to :80;ok;meta l4proto 6 dnat to :80
dnat ip to ct mark map { 0x00000014 : 1.2.3.4};ok
dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4};ok
diff --git a/tests/py/inet/dnat.t.json b/tests/py/inet/dnat.t.json
index ac6dac6..f88e9cf 100644
--- a/tests/py/inet/dnat.t.json
+++ b/tests/py/inet/dnat.t.json
@@ -164,3 +164,23 @@
}
]
+# meta l4proto tcp dnat to :80
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "dnat": {
+ "port": 80
+ }
+ }
+]
+
diff --git a/tests/py/inet/dnat.t.payload b/tests/py/inet/dnat.t.payload
index b81caf7..6d8569d 100644
--- a/tests/py/inet/dnat.t.payload
+++ b/tests/py/inet/dnat.t.payload
@@ -52,3 +52,11 @@ inet test-inet prerouting
[ payload load 4b @ network header + 16 => reg 9 ]
[ lookup reg 1 set __map%d dreg 1 ]
[ nat dnat ip addr_min reg 1 addr_max reg 0 ]
+
+# meta l4proto tcp dnat to :80
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00005000 ]
+ [ nat dnat inet proto_min reg 1 flags 0x2 ]
+
--
2.31.1

View File

@ -0,0 +1,214 @@
From bd940a4efd2b5897f8a8e58ec7733417b3710e1e Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 8 Dec 2021 13:28:49 +0100
Subject: [PATCH] mnl: do not build nftnl_set element list
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2047821
Upstream Status: nftables commit b4b234f5a29e8
Conflicts: Context change due to missing commit 66746e7dedeb0
("src: support for nat with interval concatenation").
commit b4b234f5a29e819045679acd95820a7457d4d7de
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu Nov 4 12:53:11 2021 +0100
mnl: do not build nftnl_set element list
Do not call alloc_setelem_cache() to build the set element list in
nftnl_set. Instead, translate one single set element expression to
nftnl_set_elem object at a time and use this object to build the netlink
header.
Using a huge test set containing 1.1 million element blocklist, this
patch is reducing userspace memory consumption by 40%.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/netlink.h | 2 +
src/mnl.c | 112 ++++++++++++++++++++++++++++++++++++----------
src/netlink.c | 4 +-
3 files changed, 93 insertions(+), 25 deletions(-)
diff --git a/include/netlink.h b/include/netlink.h
index 059092e..3443582 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -56,6 +56,8 @@ struct netlink_ctx {
extern struct nftnl_expr *alloc_nft_expr(const char *name);
extern void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls);
+struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
+ const struct expr *expr);
extern struct nftnl_table *netlink_table_alloc(const struct nlmsghdr *nlh);
extern struct nftnl_chain *netlink_chain_alloc(const struct nlmsghdr *nlh);
diff --git a/src/mnl.c b/src/mnl.c
index 23341e6..44cf1a4 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1201,33 +1201,102 @@ static int set_elem_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
-static int mnl_nft_setelem_batch(struct nftnl_set *nls,
+static bool mnl_nft_attr_nest_overflow(struct nlmsghdr *nlh,
+ const struct nlattr *from,
+ const struct nlattr *to)
+{
+ int len = (void *)to + to->nla_len - (void *)from;
+
+ /* The attribute length field is 16 bits long, thus the maximum payload
+ * that an attribute can convey is UINT16_MAX. In case of overflow,
+ * discard the last attribute that did not fit into the nest.
+ */
+ if (len > UINT16_MAX) {
+ nlh->nlmsg_len -= to->nla_len;
+ return true;
+ }
+ return false;
+}
+
+static void netlink_dump_setelem(const struct nftnl_set_elem *nlse,
+ struct netlink_ctx *ctx)
+{
+ FILE *fp = ctx->nft->output.output_fp;
+ char buf[4096];
+
+ if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
+ return;
+
+ nftnl_set_elem_snprintf(buf, sizeof(buf), nlse, NFTNL_OUTPUT_DEFAULT, 0);
+ fprintf(fp, "\t%s", buf);
+}
+
+static void netlink_dump_setelem_done(struct netlink_ctx *ctx)
+{
+ FILE *fp = ctx->nft->output.output_fp;
+
+ if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
+ return;
+
+ fprintf(fp, "\n");
+}
+
+static int mnl_nft_setelem_batch(const struct nftnl_set *nls,
struct nftnl_batch *batch,
enum nf_tables_msg_types cmd,
- unsigned int flags, uint32_t seqnum)
+ unsigned int flags, uint32_t seqnum,
+ const struct expr *set,
+ struct netlink_ctx *ctx)
{
+ struct nlattr *nest1, *nest2;
+ struct nftnl_set_elem *nlse;
struct nlmsghdr *nlh;
- struct nftnl_set_elems_iter *iter;
- int ret;
-
- iter = nftnl_set_elems_iter_create(nls);
- if (iter == NULL)
- memory_allocation_error();
+ struct expr *expr = NULL;
+ int i = 0;
if (cmd == NFT_MSG_NEWSETELEM)
flags |= NLM_F_CREATE;
- while (nftnl_set_elems_iter_cur(iter)) {
- nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), cmd,
- nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
- flags, seqnum);
- ret = nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter);
- mnl_nft_batch_continue(batch);
- if (ret <= 0)
- break;
+ if (set)
+ expr = list_first_entry(&set->expressions, struct expr, list);
+
+next:
+ nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), cmd,
+ nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
+ flags, seqnum);
+
+ if (nftnl_set_is_set(nls, NFTNL_SET_TABLE)) {
+ mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE,
+ nftnl_set_get_str(nls, NFTNL_SET_TABLE));
+ }
+ if (nftnl_set_is_set(nls, NFTNL_SET_NAME)) {
+ mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET,
+ nftnl_set_get_str(nls, NFTNL_SET_NAME));
}
+ if (nftnl_set_is_set(nls, NFTNL_SET_ID)) {
+ mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID,
+ htonl(nftnl_set_get_u32(nls, NFTNL_SET_ID)));
+ }
+
+ if (!set || list_empty(&set->expressions))
+ return 0;
- nftnl_set_elems_iter_destroy(iter);
+ assert(expr);
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
+ list_for_each_entry_from(expr, &set->expressions, list) {
+ nlse = alloc_nftnl_setelem(set, expr);
+ nest2 = nftnl_set_elem_nlmsg_build(nlh, nlse, ++i);
+ netlink_dump_setelem(nlse, ctx);
+ nftnl_set_elem_free(nlse);
+ if (mnl_nft_attr_nest_overflow(nlh, nest1, nest2)) {
+ mnl_attr_nest_end(nlh, nest1);
+ mnl_nft_batch_continue(batch);
+ goto next;
+ }
+ }
+ mnl_attr_nest_end(nlh, nest1);
+ mnl_nft_batch_continue(batch);
+ netlink_dump_setelem_done(ctx);
return 0;
}
@@ -1249,11 +1318,10 @@ int mnl_nft_setelem_add(struct netlink_ctx *ctx, const struct set *set,
if (h->set_id)
nftnl_set_set_u32(nls, NFTNL_SET_ID, h->set_id);
- alloc_setelem_cache(expr, nls);
netlink_dump_set(nls, ctx);
- err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_NEWSETELEM, flags,
- ctx->seqnum);
+ err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_NEWSETELEM,
+ flags, ctx->seqnum, expr, ctx);
nftnl_set_free(nls);
return err;
@@ -1306,12 +1374,10 @@ int mnl_nft_setelem_del(struct netlink_ctx *ctx, const struct cmd *cmd)
else if (h->handle.id)
nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id);
- if (cmd->expr)
- alloc_setelem_cache(cmd->expr, nls);
netlink_dump_set(nls, ctx);
err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_DELSETELEM, 0,
- ctx->seqnum);
+ ctx->seqnum, cmd->expr, ctx);
nftnl_set_free(nls);
return err;
diff --git a/src/netlink.c b/src/netlink.c
index 825c2cc..f8c97d0 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -95,8 +95,8 @@ struct nftnl_expr *alloc_nft_expr(const char *name)
return nle;
}
-static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
- const struct expr *expr)
+struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
+ const struct expr *expr)
{
const struct expr *elem, *data;
struct nftnl_set_elem *nlse;
--
2.31.1

View File

@ -0,0 +1,130 @@
From 2747cab9c49b570347c86ff59daec93a1432b0bc Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:37:00 +0200
Subject: [PATCH] mnl: do not use expr->identifier to fetch device name
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2070924
Upstream Status: nftables commit 78bbe7f7a55be
commit 78bbe7f7a55be48909067e25900de27623d8fa6a
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed Feb 19 21:05:26 2020 +0100
mnl: do not use expr->identifier to fetch device name
This string might not be nul-terminated, resulting in spurious errors
when adding netdev chains.
Fixes: 3fdc7541fba0 ("src: add multidevice support for netdev chain")
Fixes: 92911b362e90 ("src: add support to add flowtables")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/mnl.c | 33 +++++++++++++++++++++++++++++----
src/parser_bison.y | 6 +++---
2 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/src/mnl.c b/src/mnl.c
index 44cf1a4..f881d97 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -26,6 +26,7 @@
#include <mnl.h>
#include <string.h>
+#include <net/if.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
@@ -529,7 +530,9 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, const struct cmd *cmd,
{
int priority, policy, i = 0;
struct nftnl_chain *nlc;
+ unsigned int ifname_len;
const char **dev_array;
+ char ifname[IFNAMSIZ];
struct nlmsghdr *nlh;
struct expr *expr;
int dev_array_len;
@@ -562,7 +565,12 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, const struct cmd *cmd,
dev_array = xmalloc(sizeof(char *) * 8);
dev_array_len = 8;
list_for_each_entry(expr, &cmd->chain->dev_expr->expressions, list) {
- dev_array[i++] = expr->identifier;
+ ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
+ memset(ifname, 0, sizeof(ifname));
+ mpz_export_data(ifname, expr->value,
+ BYTEORDER_HOST_ENDIAN,
+ ifname_len);
+ dev_array[i++] = xstrdup(ifname);
if (i == dev_array_len) {
dev_array_len *= 2;
dev_array = xrealloc(dev_array,
@@ -577,6 +585,10 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, const struct cmd *cmd,
nftnl_chain_set_data(nlc, NFTNL_CHAIN_DEVICES, dev_array,
sizeof(char *) * dev_array_len);
+ i = 0;
+ while (dev_array[i] != NULL)
+ xfree(dev_array[i++]);
+
xfree(dev_array);
}
}
@@ -1488,7 +1500,9 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags)
{
struct nftnl_flowtable *flo;
+ unsigned int ifname_len;
const char **dev_array;
+ char ifname[IFNAMSIZ];
struct nlmsghdr *nlh;
int i = 0, len = 1;
struct expr *expr;
@@ -1513,13 +1527,24 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
list_for_each_entry(expr, &cmd->flowtable->dev_expr->expressions, list)
len++;
- dev_array = calloc(len, sizeof(char *));
- list_for_each_entry(expr, &cmd->flowtable->dev_expr->expressions, list)
- dev_array[i++] = expr->identifier;
+ dev_array = xmalloc(sizeof(char *) * len);
+
+ list_for_each_entry(expr, &cmd->flowtable->dev_expr->expressions, list) {
+ ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
+ memset(ifname, 0, sizeof(ifname));
+ mpz_export_data(ifname, expr->value, BYTEORDER_HOST_ENDIAN,
+ ifname_len);
+ dev_array[i++] = xstrdup(ifname);
+ }
dev_array[i] = NULL;
nftnl_flowtable_set_data(flo, NFTNL_FLOWTABLE_DEVICES,
dev_array, sizeof(char *) * len);
+
+ i = 0;
+ while (dev_array[i] != NULL)
+ xfree(dev_array[i++]);
+
free(dev_array);
netlink_dump_flowtable(flo, ctx);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 2cdf8ec..dc87571 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1909,9 +1909,9 @@ flowtable_list_expr : flowtable_expr_member
flowtable_expr_member : STRING
{
- $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
- current_scope(state),
- $1);
+ $$ = constant_expr_alloc(&@$, &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ strlen($1) * BITS_PER_BYTE, $1);
xfree($1);
}
;
--
2.34.1

View File

@ -0,0 +1,47 @@
From 66369d42095a214672c1f935eed91902d4cca8d5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:37:00 +0200
Subject: [PATCH] tests: shell: auto-removal of chain hook on netns removal
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2070924
Upstream Status: nftables commit e632eea21f4b3
Conflicts: Commit b4775dec9f80b ("src: ingress inet support") creating
the test not backported, RHEL8 does not support inet ingress.
Script adjusted accordingly.
commit e632eea21f4b3d03b629a5c1ac7e776d65785873
Author: Florian Westphal <fw@strlen.de>
Date: Tue Oct 19 14:07:25 2021 +0200
tests: shell: auto-removal of chain hook on netns removal
This is the nft equivalent of the syzbot report that lead to
kernel commit 68a3765c659f8
("netfilter: nf_tables: skip netdev events generated on netns removal").
Signed-off-by: Florian Westphal <fw@strlen.de>
---
tests/shell/testcases/chains/0043chain_ingress_0 | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100755 tests/shell/testcases/chains/0043chain_ingress_0
diff --git a/tests/shell/testcases/chains/0043chain_ingress_0 b/tests/shell/testcases/chains/0043chain_ingress_0
new file mode 100755
index 0000000..09d6907
--- /dev/null
+++ b/tests/shell/testcases/chains/0043chain_ingress_0
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+# Test auto-removal of chain hook on netns removal
+unshare -n bash -c "ip link add br0 type bridge; \
+ $NFT add table netdev test; \
+ $NFT add chain netdev test ingress { type filter hook ingress device \"br0\" priority 0\; policy drop\; } ; \
+" || exit 1
+
+exit 0
--
2.34.1

View File

@ -0,0 +1,53 @@
From bc2bfe4b68d213c74c634e87dee0116c066209e4 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:46:47 +0200
Subject: [PATCH] rule: memleak in __do_add_setelems()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2073287
Upstream Status: nftables commit b6d50bfde21b5
commit b6d50bfde21b5a24a606cbf22137e04e8e0f195d
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu Apr 30 14:18:45 2020 +0200
rule: memleak in __do_add_setelems()
This patch invokes interval_map_decompose() with named sets:
==3402== 2,352 (128 direct, 2,224 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 9
==3402== at 0x483577F: malloc (vg_replace_malloc.c:299)
==3402== by 0x48996A8: xmalloc (utils.c:36)
==3402== by 0x4899778: xzalloc (utils.c:65)
==3402== by 0x487CB46: expr_alloc (expression.c:45)
==3402== by 0x487E2A0: mapping_expr_alloc (expression.c:1140)
==3402== by 0x4898AA8: interval_map_decompose (segtree.c:1095)
==3402== by 0x4872BDF: __do_add_setelems (rule.c:1569)
==3402== by 0x4872BDF: __do_add_setelems (rule.c:1559)
==3402== by 0x4877936: do_command (rule.c:2710)
==3402== by 0x489F1CB: nft_netlink.isra.5 (libnftables.c:42)
==3402== by 0x489FB07: nft_run_cmd_from_filename (libnftables.c:508)
==3402== by 0x10A9AA: main (main.c:455)
Fixes: dd44081d91ce ("segtree: Fix add and delete of element in same batch")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/rule.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/rule.c b/src/rule.c
index f7d888b..b2aa1d7 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1511,7 +1511,8 @@ static int __do_add_setelems(struct netlink_ctx *ctx, struct set *set,
if (mnl_nft_setelem_add(ctx, set, expr, flags) < 0)
return -1;
- if (set->init != NULL &&
+ if (!set_is_anonymous(set->flags) &&
+ set->init != NULL &&
set->flags & NFT_SET_INTERVAL &&
set->desc.field_count <= 1) {
interval_map_decompose(expr);
--
2.34.1

View File

@ -0,0 +1,43 @@
From 0e284af80adefc8d8738c7191eff0ca7c6ad64a6 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:46:47 +0200
Subject: [PATCH] rule: fix element cache update in __do_add_setelems()
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2073287
Upstream Status: nftables commit e68938f2bf89f
commit e68938f2bf89fcc9a99e12c9b7a10c1838f2a133
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu Apr 30 16:30:15 2020 +0200
rule: fix element cache update in __do_add_setelems()
The set->init and expr arguments might actually refer to the same list
of elements. Skip set element cache update introduced by dd44081d91ce
("segtree: Fix add and delete of element in same batch") otherwise
list_splice_tail_init() actually operates with the same list as
arguments. Valgrind reports this problem as a memleak since the result
of this operation was an empty set element list.
Fixes: dd44081d91ce ("segtree: Fix add and delete of element in same batch")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/rule.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/rule.c b/src/rule.c
index b2aa1d7..9ae6d19 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1512,7 +1512,7 @@ static int __do_add_setelems(struct netlink_ctx *ctx, struct set *set,
return -1;
if (!set_is_anonymous(set->flags) &&
- set->init != NULL &&
+ set->init != NULL && set->init != expr &&
set->flags & NFT_SET_INTERVAL &&
set->desc.field_count <= 1) {
interval_map_decompose(expr);
--
2.34.1

View File

@ -0,0 +1,208 @@
From 43d5837615201d68108151e70c06cc0e90622fcc Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:46:47 +0200
Subject: [PATCH] src: rename CMD_OBJ_SETELEM to CMD_OBJ_ELEMENTS
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2073287
Upstream Status: nftables commit 9ed076c6f5abc
commit 9ed076c6f5abcbbad1b6b721dca29f87963f0ecc
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri May 8 14:44:01 2020 +0200
src: rename CMD_OBJ_SETELEM to CMD_OBJ_ELEMENTS
The CMD_OBJ_ELEMENTS provides an expression that contains the list of
set elements. This leaves room to introduce CMD_OBJ_SETELEMS in a follow
up patch.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/rule.h | 4 ++--
src/cache.c | 6 +++---
src/evaluate.c | 6 +++---
src/parser_bison.y | 8 ++++----
src/parser_json.c | 2 +-
src/rule.c | 8 ++++----
6 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/rule.h b/include/rule.h
index 3637462..7fe607f 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -542,7 +542,7 @@ enum cmd_ops {
* enum cmd_obj - command objects
*
* @CMD_OBJ_INVALID: invalid
- * @CMD_OBJ_SETELEM: set element(s)
+ * @CMD_OBJ_ELEMENTS: set element(s)
* @CMD_OBJ_SET: set
* @CMD_OBJ_SETS: multiple sets
* @CMD_OBJ_RULE: rule
@@ -570,7 +570,7 @@ enum cmd_ops {
*/
enum cmd_obj {
CMD_OBJ_INVALID,
- CMD_OBJ_SETELEM,
+ CMD_OBJ_ELEMENTS,
CMD_OBJ_SET,
CMD_OBJ_SETS,
CMD_OBJ_RULE,
diff --git a/src/cache.c b/src/cache.c
index 05f0d68..a45111a 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -25,7 +25,7 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
case CMD_OBJ_FLOWTABLE:
flags |= NFT_CACHE_TABLE;
break;
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
flags |= NFT_CACHE_TABLE |
NFT_CACHE_CHAIN |
NFT_CACHE_SET |
@@ -53,7 +53,7 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
static unsigned int evaluate_cache_del(struct cmd *cmd, unsigned int flags)
{
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
flags |= NFT_CACHE_SETELEM;
break;
default:
@@ -66,7 +66,7 @@ static unsigned int evaluate_cache_del(struct cmd *cmd, unsigned int flags)
static unsigned int evaluate_cache_get(struct cmd *cmd, unsigned int flags)
{
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
flags |= NFT_CACHE_TABLE |
NFT_CACHE_SET |
NFT_CACHE_SETELEM;
diff --git a/src/evaluate.c b/src/evaluate.c
index e495faf..fd6db8a 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3815,7 +3815,7 @@ static int table_evaluate(struct eval_ctx *ctx, struct table *table)
static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
{
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
handle_merge(&cmd->set->handle, &cmd->handle);
@@ -3847,7 +3847,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
{
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
case CMD_OBJ_RULE:
@@ -3874,7 +3874,7 @@ static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd)
struct set *set;
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
table = table_lookup(&cmd->handle, &ctx->nft->cache);
if (table == NULL)
return table_not_found(ctx);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index dc87571..96f0a4c 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1019,7 +1019,7 @@ add_cmd : TABLE table_spec
}
| ELEMENT set_spec set_block_expr
{
- $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SETELEM, &$2, &@$, $3);
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
}
| FLOWTABLE flowtable_spec flowtable_block_alloc
'{' flowtable_block '}'
@@ -1116,7 +1116,7 @@ create_cmd : TABLE table_spec
}
| ELEMENT set_spec set_block_expr
{
- $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SETELEM, &$2, &@$, $3);
+ $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
}
| FLOWTABLE flowtable_spec flowtable_block_alloc
'{' flowtable_block '}'
@@ -1208,7 +1208,7 @@ delete_cmd : TABLE table_spec
}
| ELEMENT set_spec set_block_expr
{
- $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SETELEM, &$2, &@$, $3);
+ $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
}
| FLOWTABLE flowtable_spec
{
@@ -1266,7 +1266,7 @@ delete_cmd : TABLE table_spec
get_cmd : ELEMENT set_spec set_block_expr
{
- $$ = cmd_alloc(CMD_GET, CMD_OBJ_SETELEM, &$2, &@$, $3);
+ $$ = cmd_alloc(CMD_GET, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
}
;
diff --git a/src/parser_json.c b/src/parser_json.c
index 2250be9..15902a8 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3391,7 +3391,7 @@ static struct cmd *json_parse_cmd_add(struct json_ctx *ctx,
{ "rule", CMD_OBJ_RULE, json_parse_cmd_add_rule },
{ "set", CMD_OBJ_SET, json_parse_cmd_add_set },
{ "map", CMD_OBJ_SET, json_parse_cmd_add_set },
- { "element", CMD_OBJ_SETELEM, json_parse_cmd_add_element },
+ { "element", CMD_OBJ_ELEMENTS, json_parse_cmd_add_element },
{ "flowtable", CMD_OBJ_FLOWTABLE, json_parse_cmd_add_flowtable },
{ "counter", CMD_OBJ_COUNTER, json_parse_cmd_add_object },
{ "quota", CMD_OBJ_QUOTA, json_parse_cmd_add_object },
diff --git a/src/rule.c b/src/rule.c
index 9ae6d19..afb6dc9 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1456,7 +1456,7 @@ void cmd_free(struct cmd *cmd)
handle_free(&cmd->handle);
if (cmd->data != NULL) {
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
expr_free(cmd->expr);
break;
case CMD_OBJ_SET:
@@ -1580,7 +1580,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
return mnl_nft_rule_add(ctx, cmd, flags | NLM_F_APPEND);
case CMD_OBJ_SET:
return do_add_set(ctx, cmd, flags);
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
return do_add_setelems(ctx, cmd, flags);
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
@@ -1659,7 +1659,7 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd)
return mnl_nft_rule_del(ctx, cmd);
case CMD_OBJ_SET:
return mnl_nft_set_del(ctx, cmd);
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
return do_delete_setelems(ctx, cmd);
case CMD_OBJ_COUNTER:
return mnl_nft_obj_del(ctx, cmd, NFT_OBJECT_COUNTER);
@@ -2519,7 +2519,7 @@ static int do_command_get(struct netlink_ctx *ctx, struct cmd *cmd)
table = table_lookup(&cmd->handle, &ctx->nft->cache);
switch (cmd->obj) {
- case CMD_OBJ_SETELEM:
+ case CMD_OBJ_ELEMENTS:
return do_get_setelems(ctx, cmd, table);
default:
BUG("invalid command object type %u\n", cmd->obj);
--
2.34.1

View File

@ -0,0 +1,125 @@
From 61c295c9dec447239ed2c84b0073594ffecf7554 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 27 Apr 2022 14:46:47 +0200
Subject: [PATCH] src: add CMD_OBJ_SETELEMS
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2073287
Upstream Status: nftables commit c9eae091983ae
Conflicts: Context change due to missing commit 086ec6f30c96e
("mnl: extended error support for create command").
commit c9eae091983ae9ffcf2ca5b666bc03d5a1916c2f
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri May 8 14:44:03 2020 +0200
src: add CMD_OBJ_SETELEMS
This new command type results from expanding the set definition in two
commands: One to add the set and another to add the elements. This
results in 1:1 mapping between the command object to the netlink API.
The command is then translated into a netlink message which gets a
unique sequence number. This sequence number allows to correlate the
netlink extended error reporting with the corresponding command.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/rule.h | 2 ++
src/rule.c | 23 +++++++++++++++++++----
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/include/rule.h b/include/rule.h
index 7fe607f..1efd4fb 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -545,6 +545,7 @@ enum cmd_ops {
* @CMD_OBJ_ELEMENTS: set element(s)
* @CMD_OBJ_SET: set
* @CMD_OBJ_SETS: multiple sets
+ * @CMD_OBJ_SETELEMS: set elements
* @CMD_OBJ_RULE: rule
* @CMD_OBJ_CHAIN: chain
* @CMD_OBJ_CHAINS: multiple chains
@@ -572,6 +573,7 @@ enum cmd_obj {
CMD_OBJ_INVALID,
CMD_OBJ_ELEMENTS,
CMD_OBJ_SET,
+ CMD_OBJ_SETELEMS,
CMD_OBJ_SETS,
CMD_OBJ_RULE,
CMD_OBJ_CHAIN,
diff --git a/src/rule.c b/src/rule.c
index afb6dc9..c43e0cd 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1352,11 +1352,11 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
void nft_cmd_expand(struct cmd *cmd)
{
struct list_head new_cmds;
+ struct set *set, *newset;
struct flowtable *ft;
struct table *table;
struct chain *chain;
struct rule *rule;
- struct set *set;
struct obj *obj;
struct cmd *new;
struct handle h;
@@ -1412,6 +1412,18 @@ void nft_cmd_expand(struct cmd *cmd)
}
list_splice(&new_cmds, &cmd->list);
break;
+ case CMD_OBJ_SET:
+ set = cmd->set;
+ memset(&h, 0, sizeof(h));
+ handle_merge(&h, &set->handle);
+ newset = set_clone(set);
+ newset->handle.set_id = set->handle.set_id;
+ newset->init = set->init;
+ set->init = NULL;
+ new = cmd_alloc(CMD_ADD, CMD_OBJ_SETELEMS, &h,
+ &set->location, newset);
+ list_add(&new->list, &cmd->list);
+ break;
default:
break;
}
@@ -1460,6 +1472,7 @@ void cmd_free(struct cmd *cmd)
expr_free(cmd->expr);
break;
case CMD_OBJ_SET:
+ case CMD_OBJ_SETELEMS:
set_free(cmd->set);
break;
case CMD_OBJ_RULE:
@@ -1545,7 +1558,7 @@ static int do_add_setelems(struct netlink_ctx *ctx, struct cmd *cmd,
}
static int do_add_set(struct netlink_ctx *ctx, const struct cmd *cmd,
- uint32_t flags)
+ uint32_t flags, bool add)
{
struct set *set = cmd->set;
@@ -1556,7 +1569,7 @@ static int do_add_set(struct netlink_ctx *ctx, const struct cmd *cmd,
&ctx->nft->output) < 0)
return -1;
}
- if (mnl_nft_set_add(ctx, cmd, flags) < 0)
+ if (add && mnl_nft_set_add(ctx, cmd, flags) < 0)
return -1;
if (set->init != NULL) {
return __do_add_setelems(ctx, set, set->init, flags);
@@ -1579,7 +1592,9 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
case CMD_OBJ_RULE:
return mnl_nft_rule_add(ctx, cmd, flags | NLM_F_APPEND);
case CMD_OBJ_SET:
- return do_add_set(ctx, cmd, flags);
+ return do_add_set(ctx, cmd, flags, true);
+ case CMD_OBJ_SETELEMS:
+ return do_add_set(ctx, cmd, flags, false);
case CMD_OBJ_ELEMENTS:
return do_add_setelems(ctx, cmd, flags);
case CMD_OBJ_COUNTER:
--
2.34.1

View File

@ -0,0 +1,43 @@
From 34a7632a4d72c16d2a087fcc6450d1a783858124 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Thu, 28 Apr 2022 14:14:39 +0200
Subject: [PATCH] libnftables: call nft_cmd_expand() only with CMD_ADD
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2073287
Upstream Status: nftables commit b81519f1641b5
commit b81519f1641b508c289ddfefc800b2c20ab243e6
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri May 8 14:44:02 2020 +0200
libnftables: call nft_cmd_expand() only with CMD_ADD
Restrict the expansion logic to the CMD_ADD command which is where this
is only required.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/libnftables.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/libnftables.c b/src/libnftables.c
index cd2fcf2..ab01909 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -421,8 +421,12 @@ static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs,
if (nft->state->nerrs)
return -1;
- list_for_each_entry(cmd, cmds, list)
+ list_for_each_entry(cmd, cmds, list) {
+ if (cmd->op != CMD_ADD)
+ continue;
+
nft_cmd_expand(cmd);
+ }
return 0;
}
--
2.34.1

64
main.nft Normal file
View File

@ -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"

30
nat.nft Normal file
View File

@ -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
}
}

8
nftables.conf Normal file
View File

@ -0,0 +1,8 @@
# 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'.

17
nftables.service Normal file
View File

@ -0,0 +1,17 @@
[Unit]
Description=Netfilter Tables
Documentation=man:nft(8)
Wants=network-pre.target
Before=network-pre.target
[Service]
Type=oneshot
ProtectSystem=full
ProtectHome=true
ExecStart=/sbin/nft -f /etc/sysconfig/nftables.conf
ExecReload=/sbin/nft 'flush ruleset; include "/etc/sysconfig/nftables.conf";'
ExecStop=/sbin/nft flush ruleset
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

560
nftables.spec Normal file
View File

@ -0,0 +1,560 @@
%define rpmversion 0.9.3
%define specrelease 26
%define libnftnl_ver 1.1.5-5
Name: nftables
Version: %{rpmversion}
Release: %{specrelease}%{?dist}%{?buildid}
# Upstream released a 0.100 version, then 0.4. Need Epoch to get back on track.
Epoch: 1
Summary: Netfilter Tables userspace utillites
License: GPLv2
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
Patch25: 0025-segtree-Fix-missing-expires-value-in-prefixes.patch
Patch26: 0026-segtree-Use-expr_clone-in-get_set_interval_.patch
Patch27: 0027-segtree-Merge-get_set_interval_find-and-get_set_inte.patch
Patch28: 0028-tests-0034get_element_0-do-not-discard-stderr.patch
Patch29: 0029-segtree-Fix-get-element-command-with-prefixes.patch
Patch30: 0030-include-Resync-nf_tables.h-cache-copy.patch
Patch31: 0031-src-Set-NFT_SET_CONCAT-flag-for-sets-with-concatenat.patch
Patch32: 0032-src-store-expr-not-dtype-to-track-data-in-sets.patch
Patch33: 0033-evaluate-Perform-set-evaluation-on-implicitly-declar.patch
Patch34: 0034-evaluate-missing-datatype-definition-in-implicit_set.patch
Patch35: 0035-mergesort-unbreak-listing-with-binops.patch
Patch36: 0036-proto-add-sctp-crc32-checksum-fixup.patch
Patch37: 0037-proto-Fix-ARP-header-field-ordering.patch
Patch38: 0038-json-echo-Speedup-seqnum_to_json.patch
Patch39: 0039-json-Fix-seqnum_to_json-functionality.patch
Patch40: 0040-json-don-t-leave-dangling-pointers-on-hlist.patch
Patch41: 0041-json-init-parser-state-for-every-new-buffer-file.patch
Patch42: 0042-tests-Disable-tests-known-to-fail-on-RHEL8.patch
Patch43: 0043-monitor-Fix-for-use-after-free-when-printing-map-ele.patch
Patch44: 0044-tests-monitor-use-correct-nft-value-in-EXIT-trap.patch
Patch45: 0045-evaluate-Reject-quoted-strings-containing-only-wildc.patch
Patch46: 0046-src-Support-odd-sized-payload-matches.patch
Patch47: 0047-src-Optimize-prefix-matches-on-byte-boundaries.patch
Patch48: 0048-tests-py-Move-tcpopt.t-to-any-directory.patch
Patch49: 0049-parser-merge-sack-perm-sack-permitted-and-maxseg-mss.patch
Patch50: 0050-tcpopts-clean-up-parser-tcpopt.c-plumbing.patch
Patch51: 0051-tcpopt-rename-noop-to-nop.patch
Patch52: 0052-tcpopt-split-tcpopt_hdr_fields-into-per-option-enum.patch
Patch53: 0053-tcpopt-allow-to-check-for-presence-of-any-tcp-option.patch
Patch54: 0054-tcp-add-raw-tcp-option-match-support.patch
Patch55: 0055-json-tcp-add-raw-tcp-option-match-support.patch
Patch56: 0056-json-Simplify-non-tcpopt-exthdr-printing-a-bit.patch
Patch57: 0057-scanner-introduce-start-condition-stack.patch
Patch58: 0058-scanner-sctp-Move-to-own-scope.patch
Patch59: 0059-exthdr-Implement-SCTP-Chunk-matching.patch
Patch60: 0060-include-missing-sctp_chunk.h-in-Makefile.am.patch
Patch61: 0061-doc-nft.8-Extend-monitor-description-by-trace.patch
Patch62: 0062-tests-shell-Fix-bogus-testsuite-failure-with-100Hz.patch
Patch63: 0063-parser_json-Fix-error-reporting-for-invalid-syntax.patch
Patch64: 0064-parser_bison-Fix-for-implicit-declaration-of-isalnum.patch
Patch65: 0065-parser_json-Fix-for-memleak-in-tcp-option-error-path.patch
Patch66: 0066-json-Drop-pointless-assignment-in-exthdr_expr_json.patch
Patch67: 0067-segtree-Fix-segfault-when-restoring-a-huge-interval-.patch
Patch68: 0068-tests-cover-baecd1cf2685-segtree-Fix-segfault-when-r.patch
Patch69: 0069-tests-shell-NFT-needs-to-be-invoked-unquoted.patch
Patch70: 0070-tests-shell-better-parameters-for-the-interval-stack.patch
Patch71: 0071-netlink-remove-unused-parameter-from-netlink_gen_stm.patch
Patch72: 0072-src-support-for-restoring-element-counters.patch
Patch73: 0073-evaluate-attempt-to-set_eval-flag-if-dynamic-updates.patch
Patch74: 0074-evaluate-fix-inet-nat-with-no-layer-3-info.patch
Patch75: 0075-tests-py-add-dnat-to-port-without-defining-destinati.patch
Patch76: 0076-mnl-do-not-build-nftnl_set-element-list.patch
Patch77: 0077-mnl-do-not-use-expr-identifier-to-fetch-device-name.patch
Patch78: 0078-tests-shell-auto-removal-of-chain-hook-on-netns-remo.patch
Patch79: 0079-rule-memleak-in-__do_add_setelems.patch
Patch80: 0080-rule-fix-element-cache-update-in-__do_add_setelems.patch
Patch81: 0081-src-rename-CMD_OBJ_SETELEM-to-CMD_OBJ_ELEMENTS.patch
Patch82: 0082-src-add-CMD_OBJ_SETELEMS.patch
Patch83: 0083-libnftables-call-nft_cmd_expand-only-with-CMD_ADD.patch
BuildRequires: autogen
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: gcc
BuildRequires: flex
BuildRequires: bison
BuildRequires: libmnl-devel
BuildRequires: gmp-devel
BuildRequires: readline-devel
BuildRequires: pkgconfig(libnftnl) >= %{libnftnl_ver}
BuildRequires: systemd
BuildRequires: asciidoc
BuildRequires: iptables-devel
BuildRequires: jansson-devel
BuildRequires: python3-devel
Requires: libnftnl >= %{libnftnl_ver}
%description
Netfilter Tables userspace utilities.
%package devel
Summary: Development library for nftables / libnftables
Group: Development/Libraries
Requires: %{name} = %{epoch}:%{version}-%{release}
Requires: pkgconfig
%description devel
Development tools and static libraries and header files for the libnftables library.
%package -n python3-nftables
Summary: Python module providing an interface to libnftables
Requires: %{name} = %{epoch}:%{version}-%{release}
%description -n python3-nftables
The nftables python module provides an interface to libnftables via ctypes.
%prep
%autosetup -p1
%build
autoreconf -fi
rm -Rf autom4te*.cache config.h.in~
%configure --disable-silent-rules --with-json --with-xtables \
--enable-python --with-python-bin=%{__python3}
make %{?_smp_mflags}
%install
%make_install
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
# Don't ship static lib (for now at least)
rm -f $RPM_BUILD_ROOT/%{_libdir}/libnftables.a
chmod 644 $RPM_BUILD_ROOT/%{_mandir}/man8/nft*
mkdir -p $RPM_BUILD_ROOT/%{_unitdir}
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 {} \; \)
# make nftables.py use the real library file name
# to avoid nftables-devel package dependency
sofile=$(readlink $RPM_BUILD_ROOT/%{_libdir}/libnftables.so)
sed -i -e 's/\(sofile=\)".*"/\1"'$sofile'"/' \
$RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py
touch -r %{SOURCE2} $RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py
%post
%systemd_post nftables.service
%preun
%systemd_preun nftables.service
%postun
%systemd_postun_with_restart nftables.service
%post devel
%ldconfig_post
%postun devel
%ldconfig_postun
%files
%license COPYING
%config(noreplace) %{_sysconfdir}/nftables/
%config(noreplace) %{_sysconfdir}/sysconfig/nftables.conf
%{_sbindir}/nft
%{_libdir}/libnftables.so.*
%{_mandir}/man5/libnftables-json.5*
%{_mandir}/man8/nft*
%{_unitdir}/nftables.service
%{_docdir}/nftables/examples/*.nft
%files devel
%{_libdir}/libnftables.so
%{_libdir}/pkgconfig/libnftables.pc
%{_includedir}/nftables/libnftables.h
%{_mandir}/man3/libnftables.3*
%files -n python3-nftables
%{python3_sitelib}/nftables-*.egg-info
%{python3_sitelib}/nftables/
%changelog
* Thu Apr 28 2022 Phil Sutter <psutter@redhat.com> [0.9.3-26.el8]
- libnftables: call nft_cmd_expand() only with CMD_ADD (Phil Sutter) [2073287]
- src: add CMD_OBJ_SETELEMS (Phil Sutter) [2073287]
- src: rename CMD_OBJ_SETELEM to CMD_OBJ_ELEMENTS (Phil Sutter) [2073287]
- rule: fix element cache update in __do_add_setelems() (Phil Sutter) [2073287]
- rule: memleak in __do_add_setelems() (Phil Sutter) [2073287]
- tests: shell: auto-removal of chain hook on netns removal (Phil Sutter) [2070924]
- mnl: do not use expr->identifier to fetch device name (Phil Sutter) [2070924]
* Fri Feb 04 2022 Phil Sutter <psutter@redhat.com> [0.9.3-25.el8]
- mnl: do not build nftnl_set element list (Phil Sutter) [2047821]
- tests: py: add dnat to port without defining destination address (Phil Sutter) [2030773]
- evaluate: fix inet nat with no layer 3 info (Phil Sutter) [2030773]
- evaluate: attempt to set_eval flag if dynamic updates requested (Phil Sutter) [2039594]
- src: support for restoring element counters (Phil Sutter) [2039594]
- netlink: remove unused parameter from netlink_gen_stmt_stateful() (Phil Sutter) [2039594]
* Wed Dec 08 2021 Phil Sutter <psutter@redhat.com> [0.9.3-24.el8]
- tests: shell: better parameters for the interval stack overflow test (Phil Sutter) [1908127]
- tests: shell: $NFT needs to be invoked unquoted (Phil Sutter) [1908127]
* Fri Nov 05 2021 Phil Sutter <psutter@redhat.com> [0.9.3-23.el8]
- tests: cover baecd1cf2685 ("segtree: Fix segfault when restoring a huge interval set") (Phil Sutter) [1908127]
- segtree: Fix segfault when restoring a huge interval set (Phil Sutter) [1908127]
* Wed Oct 06 2021 Phil Sutter <psutter@redhat.com> [0.9.3-22.el8]
- json: Drop pointless assignment in exthdr_expr_json() (Phil Sutter) [1999059]
- parser_json: Fix for memleak in tcp option error path (Phil Sutter) [1999059]
- parser_bison: Fix for implicit declaration of isalnum (Phil Sutter) [1999059]
- parser_json: Fix error reporting for invalid syntax (Phil Sutter) [1994141]
* Mon Aug 02 2021 Phil Sutter <psutter@redhat.com> [0.9.3-21.el8]
- tests: shell: Fix bogus testsuite failure with 100Hz (Phil Sutter) [1919203]
- doc: nft.8: Extend monitor description by trace (Phil Sutter) [1820365]
- include: missing sctp_chunk.h in Makefile.am (Phil Sutter) [1979334]
- exthdr: Implement SCTP Chunk matching (Phil Sutter) [1979334]
- scanner: sctp: Move to own scope (Phil Sutter) [1979334]
- scanner: introduce start condition stack (Phil Sutter) [1979334]
- json: Simplify non-tcpopt exthdr printing a bit (Phil Sutter) [1979334]
- json: tcp: add raw tcp option match support (Phil Sutter) [1979334]
- tcp: add raw tcp option match support (Phil Sutter) [1979334]
- tcpopt: allow to check for presence of any tcp option (Phil Sutter) [1979334]
- tcpopt: split tcpopt_hdr_fields into per-option enum (Phil Sutter) [1979334]
- tcpopt: rename noop to nop (Phil Sutter) [1979334]
- tcpopts: clean up parser -> tcpopt.c plumbing (Phil Sutter) [1979334]
- parser: merge sack-perm/sack-permitted and maxseg/mss (Phil Sutter) [1979334]
- tests/py: Move tcpopt.t to any/ directory (Phil Sutter) [1979334]
* Thu May 20 2021 Phil Sutter <psutter@redhat.com> [0.9.3-20.el8]
- src: Optimize prefix matches on byte-boundaries (Phil Sutter) [1934926]
- src: Support odd-sized payload matches (Phil Sutter) [1934926]
- spec: Add an rpminspect.yaml file to steer rpminspect (Phil Sutter) [1962184]
- spec: Explicitly state dist string in Release tag (Phil Sutter) [1962184]
* Wed May 19 2021 Phil Sutter <psutter@redhat.com> [0.9.3-19.el8]
- evaluate: Reject quoted strings containing only wildcard (Phil Sutter) [1818117]
- tests: monitor: use correct $nft value in EXIT trap (Phil Sutter) [1919203]
- monitor: Fix for use after free when printing map elements (Phil Sutter) [1919203]
- tests: Disable tests known to fail on RHEL8 (Phil Sutter) [1919203]
* Sat Feb 20 2021 Phil Sutter <psutter@redhat.com> [0.9.3-18.el8]
- json: init parser state for every new buffer/file (Phil Sutter) [1930873]
* Tue Jan 12 2021 Phil Sutter <psutter@redhat.com> [0.9.3-17.el8]
- json: don't leave dangling pointers on hlist (Phil Sutter) [1900565]
- json: Fix seqnum_to_json() functionality (Phil Sutter) [1900565]
- json: echo: Speedup seqnum_to_json() (Phil Sutter) [1900565]
- proto: Fix ARP header field ordering (Phil Sutter) [1896334]
- proto: add sctp crc32 checksum fixup (Phil Sutter) [1895804]
- mergesort: unbreak listing with binops (Phil Sutter) [1891790]
- evaluate: missing datatype definition in implicit_set_declaration() (Phil Sutter) [1877022]
- evaluate: Perform set evaluation on implicitly declared (anonymous) sets (Phil Sutter) [1877022]
- src: store expr, not dtype to track data in sets (Phil Sutter) [1877022]
* Sat Aug 08 2020 Phil Sutter <psutter@redhat.com> [0.9.3-16.el8]
- src: Set NFT_SET_CONCAT flag for sets with concatenated ranges (Phil Sutter) [1820684]
- include: Resync nf_tables.h cache copy (Phil Sutter) [1820684]
* Tue Jun 30 2020 Phil Sutter <psutter@redhat.com> [0.9.3-15.el8]
- segtree: Fix get element command with prefixes (Phil Sutter) [1832235]
- tests: 0034get_element_0: do not discard stderr (Phil Sutter) [1832235]
- segtree: Merge get_set_interval_find() and get_set_interval_end() (Phil Sutter) [1832235]
- segtree: Use expr_clone in get_set_interval_*() (Phil Sutter) [1832235]
- segtree: Fix missing expires value in prefixes (Phil Sutter) [1832235]
* Wed Jun 24 2020 Phil Sutter <psutter@redhat.com> [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 <psutter@redhat.com> [0.9.3-13.el8]
- parser_json: Support ranges in concat expressions (Phil Sutter) [1805798]
* Thu Mar 26 2020 Phil Sutter <psutter@redhat.com> [0.9.3-12.el8]
- Restore default config to be empty (Phil Sutter) [1694723]
* Mon Feb 17 2020 Phil Sutter <psutter@redhat.com> [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 <psutter@redhat.com> [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 <psutter@redhat.com> [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 <psutter@redhat.com> [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 <psutter@redhat.com> [0.9.3-7.el8]
- monitor: Fix output for ranges in anonymous sets (Phil Sutter) [1774742]
* Fri Jan 10 2020 Phil Sutter <psutter@redhat.com> [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 <psutter@redhat.com> [0.9.3-5.el8]
- Install an improved sample config (Phil Sutter) [1694723]
* Wed Dec 04 2019 Phil Sutter <psutter@redhat.com> [0.9.3-4.el8]
- Explicitly depend on newer libnftl version (Phil Sutter) [1643192]
* Tue Dec 03 2019 Phil Sutter <psutter@redhat.com> [0.9.3-3.el8]
- Fix permissions of osf-related configs (Phil Sutter) [1776462]
* Tue Dec 03 2019 Phil Sutter <psutter@redhat.com> [0.9.3-2.el8]
- Add example scripts to nftables package (Phil Sutter) [1643192]
* Mon Dec 02 2019 Phil Sutter <psutter@redhat.com> [0.9.3-1.el8]
- Rebase onto upstream release 0.9.3 (Phil Sutter) [1643192]
* Mon Oct 21 2019 Phil Sutter <psutter@redhat.com> [0.9.2-4.el8]
- tproxy: Add missing error checking when parsing from netlink (Phil Sutter) [1643192]
- parser_json: Fix checking of parse_policy() return code (Phil Sutter) [1643192]
* Fri Oct 18 2019 Phil Sutter <psutter@redhat.com> [0.9.2-3.el8]
- spec: Avoid multilib problems due to updated nftables.py (Phil Sutter) [1643192]
* Fri Oct 18 2019 Phil Sutter <psutter@redhat.com> [0.9.2-2.el8]
- rule: Fix for single line ct timeout printing (Phil Sutter) [1643192]
- tests/monitor: Fix for changed ct timeout format (Phil Sutter) [1643192]
- monitor: Add missing newline to error message (Phil Sutter) [1643192]
- src: restore --echo with anonymous sets (Phil Sutter) [1643192]
* Tue Oct 15 2019 Phil Sutter <psutter@redhat.com> [0.9.2-1.el8]
- src: obj: fix memleak in handle_free() (Phil Sutter) [1643192]
- libnftables: memleak when list of commands is empty (Phil Sutter) [1643192]
- mnl: do not cache sender buffer size (Phil Sutter) [1643192]
- src: meter: avoid double-space in list ruleset output (Phil Sutter) [1643192]
- src: parser_json: fix crash while restoring secmark object (Phil Sutter) [1643192]
- nftables: don't crash in 'list ruleset' if policy is not set (Phil Sutter) [1643192]
- json: tests: fix typo in ct expectation json test (Phil Sutter) [1643192]
- parser_bison: Fix 'exists' keyword on Big Endian (Phil Sutter) [1643192]
- json: fix type mismatch on "ct expect" json exporting (Phil Sutter) [1643192]
- libnftables: use-after-free in exit path (Phil Sutter) [1643192]
- netlink_delinearize: fix wrong conversion to "list" in ct mark (Phil Sutter) [1643192]
- mnl: fix --echo buffer size again (Phil Sutter) [1643192]
- parser_json: fix crash on insert rule to bad references (Phil Sutter) [1643192]
- evaluate: flag fwd and queue statements as terminal (Phil Sutter) [1643192]
- tests: shell: check that rule add with index works with echo (Phil Sutter) [1643192]
- cache: fix --echo with index/position (Phil Sutter) [1643192]
- src: secmark: fix brace indentation and missing quotes in selctx output (Phil Sutter) [1643192]
- Add python3-nftables sub-package (Phil Sutter) [1643192]
- Rebase onto upstream version 0.9.2 (Phil Sutter) [1643192]
* Mon Aug 12 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-14
- src: fix jumps on bigendian arches
- src: json: fix constant parsing on bigendian
* Thu Aug 08 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-13
- Fix for adding a rule with index and set reference
* Wed Jul 31 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-12
- Fix permissions of /etc/nftables directory
* Wed Jun 26 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-11
- Fix segfault with xtables support
* Wed Jun 26 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-10
- Fix typo in spec file
* Wed Jun 26 2019 Phil Sutter <psutter@redhat.com> - 1:0.9.0-9
- Allow variables in jump statement
- Make example configs readable only by root
- Document nft list parameters
- Document vmap statement
- Install netdev-ingress.nft sample config in the right spot
- Backport upstream fixes since last release
* Fri Mar 01 2019 Phil Sutter - 1:0.9.0-8
- Add missing patch to spec file
* Fri Dec 21 2018 Phil Sutter - 1:0.9.0-7
- src: Reject 'export vm json' command
* Tue Dec 18 2018 Phil Sutter - 1:0.9.0-6
- Rebuild for updated libnftnl
* Thu Dec 13 2018 Phil Sutter - 1:0.9.0-5
- nft.8: Document log level audit
- nft.8: Clarify 'index' option of add rule command
* Thu Oct 25 2018 Phil Sutter - 1:0.9.0-4
- Add fixes for covscan report
- Fix for ECN keyword in LHS of relational
- Update meta pkt_type value description
- Fix for segfault with JSON output if xt expression is present
- Add missing nft suffix to files included from /etc/sysconfig/nftables.conf
- Use native JSON API in nft monitor
* Thu Oct 11 2018 Phil Sutter - 1:0.9.0-3
- Enable xtables support
- Enable JSON support
* Mon Sep 10 2018 Phil Sutter - 1:0.9.0-2
- Allow icmpx in inet/bridge families
* Tue Aug 14 2018 Phil Sutter - 1:0.9.0-1
- New version 0.9.0
- Install libnftables
- Add devel sub-package
- Add gcc BuildRequires
* Sat Mar 03 2018 Kevin Fenzi <kevin@scrye.com> - 0.8.3-1
- Update to 0.8.3. Fixes bug #1551207
* Thu Feb 08 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1:0.8.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Mon Feb 05 2018 Kevin Fenzi <kevin@scrye.com> - 0.8.2-1
- Update to 0.8.2. Fixes bug #1541582
* Tue Jan 16 2018 Kevin Fenzi <kevin@scrye.com> - 0.8.1-1
- Update to 0.8.1. Fixes bug #1534982
* Sun Oct 22 2017 Kevin Fenzi <kevin@scrye.com> - 0.8-1
- Update to 0.8.
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1:0.7-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1:0.7-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1:0.7-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Thu Jan 12 2017 Igor Gnatenko <ignatenko@redhat.com> - 1:0.7-2
- Rebuild for readline 7.x
* Thu Dec 22 2016 Kevin Fenzi <kevin@scrye.com> - 0.7-1
- Update to 0.7
* Fri Jul 15 2016 Kevin Fenzi <kevin@scrye.com> - 0.6-2
- Rebuild for new glibc symbols
* Thu Jun 02 2016 Kevin Fenzi <kevin@scrye.com> - 0.6-1
- Update to 0.6.
* Sun Apr 10 2016 Kevin Fenzi <kevin@scrye.com> - 0.5-4
- Add example config files and move config to /etc/sysconfig. Fixes bug #1313936
* Fri Mar 25 2016 Kevin Fenzi <kevin@scrye.com> - 0.5-3
- Add systemd unit file. Fixes bug #1313936
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1:0.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Thu Sep 17 2015 Kevin Fenzi <kevin@scrye.com> 0.5-1
- Update to 0.5
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:0.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Sat Jan 10 2015 Kevin Fenzi <kevin@scrye.com> 0.4-2
- Add patch to fix nft -f dep gen.
* Fri Dec 26 2014 Kevin Fenzi <kevin@scrye.com> 0.4-1
- Update to 0.4
- Add Epoch to fix versioning.
* Wed Sep 03 2014 Kevin Fenzi <kevin@scrye.com> 0.100-4.20140903git
- Update to 20140903 snapshot
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.100-4.20140704git
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Fri Jul 04 2014 Kevin Fenzi <kevin@scrye.com> 0.100-3.20140704git
- Update to new snapshot
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.100-2.20140426git
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Sat Apr 26 2014 Kevin Fenzi <kevin@scrye.com> 0.100-1.20140426git
- Update t0 20140426
* Sun Mar 30 2014 Kevin Fenzi <kevin@scrye.com> 0.100-1.20140330git
- Update to 20140330 snapshot
- Sync versions to be post 0.100 release.
* Wed Mar 26 2014 Kevin Fenzi <kevin@scrye.com> 0-0.7.20140326git
- Update to 20140326 snapshot
- Fix permissions on man pages.
* Mon Mar 24 2014 Kevin Fenzi <kevin@scrye.com> 0-0.6.20140324git
- Update to 20140324 snapshot
* Fri Mar 07 2014 Kevin Fenzi <kevin@scrye.com> 0-0.5.20140307git
- Update to 20140307
* Sat Jan 25 2014 Kevin Fenzi <kevin@scrye.com> 0-0.4.20140125git
- Update to 20140125 snapshot
* Sat Jan 18 2014 Kevin Fenzi <kevin@scrye.com> 0-0.3.20140118git
- Update to 20140118 snapshot
- Fixed License tag to be correct
- Fixed changelog
- nft scripts now use full path for nft
- Fixed man page building
- Dropped unneeded rm in install
- Patched build to not be silent.
* Tue Dec 03 2013 Kevin Fenzi <kevin@scrye.com> 0-0.2.20131202git
- Use upstream snapshots for source.
- Use 0 for version.
* Sat Nov 30 2013 Kevin Fenzi <kevin@scrye.com> 0-0.1
- initial version for Fedora review

16
router.nft Normal file
View File

@ -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
}
}

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (nftables-0.9.3.tar.bz2) = d264f6fc75c95510e29fe7d5b82ae418d502f40437b098ba6117ffb1374d9989d70a7296e2e58c5fb25142145a987bb9c160902637899f892589809f9541db43