import iptables-1.8.4-17.el8
This commit is contained in:
parent
1f113a48e4
commit
e7ebe75cd0
@ -0,0 +1,167 @@
|
||||
From d1b516014e4883f30ee2faf264dd89a6d7940e2c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Sat, 3 Oct 2020 17:46:09 +0200
|
||||
Subject: [PATCH] nft: Make batch_add_chain() return the added batch object
|
||||
|
||||
Do this so in a later patch the 'skip' field can be adjusted.
|
||||
|
||||
While being at it, simplify a few callers and eliminate the need for a
|
||||
'ret' variable.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
(cherry picked from commit 0d77e64e8d9b8a3984b01a4951524dc40f61f4b6)
|
||||
|
||||
Conflicts:
|
||||
iptables/nft.c
|
||||
-> Upstream changed good/bad return codes of nft_chain_restore()
|
||||
function.
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft.c | 35 +++++++++++++++++------------------
|
||||
1 file changed, 17 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index e95e99f1d8d71..0efd18d57320f 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -398,10 +398,11 @@ batch_set_add(struct nft_handle *h, enum obj_update_type type,
|
||||
return batch_add(h, type, s);
|
||||
}
|
||||
|
||||
-static int batch_chain_add(struct nft_handle *h, enum obj_update_type type,
|
||||
+static struct obj_update *
|
||||
+batch_chain_add(struct nft_handle *h, enum obj_update_type type,
|
||||
struct nftnl_chain *c)
|
||||
{
|
||||
- return batch_add(h, type, c) ? 0 : -1;
|
||||
+ return batch_add(h, type, c);
|
||||
}
|
||||
|
||||
static struct obj_update *
|
||||
@@ -910,7 +911,6 @@ int nft_chain_set(struct nft_handle *h, const char *table,
|
||||
const struct xt_counters *counters)
|
||||
{
|
||||
struct nftnl_chain *c = NULL;
|
||||
- int ret;
|
||||
|
||||
nft_fn = nft_chain_set;
|
||||
|
||||
@@ -924,10 +924,11 @@ int nft_chain_set(struct nft_handle *h, const char *table,
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
|
||||
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c))
|
||||
+ return 0;
|
||||
|
||||
/* the core expects 1 for success and 0 for error */
|
||||
- return ret == 0 ? 1 : 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
|
||||
@@ -1734,7 +1735,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
|
||||
{
|
||||
struct nftnl_chain_list *list;
|
||||
struct nftnl_chain *c;
|
||||
- int ret;
|
||||
|
||||
nft_fn = nft_chain_user_add;
|
||||
|
||||
@@ -1754,14 +1754,15 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
|
||||
if (h->family == NFPROTO_BRIDGE)
|
||||
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
|
||||
|
||||
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c))
|
||||
+ return 0;
|
||||
|
||||
list = nft_chain_list_get(h, table, chain);
|
||||
if (list)
|
||||
nftnl_chain_list_add(c, list);
|
||||
|
||||
/* the core expects 1 for success and 0 for error */
|
||||
- return ret == 0 ? 1 : 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table)
|
||||
@@ -1769,7 +1770,6 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
|
||||
struct nftnl_chain_list *list;
|
||||
struct nftnl_chain *c;
|
||||
bool created = false;
|
||||
- int ret;
|
||||
|
||||
c = nft_chain_find(h, table, chain);
|
||||
if (c) {
|
||||
@@ -1794,13 +1794,14 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
|
||||
if (!created)
|
||||
return 0;
|
||||
|
||||
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c))
|
||||
+ return -1;
|
||||
|
||||
list = nft_chain_list_get(h, table, chain);
|
||||
if (list)
|
||||
nftnl_chain_list_add(c, list);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/* From linux/netlink.h */
|
||||
@@ -1818,7 +1819,6 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
|
||||
{
|
||||
struct chain_user_del_data *d = data;
|
||||
struct nft_handle *h = d->handle;
|
||||
- int ret;
|
||||
|
||||
/* don't delete built-in chain */
|
||||
if (nft_chain_builtin(c))
|
||||
@@ -1834,8 +1834,7 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
|
||||
|
||||
/* XXX This triggers a fast lookup from the kernel. */
|
||||
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
|
||||
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
|
||||
- if (ret)
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c))
|
||||
return -1;
|
||||
|
||||
nftnl_chain_list_del(c);
|
||||
@@ -1910,7 +1909,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
|
||||
{
|
||||
struct nftnl_chain *c;
|
||||
uint64_t handle;
|
||||
- int ret;
|
||||
|
||||
nft_fn = nft_chain_user_rename;
|
||||
|
||||
@@ -1941,10 +1939,11 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
|
||||
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, newname);
|
||||
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
|
||||
|
||||
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c))
|
||||
+ return 0;
|
||||
|
||||
/* the core expects 1 for success and 0 for error */
|
||||
- return ret == 0 ? 1 : 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
bool nft_table_find(struct nft_handle *h, const char *tablename)
|
||||
@@ -3217,7 +3216,7 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
|
||||
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
|
||||
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
|
||||
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
|
||||
- if (batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c))
|
||||
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c))
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,42 @@
|
||||
From 2dff9a669400644ec1e66d394b03d743eec2cd55 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon, 5 Oct 2020 15:54:35 +0200
|
||||
Subject: [PATCH] nft: Fix error reporting for refreshed transactions
|
||||
|
||||
When preparing a batch from the list of batch objects in nft_action(),
|
||||
the sequence number used for each object is stored within that object
|
||||
for later matching against returned error messages. Though if the
|
||||
transaction has to be refreshed, some of those objects may be skipped,
|
||||
other objects take over their sequence number and errors are matched to
|
||||
skipped objects. Avoid this by resetting the skipped object's sequence
|
||||
number to zero.
|
||||
|
||||
Fixes: 58d7de0181f61 ("xtables: handle concurrent ruleset modifications")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
(cherry picked from commit e98b825a037807bf6c918eb66ee9682cc4c46183)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index 0efd18d57320f..d661ac2cafda6 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -2767,9 +2767,10 @@ retry:
|
||||
h->nft_genid++;
|
||||
|
||||
list_for_each_entry(n, &h->obj_list, head) {
|
||||
-
|
||||
- if (n->skip)
|
||||
+ if (n->skip) {
|
||||
+ n->seq = 0;
|
||||
continue;
|
||||
+ }
|
||||
|
||||
n->seq = seq++;
|
||||
switch (n->type) {
|
||||
--
|
||||
2.28.0
|
||||
|
242
SOURCES/0028-nft-Fix-for-concurrent-noflush-restore-calls.patch
Normal file
242
SOURCES/0028-nft-Fix-for-concurrent-noflush-restore-calls.patch
Normal file
@ -0,0 +1,242 @@
|
||||
From 575a1e5589f813af7e838c045863b510b4740353 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon, 5 Oct 2020 16:06:49 +0200
|
||||
Subject: [PATCH] nft: Fix for concurrent noflush restore calls
|
||||
|
||||
Transaction refresh was broken with regards to nft_chain_restore(): It
|
||||
created a rule flush batch object only if the chain was found in cache
|
||||
and a chain add object only if the chain was not found. Yet with
|
||||
concurrent ruleset updates, one has to expect both situations:
|
||||
|
||||
* If a chain vanishes, the rule flush job must be skipped and instead
|
||||
the chain add job become active.
|
||||
|
||||
* If a chain appears, the chain add job must be skipped and instead
|
||||
rules flushed.
|
||||
|
||||
Change the code accordingly: Create both batch objects and set their
|
||||
'skip' field depending on the situation in cache and adjust both in
|
||||
nft_refresh_transaction().
|
||||
|
||||
As a side-effect, the implicit rule flush becomes explicit and all
|
||||
handling of implicit batch jobs is dropped along with the related field
|
||||
indicating such.
|
||||
|
||||
Reuse the 'implicit' parameter of __nft_rule_flush() to control the
|
||||
initial 'skip' field value instead.
|
||||
|
||||
A subtle caveat is vanishing of existing chains: Creating the chain add
|
||||
job based on the chain in cache causes a netlink message containing that
|
||||
chain's handle which the kernel dislikes. Therefore unset the chain's
|
||||
handle in that case.
|
||||
|
||||
Fixes: 58d7de0181f61 ("xtables: handle concurrent ruleset modifications")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit dac904bdcd9a18aabafee7275ccf0c2bd53800f3)
|
||||
|
||||
Conflicts:
|
||||
iptables/nft.c
|
||||
-> Upstream changed good/bad return codes of nft_chain_restore()
|
||||
function.
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft.c | 58 ++++++++++---------
|
||||
.../ipt-restore/0016-concurrent-restores_0 | 53 +++++++++++++++++
|
||||
2 files changed, 83 insertions(+), 28 deletions(-)
|
||||
create mode 100755 iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index d661ac2cafda6..dc5490c085364 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -283,7 +283,6 @@ struct obj_update {
|
||||
struct list_head head;
|
||||
enum obj_update_type type:8;
|
||||
uint8_t skip:1;
|
||||
- uint8_t implicit:1;
|
||||
unsigned int seq;
|
||||
union {
|
||||
struct nftnl_table *table;
|
||||
@@ -1650,7 +1649,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
|
||||
|
||||
static void
|
||||
__nft_rule_flush(struct nft_handle *h, const char *table,
|
||||
- const char *chain, bool verbose, bool implicit)
|
||||
+ const char *chain, bool verbose, bool skip)
|
||||
{
|
||||
struct obj_update *obj;
|
||||
struct nftnl_rule *r;
|
||||
@@ -1672,7 +1671,7 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
|
||||
return;
|
||||
}
|
||||
|
||||
- obj->implicit = implicit;
|
||||
+ obj->skip = skip;
|
||||
}
|
||||
|
||||
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
|
||||
@@ -1768,17 +1767,12 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
|
||||
int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table)
|
||||
{
|
||||
struct nftnl_chain_list *list;
|
||||
+ struct obj_update *obj;
|
||||
struct nftnl_chain *c;
|
||||
bool created = false;
|
||||
|
||||
c = nft_chain_find(h, table, chain);
|
||||
- if (c) {
|
||||
- /* Apparently -n still flushes existing user defined
|
||||
- * chains that are redefined.
|
||||
- */
|
||||
- if (h->noflush)
|
||||
- __nft_rule_flush(h, table, chain, false, true);
|
||||
- } else {
|
||||
+ if (!c) {
|
||||
c = nftnl_chain_alloc();
|
||||
if (!c)
|
||||
return -1;
|
||||
@@ -1786,20 +1780,26 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
|
||||
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
|
||||
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
|
||||
created = true;
|
||||
- }
|
||||
|
||||
- if (h->family == NFPROTO_BRIDGE)
|
||||
- nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
|
||||
+ list = nft_chain_list_get(h, table, chain);
|
||||
+ if (list)
|
||||
+ nftnl_chain_list_add(c, list);
|
||||
+ } else {
|
||||
+ /* If the chain should vanish meanwhile, kernel genid changes
|
||||
+ * and the transaction is refreshed enabling the chain add
|
||||
+ * object. With the handle still set, kernel interprets it as a
|
||||
+ * chain replace job and errors since it is not found anymore.
|
||||
+ */
|
||||
+ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
|
||||
+ }
|
||||
|
||||
- if (!created)
|
||||
- return 0;
|
||||
+ __nft_rule_flush(h, table, chain, false, created);
|
||||
|
||||
- if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c))
|
||||
+ obj = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
|
||||
+ if (!obj)
|
||||
return -1;
|
||||
|
||||
- list = nft_chain_list_get(h, table, chain);
|
||||
- if (list)
|
||||
- nftnl_chain_list_add(c, list);
|
||||
+ obj->skip = !created;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2693,11 +2693,6 @@ static void nft_refresh_transaction(struct nft_handle *h)
|
||||
h->error.lineno = 0;
|
||||
|
||||
list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
|
||||
- if (n->implicit) {
|
||||
- batch_obj_del(h, n);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
switch (n->type) {
|
||||
case NFT_COMPAT_TABLE_FLUSH:
|
||||
tablename = nftnl_table_get_str(n->table, NFTNL_TABLE_NAME);
|
||||
@@ -2723,14 +2718,22 @@ static void nft_refresh_transaction(struct nft_handle *h)
|
||||
|
||||
c = nft_chain_find(h, tablename, chainname);
|
||||
if (c) {
|
||||
- /* -restore -n flushes existing rules from redefined user-chain */
|
||||
- __nft_rule_flush(h, tablename,
|
||||
- chainname, false, true);
|
||||
n->skip = 1;
|
||||
} else if (!c) {
|
||||
n->skip = 0;
|
||||
}
|
||||
break;
|
||||
+ case NFT_COMPAT_RULE_FLUSH:
|
||||
+ tablename = nftnl_rule_get_str(n->rule, NFTNL_RULE_TABLE);
|
||||
+ if (!tablename)
|
||||
+ continue;
|
||||
+
|
||||
+ chainname = nftnl_rule_get_str(n->rule, NFTNL_RULE_CHAIN);
|
||||
+ if (!chainname)
|
||||
+ continue;
|
||||
+
|
||||
+ n->skip = !nft_chain_find(h, tablename, chainname);
|
||||
+ break;
|
||||
case NFT_COMPAT_TABLE_ADD:
|
||||
case NFT_COMPAT_CHAIN_ADD:
|
||||
case NFT_COMPAT_CHAIN_ZERO:
|
||||
@@ -2742,7 +2745,6 @@ static void nft_refresh_transaction(struct nft_handle *h)
|
||||
case NFT_COMPAT_RULE_INSERT:
|
||||
case NFT_COMPAT_RULE_REPLACE:
|
||||
case NFT_COMPAT_RULE_DELETE:
|
||||
- case NFT_COMPAT_RULE_FLUSH:
|
||||
case NFT_COMPAT_SET_ADD:
|
||||
break;
|
||||
}
|
||||
diff --git a/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0 b/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
new file mode 100755
|
||||
index 0000000000000..53ec12fa368af
|
||||
--- /dev/null
|
||||
+++ b/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
@@ -0,0 +1,53 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+RS="*filter
|
||||
+:INPUT ACCEPT [12024:3123388]
|
||||
+:FORWARD ACCEPT [0:0]
|
||||
+:OUTPUT ACCEPT [12840:2144421]
|
||||
+:FOO - [0:0]
|
||||
+:BAR0 - [0:0]
|
||||
+:BAR1 - [0:0]
|
||||
+:BAR2 - [0:0]
|
||||
+:BAR3 - [0:0]
|
||||
+:BAR4 - [0:0]
|
||||
+:BAR5 - [0:0]
|
||||
+:BAR6 - [0:0]
|
||||
+:BAR7 - [0:0]
|
||||
+:BAR8 - [0:0]
|
||||
+:BAR9 - [0:0]
|
||||
+"
|
||||
+
|
||||
+RS1="$RS
|
||||
+-X BAR3
|
||||
+-X BAR6
|
||||
+-X BAR9
|
||||
+-A FOO -s 9.9.0.1/32 -j BAR1
|
||||
+-A FOO -s 9.9.0.2/32 -j BAR2
|
||||
+-A FOO -s 9.9.0.4/32 -j BAR4
|
||||
+-A FOO -s 9.9.0.5/32 -j BAR5
|
||||
+-A FOO -s 9.9.0.7/32 -j BAR7
|
||||
+-A FOO -s 9.9.0.8/32 -j BAR8
|
||||
+COMMIT
|
||||
+"
|
||||
+
|
||||
+RS2="$RS
|
||||
+-X BAR2
|
||||
+-X BAR5
|
||||
+-X BAR7
|
||||
+-A FOO -s 9.9.0.1/32 -j BAR1
|
||||
+-A FOO -s 9.9.0.3/32 -j BAR3
|
||||
+-A FOO -s 9.9.0.4/32 -j BAR4
|
||||
+-A FOO -s 9.9.0.6/32 -j BAR6
|
||||
+-A FOO -s 9.9.0.8/32 -j BAR8
|
||||
+-A FOO -s 9.9.0.9/32 -j BAR9
|
||||
+COMMIT
|
||||
+"
|
||||
+
|
||||
+for n in $(seq 1 10); do
|
||||
+ $XT_MULTI iptables-restore --noflush -w <<< "$RS1" &
|
||||
+ $XT_MULTI iptables-restore --noflush -w <<< "$RS2" &
|
||||
+ wait -n
|
||||
+ wait -n
|
||||
+done
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 674cce10a34e90f2791a3d58789793eef29e8f8b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon, 26 Oct 2020 17:25:03 +0100
|
||||
Subject: [PATCH] tests: shell: Improve concurrent noflush restore test a bit
|
||||
|
||||
The described issue happens only if chain FOO does not exist at program
|
||||
start so flush the ruleset after each iteration to make sure this is the
|
||||
case. Sadly the bug is still not 100% reproducible on my testing VM.
|
||||
|
||||
While being at it, add a paragraph describing what exact situation the
|
||||
test is trying to provoke.
|
||||
|
||||
Fixes: dac904bdcd9a1 ("nft: Fix for concurrent noflush restore calls")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit ed8c8b9316451a4499eeb592d2cf7d782bbe4e9a)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../ipt-restore/0016-concurrent-restores_0 | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0 b/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
index 53ec12fa368af..aa746ab458a3c 100755
|
||||
--- a/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
+++ b/iptables/tests/shell/testcases/ipt-restore/0016-concurrent-restores_0
|
||||
@@ -1,5 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
+# test for iptables-restore --noflush skipping an explicitly requested chain
|
||||
+# flush because the chain did not exist when cache was fetched. In order to
|
||||
+# expect for that chain to appear when refreshing the transaction (due to a
|
||||
+# concurrent ruleset change), the chain flush job has to be present in batch
|
||||
+# job list (although disabled at first).
|
||||
+# The input line requesting chain flush is ':FOO - [0:0]'. RS1 and RS2 contents
|
||||
+# are crafted to cause EBUSY when deleting the BAR* chains if FOO is not
|
||||
+# flushed in the same transaction.
|
||||
+
|
||||
set -e
|
||||
|
||||
RS="*filter
|
||||
@@ -45,7 +54,12 @@ RS2="$RS
|
||||
COMMIT
|
||||
"
|
||||
|
||||
+NORS="*filter
|
||||
+COMMIT
|
||||
+"
|
||||
+
|
||||
for n in $(seq 1 10); do
|
||||
+ $XT_MULTI iptables-restore <<< "$NORS"
|
||||
$XT_MULTI iptables-restore --noflush -w <<< "$RS1" &
|
||||
$XT_MULTI iptables-restore --noflush -w <<< "$RS2" &
|
||||
wait -n
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,80 @@
|
||||
From 2c183a2457d8640aaee3a98fc8fea70bf64d46f2 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Sat, 29 Feb 2020 02:08:26 +0100
|
||||
Subject: [PATCH] nft: cache: Make nft_rebuild_cache() respect fake cache
|
||||
|
||||
If transaction needed a refresh in nft_action(), restore with flush
|
||||
would fetch a full cache instead of merely refreshing table list
|
||||
contained in "fake" cache.
|
||||
|
||||
To fix this, nft_rebuild_cache() must distinguish between fake cache and
|
||||
full rule cache. Therefore introduce NFT_CL_FAKE to be distinguished
|
||||
from NFT_CL_RULES.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 40ad7793d1884f28767cf58c96e9d76ae0a18db1)
|
||||
|
||||
RHEL-only fix: Make nft_rebuild_cache() check 'level' instead of
|
||||
'h->cache_level' as the latter may be reset by __nft_flush_cache().
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft-cache.c | 13 +++++++++----
|
||||
iptables/nft.h | 3 ++-
|
||||
2 files changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
|
||||
index bc6e7f7eaebfb..9623b463f0dd5 100644
|
||||
--- a/iptables/nft-cache.c
|
||||
+++ b/iptables/nft-cache.c
|
||||
@@ -480,6 +480,7 @@ __nft_build_cache(struct nft_handle *h, enum nft_cache_level level,
|
||||
break;
|
||||
/* fall through */
|
||||
case NFT_CL_RULES:
|
||||
+ case NFT_CL_FAKE:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -516,7 +517,7 @@ void nft_fake_cache(struct nft_handle *h)
|
||||
|
||||
h->cache->table[type].chains = nftnl_chain_list_alloc();
|
||||
}
|
||||
- h->cache_level = NFT_CL_RULES;
|
||||
+ h->cache_level = NFT_CL_FAKE;
|
||||
mnl_genid_get(h, &h->nft_genid);
|
||||
}
|
||||
|
||||
@@ -629,9 +630,13 @@ void nft_rebuild_cache(struct nft_handle *h)
|
||||
if (h->cache_level)
|
||||
__nft_flush_cache(h);
|
||||
|
||||
- h->nft_genid = 0;
|
||||
- h->cache_level = NFT_CL_NONE;
|
||||
- __nft_build_cache(h, level, NULL, NULL, NULL);
|
||||
+ if (level == NFT_CL_FAKE) {
|
||||
+ nft_fake_cache(h);
|
||||
+ } else {
|
||||
+ h->nft_genid = 0;
|
||||
+ h->cache_level = NFT_CL_NONE;
|
||||
+ __nft_build_cache(h, level, NULL, NULL, NULL);
|
||||
+ }
|
||||
}
|
||||
|
||||
void nft_release_cache(struct nft_handle *h)
|
||||
diff --git a/iptables/nft.h b/iptables/nft.h
|
||||
index 5cf260a6d2cd3..2094b01455194 100644
|
||||
--- a/iptables/nft.h
|
||||
+++ b/iptables/nft.h
|
||||
@@ -32,7 +32,8 @@ enum nft_cache_level {
|
||||
NFT_CL_TABLES,
|
||||
NFT_CL_CHAINS,
|
||||
NFT_CL_SETS,
|
||||
- NFT_CL_RULES
|
||||
+ NFT_CL_RULES,
|
||||
+ NFT_CL_FAKE /* must be last entry */
|
||||
};
|
||||
|
||||
struct nft_cache {
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,60 @@
|
||||
From 74a62264d4615ae7f76454e7ca406c46a62c7999 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon, 28 Sep 2020 18:57:18 +0200
|
||||
Subject: [PATCH] nft: Fix for broken address mask match detection
|
||||
|
||||
Trying to decide whether a bitwise expression is needed to match parts
|
||||
of a source or destination address only, add_addr() checks if all bytes
|
||||
in 'mask' are 0xff or not. The check is apparently broken though as each
|
||||
byte in 'mask' is cast to a signed char before comparing against 0xff,
|
||||
therefore the bitwise is always added:
|
||||
|
||||
| # ./bad/iptables-nft -A foo -s 10.0.0.1 -j ACCEPT
|
||||
| # ./good/iptables-nft -A foo -s 10.0.0.2 -j ACCEPT
|
||||
| # nft --debug=netlink list chain ip filter foo
|
||||
| ip filter foo 5
|
||||
| [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
| [ bitwise reg 1 = (reg=1 & 0xffffffff ) ^ 0x00000000 ]
|
||||
| [ cmp eq reg 1 0x0100000a ]
|
||||
| [ counter pkts 0 bytes 0 ]
|
||||
| [ immediate reg 0 accept ]
|
||||
|
|
||||
| ip filter foo 6 5
|
||||
| [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
| [ cmp eq reg 1 0x0200000a ]
|
||||
| [ counter pkts 0 bytes 0 ]
|
||||
| [ immediate reg 0 accept ]
|
||||
|
|
||||
| table ip filter {
|
||||
| chain foo {
|
||||
| ip saddr 10.0.0.1 counter packets 0 bytes 0 accept
|
||||
| ip saddr 10.0.0.2 counter packets 0 bytes 0 accept
|
||||
| }
|
||||
| }
|
||||
|
||||
Fix the cast, safe an extra op and gain 100% performance in ideal cases.
|
||||
|
||||
Fixes: 56859380eb328 ("xtables-compat: avoid unneeded bitwise ops")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 72ed608bf1ea550ac13b5b880afc7ad3ffa0afd0)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft-shared.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
|
||||
index 78e422781723f..f60f5df97fb86 100644
|
||||
--- a/iptables/nft-shared.c
|
||||
+++ b/iptables/nft-shared.c
|
||||
@@ -165,7 +165,7 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
|
||||
void add_addr(struct nftnl_rule *r, int offset,
|
||||
void *data, void *mask, size_t len, uint32_t op)
|
||||
{
|
||||
- const char *m = mask;
|
||||
+ const unsigned char *m = mask;
|
||||
int i;
|
||||
|
||||
add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
||||
--
|
||||
2.28.0
|
||||
|
150
SOURCES/0032-nft-Optimize-class-based-IP-prefix-matches.patch
Normal file
150
SOURCES/0032-nft-Optimize-class-based-IP-prefix-matches.patch
Normal file
@ -0,0 +1,150 @@
|
||||
From 87a2128fcfd4c5b0847a8c611652ade8c54d8185 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 2 Oct 2020 09:44:38 +0200
|
||||
Subject: [PATCH] nft: Optimize class-based IP prefix matches
|
||||
|
||||
Payload expression works on byte-boundaries, leverage this with suitable
|
||||
prefix lengths.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 323259001d617ae359430a03ee3d3e7f107684e0)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft-arp.c | 11 ++++++++---
|
||||
iptables/nft-ipv4.c | 6 ++++--
|
||||
iptables/nft-ipv6.c | 6 ++++--
|
||||
iptables/nft-shared.c | 14 ++++++++++----
|
||||
iptables/nft-shared.h | 4 ++++
|
||||
5 files changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
|
||||
index d4a86610ec217..ac400e484a4fa 100644
|
||||
--- a/iptables/nft-arp.c
|
||||
+++ b/iptables/nft-arp.c
|
||||
@@ -303,7 +303,8 @@ static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
|
||||
memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- memset(info->mask, 0xff, ETH_ALEN);
|
||||
+ memset(info->mask, 0xff,
|
||||
+ min(ctx->payload.len, ETH_ALEN));
|
||||
}
|
||||
|
||||
return inv;
|
||||
@@ -360,7 +361,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv4(ctx, &fw->arp.smsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- fw->arp.smsk.s_addr = 0xffffffff;
|
||||
+ memset(&fw->arp.smsk, 0xff,
|
||||
+ min(ctx->payload.len,
|
||||
+ sizeof(struct in_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
@@ -380,7 +383,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv4(ctx, &fw->arp.tmsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- fw->arp.tmsk.s_addr = 0xffffffff;
|
||||
+ memset(&fw->arp.tmsk, 0xff,
|
||||
+ min(ctx->payload.len,
|
||||
+ sizeof(struct in_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
|
||||
index 70634f8fad84d..c84af2df90da7 100644
|
||||
--- a/iptables/nft-ipv4.c
|
||||
+++ b/iptables/nft-ipv4.c
|
||||
@@ -199,7 +199,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv4(ctx, &cs->fw.ip.smsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- cs->fw.ip.smsk.s_addr = 0xffffffff;
|
||||
+ memset(&cs->fw.ip.smsk, 0xff,
|
||||
+ min(ctx->payload.len, sizeof(struct in_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
@@ -212,7 +213,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv4(ctx, &cs->fw.ip.dmsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- cs->fw.ip.dmsk.s_addr = 0xffffffff;
|
||||
+ memset(&cs->fw.ip.dmsk, 0xff,
|
||||
+ min(ctx->payload.len, sizeof(struct in_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
|
||||
index d01491bfdb689..cfced245a781c 100644
|
||||
--- a/iptables/nft-ipv6.c
|
||||
+++ b/iptables/nft-ipv6.c
|
||||
@@ -146,7 +146,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv6(ctx, &cs->fw6.ipv6.smsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- memset(&cs->fw6.ipv6.smsk, 0xff, sizeof(struct in6_addr));
|
||||
+ memset(&cs->fw6.ipv6.smsk, 0xff,
|
||||
+ min(ctx->payload.len, sizeof(struct in6_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
@@ -159,7 +160,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
|
||||
parse_mask_ipv6(ctx, &cs->fw6.ipv6.dmsk);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- memset(&cs->fw6.ipv6.dmsk, 0xff, sizeof(struct in6_addr));
|
||||
+ memset(&cs->fw6.ipv6.dmsk, 0xff,
|
||||
+ min(ctx->payload.len, sizeof(struct in6_addr)));
|
||||
}
|
||||
|
||||
if (inv)
|
||||
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
|
||||
index f60f5df97fb86..b1237049d0a34 100644
|
||||
--- a/iptables/nft-shared.c
|
||||
+++ b/iptables/nft-shared.c
|
||||
@@ -166,16 +166,22 @@ void add_addr(struct nftnl_rule *r, int offset,
|
||||
void *data, void *mask, size_t len, uint32_t op)
|
||||
{
|
||||
const unsigned char *m = mask;
|
||||
+ bool bitwise = false;
|
||||
int i;
|
||||
|
||||
- add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
||||
-
|
||||
for (i = 0; i < len; i++) {
|
||||
- if (m[i] != 0xff)
|
||||
+ if (m[i] != 0xff) {
|
||||
+ bitwise = m[i] != 0;
|
||||
break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- if (i != len)
|
||||
+ if (!bitwise)
|
||||
+ len = i;
|
||||
+
|
||||
+ add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
||||
+
|
||||
+ if (bitwise)
|
||||
add_bitwise(r, mask, len);
|
||||
|
||||
add_cmp_ptr(r, op, data, len);
|
||||
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
|
||||
index bee99a7dd0c93..c7f1e366b75ee 100644
|
||||
--- a/iptables/nft-shared.h
|
||||
+++ b/iptables/nft-shared.h
|
||||
@@ -252,4 +252,8 @@ void xtables_restore_parse(struct nft_handle *h,
|
||||
const struct nft_xt_restore_parse *p);
|
||||
|
||||
void nft_check_xt_legacy(int family, bool is_ipt_save);
|
||||
+
|
||||
+#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
+#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.28.0
|
||||
|
218
SOURCES/0033-ebtables-Optimize-masked-MAC-address-matches.patch
Normal file
218
SOURCES/0033-ebtables-Optimize-masked-MAC-address-matches.patch
Normal file
@ -0,0 +1,218 @@
|
||||
From 03a484b63c5a61678555bcaca68fa36dc81468c1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 30 Oct 2020 14:08:33 +0100
|
||||
Subject: [PATCH] ebtables: Optimize masked MAC address matches
|
||||
|
||||
Just like with class-based prefix matches in iptables-nft, optimize
|
||||
masked MAC address matches if the mask is on a byte-boundary.
|
||||
|
||||
To reuse the logic in add_addr(), extend it to accept the payload base
|
||||
value via parameter.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 274cb05edc58d6fa982a34c84b2f4cf6acc3e335)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/nft-arp.c | 12 ++++++++----
|
||||
iptables/nft-bridge.c | 22 ++++++++++------------
|
||||
iptables/nft-ipv4.c | 6 ++++--
|
||||
iptables/nft-ipv6.c | 6 ++++--
|
||||
iptables/nft-shared.c | 5 ++---
|
||||
iptables/nft-shared.h | 3 ++-
|
||||
6 files changed, 30 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
|
||||
index ac400e484a4fa..776b55949472b 100644
|
||||
--- a/iptables/nft-arp.c
|
||||
+++ b/iptables/nft-arp.c
|
||||
@@ -178,7 +178,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
|
||||
if (need_devaddr(&fw->arp.src_devaddr)) {
|
||||
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR);
|
||||
- add_addr(r, sizeof(struct arphdr),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ sizeof(struct arphdr),
|
||||
&fw->arp.src_devaddr.addr,
|
||||
&fw->arp.src_devaddr.mask,
|
||||
fw->arp.arhln, op);
|
||||
@@ -189,7 +190,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
fw->arp.smsk.s_addr != 0 ||
|
||||
fw->arp.invflags & ARPT_INV_SRCIP) {
|
||||
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP);
|
||||
- add_addr(r, sizeof(struct arphdr) + fw->arp.arhln,
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ sizeof(struct arphdr) + fw->arp.arhln,
|
||||
&fw->arp.src.s_addr, &fw->arp.smsk.s_addr,
|
||||
sizeof(struct in_addr), op);
|
||||
}
|
||||
@@ -197,7 +199,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
|
||||
if (need_devaddr(&fw->arp.tgt_devaddr)) {
|
||||
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTDEVADDR);
|
||||
- add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
|
||||
&fw->arp.tgt_devaddr.addr,
|
||||
&fw->arp.tgt_devaddr.mask,
|
||||
fw->arp.arhln, op);
|
||||
@@ -207,7 +210,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
fw->arp.tmsk.s_addr != 0 ||
|
||||
fw->arp.invflags & ARPT_INV_TGTIP) {
|
||||
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
|
||||
- add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
|
||||
&fw->arp.tgt.s_addr, &fw->arp.tmsk.s_addr,
|
||||
sizeof(struct in_addr), op);
|
||||
}
|
||||
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
|
||||
index 3f85cbbf5e4cf..2aa15e2d1e69d 100644
|
||||
--- a/iptables/nft-bridge.c
|
||||
+++ b/iptables/nft-bridge.c
|
||||
@@ -159,20 +159,16 @@ static int nft_bridge_add(struct nft_handle *h,
|
||||
|
||||
if (fw->bitmask & EBT_ISOURCE) {
|
||||
op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
|
||||
- add_payload(r, offsetof(struct ethhdr, h_source), 6,
|
||||
- NFT_PAYLOAD_LL_HEADER);
|
||||
- if (!mac_all_ones(fw->sourcemsk))
|
||||
- add_bitwise(r, fw->sourcemsk, 6);
|
||||
- add_cmp_ptr(r, op, fw->sourcemac, 6);
|
||||
+ add_addr(r, NFT_PAYLOAD_LL_HEADER,
|
||||
+ offsetof(struct ethhdr, h_source),
|
||||
+ fw->sourcemac, fw->sourcemsk, ETH_ALEN, op);
|
||||
}
|
||||
|
||||
if (fw->bitmask & EBT_IDEST) {
|
||||
op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
|
||||
- add_payload(r, offsetof(struct ethhdr, h_dest), 6,
|
||||
- NFT_PAYLOAD_LL_HEADER);
|
||||
- if (!mac_all_ones(fw->destmsk))
|
||||
- add_bitwise(r, fw->destmsk, 6);
|
||||
- add_cmp_ptr(r, op, fw->destmac, 6);
|
||||
+ add_addr(r, NFT_PAYLOAD_LL_HEADER,
|
||||
+ offsetof(struct ethhdr, h_dest),
|
||||
+ fw->destmac, fw->destmsk, ETH_ALEN, op);
|
||||
}
|
||||
|
||||
if ((fw->bitmask & EBT_NOPROTO) == 0) {
|
||||
@@ -258,7 +254,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
|
||||
memcpy(fw->destmsk, ctx->bitwise.mask, ETH_ALEN);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- memset(&fw->destmsk, 0xff, ETH_ALEN);
|
||||
+ memset(&fw->destmsk, 0xff,
|
||||
+ min(ctx->payload.len, ETH_ALEN));
|
||||
}
|
||||
fw->bitmask |= EBT_IDEST;
|
||||
break;
|
||||
@@ -272,7 +269,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
|
||||
memcpy(fw->sourcemsk, ctx->bitwise.mask, ETH_ALEN);
|
||||
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
||||
} else {
|
||||
- memset(&fw->sourcemsk, 0xff, ETH_ALEN);
|
||||
+ memset(&fw->sourcemsk, 0xff,
|
||||
+ min(ctx->payload.len, ETH_ALEN));
|
||||
}
|
||||
fw->bitmask |= EBT_ISOURCE;
|
||||
break;
|
||||
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
|
||||
index c84af2df90da7..5bd0710781533 100644
|
||||
--- a/iptables/nft-ipv4.c
|
||||
+++ b/iptables/nft-ipv4.c
|
||||
@@ -50,13 +50,15 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
|
||||
if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
|
||||
op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
|
||||
- add_addr(r, offsetof(struct iphdr, saddr),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ offsetof(struct iphdr, saddr),
|
||||
&cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
|
||||
sizeof(struct in_addr), op);
|
||||
}
|
||||
if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
|
||||
op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
|
||||
- add_addr(r, offsetof(struct iphdr, daddr),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ offsetof(struct iphdr, daddr),
|
||||
&cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
|
||||
sizeof(struct in_addr), op);
|
||||
}
|
||||
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
|
||||
index cfced245a781c..6ece631d85f59 100644
|
||||
--- a/iptables/nft-ipv6.c
|
||||
+++ b/iptables/nft-ipv6.c
|
||||
@@ -51,7 +51,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.smsk) ||
|
||||
(cs->fw6.ipv6.invflags & IPT_INV_SRCIP)) {
|
||||
op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_SRCIP);
|
||||
- add_addr(r, offsetof(struct ip6_hdr, ip6_src),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ offsetof(struct ip6_hdr, ip6_src),
|
||||
&cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
|
||||
sizeof(struct in6_addr), op);
|
||||
}
|
||||
@@ -59,7 +60,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dmsk) ||
|
||||
(cs->fw6.ipv6.invflags & IPT_INV_DSTIP)) {
|
||||
op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_DSTIP);
|
||||
- add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
|
||||
+ add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
|
||||
+ offsetof(struct ip6_hdr, ip6_dst),
|
||||
&cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
|
||||
sizeof(struct in6_addr), op);
|
||||
}
|
||||
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
|
||||
index b1237049d0a34..2aae0a3a49dfe 100644
|
||||
--- a/iptables/nft-shared.c
|
||||
+++ b/iptables/nft-shared.c
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <xtables.h>
|
||||
|
||||
-#include <linux/netfilter/nf_tables.h>
|
||||
#include <linux/netfilter/xt_comment.h>
|
||||
#include <linux/netfilter/xt_limit.h>
|
||||
|
||||
@@ -162,7 +161,7 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
|
||||
add_cmp_ptr(r, op, iface, iface_len + 1);
|
||||
}
|
||||
|
||||
-void add_addr(struct nftnl_rule *r, int offset,
|
||||
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
|
||||
void *data, void *mask, size_t len, uint32_t op)
|
||||
{
|
||||
const unsigned char *m = mask;
|
||||
@@ -179,7 +178,7 @@ void add_addr(struct nftnl_rule *r, int offset,
|
||||
if (!bitwise)
|
||||
len = i;
|
||||
|
||||
- add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
||||
+ add_payload(r, offset, len, base);
|
||||
|
||||
if (bitwise)
|
||||
add_bitwise(r, mask, len);
|
||||
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
|
||||
index c7f1e366b75ee..520a296fb530c 100644
|
||||
--- a/iptables/nft-shared.h
|
||||
+++ b/iptables/nft-shared.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <libnftnl/chain.h>
|
||||
|
||||
#include <linux/netfilter_arp/arp_tables.h>
|
||||
+#include <linux/netfilter/nf_tables.h>
|
||||
|
||||
#include "xshared.h"
|
||||
|
||||
@@ -124,7 +125,7 @@ void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op);
|
||||
void add_cmp_u32(struct nftnl_rule *r, uint32_t val, uint32_t op);
|
||||
void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op);
|
||||
void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op);
|
||||
-void add_addr(struct nftnl_rule *r, int offset,
|
||||
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
|
||||
void *data, void *mask, size_t len, uint32_t op);
|
||||
void add_proto(struct nftnl_rule *r, int offset, size_t len,
|
||||
uint8_t proto, uint32_t op);
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,366 @@
|
||||
From 6aef90100bebe2b00d4edffe59fb9c43643816de Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue, 10 Nov 2020 14:50:46 +0100
|
||||
Subject: [PATCH] tests/shell: Add test for bitwise avoidance fixes
|
||||
|
||||
Masked address matching was recently improved to avoid bitwise
|
||||
expression if the given mask covers full bytes. Make use of nft netlink
|
||||
debug output to assert iptables-nft generates the right bytecode for
|
||||
each situation.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 81a2e128512837b53e5b9ea501b6c8dc64eeca78)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../nft-only/0009-needless-bitwise_0 | 339 ++++++++++++++++++
|
||||
1 file changed, 339 insertions(+)
|
||||
create mode 100755 iptables/tests/shell/testcases/nft-only/0009-needless-bitwise_0
|
||||
|
||||
diff --git a/iptables/tests/shell/testcases/nft-only/0009-needless-bitwise_0 b/iptables/tests/shell/testcases/nft-only/0009-needless-bitwise_0
|
||||
new file mode 100755
|
||||
index 0000000000000..c5c6e706a1029
|
||||
--- /dev/null
|
||||
+++ b/iptables/tests/shell/testcases/nft-only/0009-needless-bitwise_0
|
||||
@@ -0,0 +1,339 @@
|
||||
+#!/bin/bash -x
|
||||
+
|
||||
+[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
|
||||
+set -e
|
||||
+
|
||||
+nft flush ruleset
|
||||
+
|
||||
+(
|
||||
+ echo "*filter"
|
||||
+ for plen in "" 32 30 24 16 8 0; do
|
||||
+ addr="10.1.2.3${plen:+/}$plen"
|
||||
+ echo "-A OUTPUT -d $addr"
|
||||
+ done
|
||||
+ echo "COMMIT"
|
||||
+) | $XT_MULTI iptables-restore
|
||||
+
|
||||
+(
|
||||
+ echo "*filter"
|
||||
+ for plen in "" 128 124 120 112 88 80 64 48 16 8 0; do
|
||||
+ addr="feed:c0ff:ee00:0102:0304:0506:0708:090A${plen:+/}$plen"
|
||||
+ echo "-A OUTPUT -d $addr"
|
||||
+ done
|
||||
+ echo "COMMIT"
|
||||
+) | $XT_MULTI ip6tables-restore
|
||||
+
|
||||
+masks="
|
||||
+ff:ff:ff:ff:ff:ff
|
||||
+ff:ff:ff:ff:ff:f0
|
||||
+ff:ff:ff:ff:ff:00
|
||||
+ff:ff:ff:ff:00:00
|
||||
+ff:ff:ff:00:00:00
|
||||
+ff:ff:00:00:00:00
|
||||
+ff:00:00:00:00:00
|
||||
+"
|
||||
+(
|
||||
+ echo "*filter"
|
||||
+ for plen in "" 32 30 24 16 8 0; do
|
||||
+ addr="10.1.2.3${plen:+/}$plen"
|
||||
+ echo "-A OUTPUT -d $addr"
|
||||
+ done
|
||||
+ for mask in $masks; do
|
||||
+ echo "-A OUTPUT --destination-mac fe:ed:00:c0:ff:ee/$mask"
|
||||
+ done
|
||||
+ echo "COMMIT"
|
||||
+) | $XT_MULTI arptables-restore
|
||||
+
|
||||
+(
|
||||
+ echo "*filter"
|
||||
+ for mask in $masks; do
|
||||
+ echo "-A OUTPUT -d fe:ed:00:c0:ff:ee/$mask"
|
||||
+ done
|
||||
+ echo "COMMIT"
|
||||
+) | $XT_MULTI ebtables-restore
|
||||
+
|
||||
+EXPECT="ip filter OUTPUT 4
|
||||
+ [ payload load 4b @ network header + 16 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0302010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 5 4
|
||||
+ [ payload load 4b @ network header + 16 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0302010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 6 5
|
||||
+ [ payload load 4b @ network header + 16 => reg 1 ]
|
||||
+ [ bitwise reg 1 = (reg=1 & 0xfcffffff ) ^ 0x00000000 ]
|
||||
+ [ cmp eq reg 1 0x0002010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 7 6
|
||||
+ [ payload load 3b @ network header + 16 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0002010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 8 7
|
||||
+ [ payload load 2b @ network header + 16 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 9 8
|
||||
+ [ payload load 1b @ network header + 16 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip filter OUTPUT 10 9
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 4
|
||||
+ [ payload load 16b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x06050403 0x0a090807 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 5 4
|
||||
+ [ payload load 16b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x06050403 0x0a090807 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 6 5
|
||||
+ [ payload load 16b @ network header + 24 => reg 1 ]
|
||||
+ [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0xffffffff 0xf0ffffff ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x06050403 0x00090807 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 7 6
|
||||
+ [ payload load 15b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x06050403 0x00090807 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 8 7
|
||||
+ [ payload load 14b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x06050403 0x00000807 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 9 8
|
||||
+ [ payload load 11b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x00050403 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 10 9
|
||||
+ [ payload load 10b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee 0x00000403 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 11 10
|
||||
+ [ payload load 8b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x020100ee ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 12 11
|
||||
+ [ payload load 6b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xffc0edfe 0x000000ee ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 13 12
|
||||
+ [ payload load 2b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 14 13
|
||||
+ [ payload load 1b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x000000fe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+ip6 filter OUTPUT 15 14
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 3
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 4b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0302010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 4 3
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 4b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0302010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 5 4
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 4b @ network header + 24 => reg 1 ]
|
||||
+ [ bitwise reg 1 = (reg=1 & 0xfcffffff ) ^ 0x00000000 ]
|
||||
+ [ cmp eq reg 1 0x0002010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 6 5
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 3b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0002010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 7 6
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 2b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000010a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 8 7
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 1b @ network header + 24 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000000a ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 9 8
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 10 9
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 6b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x0000eeff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 11 10
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 6b @ network header + 18 => reg 1 ]
|
||||
+ [ bitwise reg 1 = (reg=1 & 0xffffffff 0x0000f0ff ) ^ 0x00000000 0x00000000 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x0000e0ff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 12 11
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 5b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x000000ff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 13 12
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 4b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 14 13
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 3b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 15 14
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 2b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+arp filter OUTPUT 16 15
|
||||
+ [ payload load 2b @ network header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000100 ]
|
||||
+ [ payload load 1b @ network header + 4 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ payload load 1b @ network header + 5 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000004 ]
|
||||
+ [ payload load 1b @ network header + 18 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x000000fe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 4
|
||||
+ [ payload load 6b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x0000eeff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 5 4
|
||||
+ [ payload load 6b @ link header + 0 => reg 1 ]
|
||||
+ [ bitwise reg 1 = (reg=1 & 0xffffffff 0x0000f0ff ) ^ 0x00000000 0x00000000 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x0000e0ff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 6 5
|
||||
+ [ payload load 5b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe 0x000000ff ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 7 6
|
||||
+ [ payload load 4b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0xc000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 8 7
|
||||
+ [ payload load 3b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 9 8
|
||||
+ [ payload load 2b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x0000edfe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+
|
||||
+bridge filter OUTPUT 10 9
|
||||
+ [ payload load 1b @ link header + 0 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x000000fe ]
|
||||
+ [ counter pkts 0 bytes 0 ]
|
||||
+"
|
||||
+
|
||||
+diff -u -Z <(echo "$EXPECT") <(nft --debug=netlink list ruleset | awk '/^table/{exit} {print}')
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,128 @@
|
||||
From e6eede725bbd395fb8b385aec4d0a32ce99e842c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon, 21 Sep 2020 13:42:06 +0200
|
||||
Subject: [PATCH] libxtables: Make sure extensions register in revision order
|
||||
|
||||
Insert extensions into pending lists in ordered fashion: Group by
|
||||
extension name (and, for matches, family) and order groups by descending
|
||||
revision number.
|
||||
|
||||
This allows to simplify the later full registration considerably. Since
|
||||
that involves kernel compatibility checks, the extra cycles here pay off
|
||||
eventually.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit b3ac87038f4e45141831d9ab485a2f627daba3f1)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
libxtables/xtables.c | 71 +++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 64 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
|
||||
index 777c2b08e9896..13139d7f8ad62 100644
|
||||
--- a/libxtables/xtables.c
|
||||
+++ b/libxtables/xtables.c
|
||||
@@ -902,8 +902,14 @@ static void xtables_check_options(const char *name, const struct option *opt)
|
||||
}
|
||||
}
|
||||
|
||||
+static int xtables_match_prefer(const struct xtables_match *a,
|
||||
+ const struct xtables_match *b);
|
||||
+
|
||||
void xtables_register_match(struct xtables_match *me)
|
||||
{
|
||||
+ struct xtables_match **pos;
|
||||
+ bool seen_myself = false;
|
||||
+
|
||||
if (me->next) {
|
||||
fprintf(stderr, "%s: match \"%s\" already registered\n",
|
||||
xt_params->program_name, me->name);
|
||||
@@ -955,10 +961,34 @@ void xtables_register_match(struct xtables_match *me)
|
||||
if (me->extra_opts != NULL)
|
||||
xtables_check_options(me->name, me->extra_opts);
|
||||
|
||||
-
|
||||
- /* place on linked list of matches pending full registration */
|
||||
- me->next = xtables_pending_matches;
|
||||
- xtables_pending_matches = me;
|
||||
+ /* order into linked list of matches pending full registration */
|
||||
+ for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
|
||||
+ /* group by name and family */
|
||||
+ if (strcmp(me->name, (*pos)->name) ||
|
||||
+ me->family != (*pos)->family) {
|
||||
+ if (seen_myself)
|
||||
+ break; /* end of own group, append to it */
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* found own group */
|
||||
+ seen_myself = true;
|
||||
+ if (xtables_match_prefer(me, *pos) >= 0)
|
||||
+ break; /* put preferred items first in group */
|
||||
+ }
|
||||
+ /* if own group was not found, prepend item */
|
||||
+ if (!*pos && !seen_myself)
|
||||
+ pos = &xtables_pending_matches;
|
||||
+
|
||||
+ me->next = *pos;
|
||||
+ *pos = me;
|
||||
+#ifdef DEBUG
|
||||
+ printf("%s: inserted match %s (family %d, revision %d):\n",
|
||||
+ __func__, me->name, me->family, me->revision);
|
||||
+ for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
|
||||
+ printf("%s:\tmatch %s (family %d, revision %d)\n", __func__,
|
||||
+ (*pos)->name, (*pos)->family, (*pos)->revision);
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1097,6 +1127,9 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n)
|
||||
|
||||
void xtables_register_target(struct xtables_target *me)
|
||||
{
|
||||
+ struct xtables_target **pos;
|
||||
+ bool seen_myself = false;
|
||||
+
|
||||
if (me->next) {
|
||||
fprintf(stderr, "%s: target \"%s\" already registered\n",
|
||||
xt_params->program_name, me->name);
|
||||
@@ -1152,9 +1185,33 @@ void xtables_register_target(struct xtables_target *me)
|
||||
if (me->family != afinfo->family && me->family != AF_UNSPEC)
|
||||
return;
|
||||
|
||||
- /* place on linked list of targets pending full registration */
|
||||
- me->next = xtables_pending_targets;
|
||||
- xtables_pending_targets = me;
|
||||
+ /* order into linked list of targets pending full registration */
|
||||
+ for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
|
||||
+ /* group by name */
|
||||
+ if (!extension_cmp(me->name, (*pos)->name, (*pos)->family)) {
|
||||
+ if (seen_myself)
|
||||
+ break; /* end of own group, append to it */
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* found own group */
|
||||
+ seen_myself = true;
|
||||
+ if (xtables_target_prefer(me, *pos) >= 0)
|
||||
+ break; /* put preferred items first in group */
|
||||
+ }
|
||||
+ /* if own group was not found, prepend item */
|
||||
+ if (!*pos && !seen_myself)
|
||||
+ pos = &xtables_pending_targets;
|
||||
+
|
||||
+ me->next = *pos;
|
||||
+ *pos = me;
|
||||
+#ifdef DEBUG
|
||||
+ printf("%s: inserted target %s (family %d, revision %d):\n",
|
||||
+ __func__, me->name, me->family, me->revision);
|
||||
+ for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
|
||||
+ printf("%s:\ttarget %s (family %d, revision %d)\n", __func__,
|
||||
+ (*pos)->name, (*pos)->family, (*pos)->revision);
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
static bool xtables_fully_register_pending_target(struct xtables_target *me)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,241 @@
|
||||
From 1a842fb1cfb3b36f3081aee37c5fdd4a897d77d5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 18 Sep 2020 18:48:14 +0200
|
||||
Subject: [PATCH] libxtables: Simplify pending extension registration
|
||||
|
||||
Assuming that pending extensions are sorted by first name and family,
|
||||
then descending revision, the decision where to insert a newly
|
||||
registered extension may be simplified by memorizing the previous
|
||||
registration (which obviously is of same name and family and higher
|
||||
revision).
|
||||
|
||||
As a side-effect, fix for unsupported old extension revisions lingering
|
||||
in pending extension list forever and being retried with every use of
|
||||
the given extension. Any revision being rejected by the kernel may
|
||||
safely be dropped iff a previous (read: higher) revision was accepted
|
||||
already.
|
||||
|
||||
Yet another side-effect of this change is the removal of an unwanted
|
||||
recursion by xtables_fully_register_pending_*() into itself via
|
||||
xtables_find_*().
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit a1eaaceb0460b338294e40bdd5bc5186320a478c)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
libxtables/xtables.c | 128 +++++++++++--------------------------------
|
||||
1 file changed, 33 insertions(+), 95 deletions(-)
|
||||
|
||||
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
|
||||
index 13139d7f8ad62..409128333e0e6 100644
|
||||
--- a/libxtables/xtables.c
|
||||
+++ b/libxtables/xtables.c
|
||||
@@ -203,8 +203,10 @@ struct xtables_match *xtables_matches;
|
||||
struct xtables_target *xtables_targets;
|
||||
|
||||
/* Fully register a match/target which was previously partially registered. */
|
||||
-static bool xtables_fully_register_pending_match(struct xtables_match *me);
|
||||
-static bool xtables_fully_register_pending_target(struct xtables_target *me);
|
||||
+static bool xtables_fully_register_pending_match(struct xtables_match *me,
|
||||
+ struct xtables_match *prev);
|
||||
+static bool xtables_fully_register_pending_target(struct xtables_target *me,
|
||||
+ struct xtables_target *prev);
|
||||
|
||||
void xtables_init(void)
|
||||
{
|
||||
@@ -616,6 +618,7 @@ struct xtables_match *
|
||||
xtables_find_match(const char *name, enum xtables_tryload tryload,
|
||||
struct xtables_rule_match **matches)
|
||||
{
|
||||
+ struct xtables_match *prev = NULL;
|
||||
struct xtables_match **dptr;
|
||||
struct xtables_match *ptr;
|
||||
const char *icmp6 = "icmp6";
|
||||
@@ -637,8 +640,12 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
|
||||
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
|
||||
ptr = *dptr;
|
||||
*dptr = (*dptr)->next;
|
||||
- if (xtables_fully_register_pending_match(ptr))
|
||||
+ if (xtables_fully_register_pending_match(ptr, prev)) {
|
||||
+ prev = ptr;
|
||||
continue;
|
||||
+ } else if (prev) {
|
||||
+ continue;
|
||||
+ }
|
||||
*dptr = ptr;
|
||||
}
|
||||
dptr = &((*dptr)->next);
|
||||
@@ -732,6 +739,7 @@ xtables_find_match_revision(const char *name, enum xtables_tryload tryload,
|
||||
struct xtables_target *
|
||||
xtables_find_target(const char *name, enum xtables_tryload tryload)
|
||||
{
|
||||
+ struct xtables_target *prev = NULL;
|
||||
struct xtables_target **dptr;
|
||||
struct xtables_target *ptr;
|
||||
|
||||
@@ -748,8 +756,12 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
|
||||
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
|
||||
ptr = *dptr;
|
||||
*dptr = (*dptr)->next;
|
||||
- if (xtables_fully_register_pending_target(ptr))
|
||||
+ if (xtables_fully_register_pending_target(ptr, prev)) {
|
||||
+ prev = ptr;
|
||||
continue;
|
||||
+ } else if (prev) {
|
||||
+ continue;
|
||||
+ }
|
||||
*dptr = ptr;
|
||||
}
|
||||
dptr = &((*dptr)->next);
|
||||
@@ -1052,64 +1064,27 @@ static int xtables_target_prefer(const struct xtables_target *a,
|
||||
b->revision, b->family);
|
||||
}
|
||||
|
||||
-static bool xtables_fully_register_pending_match(struct xtables_match *me)
|
||||
+static bool xtables_fully_register_pending_match(struct xtables_match *me,
|
||||
+ struct xtables_match *prev)
|
||||
{
|
||||
- struct xtables_match **i, *old, *pos = NULL;
|
||||
+ struct xtables_match **i;
|
||||
const char *rn;
|
||||
- int compare;
|
||||
|
||||
/* See if new match can be used. */
|
||||
rn = (me->real_name != NULL) ? me->real_name : me->name;
|
||||
if (!compatible_match_revision(rn, me->revision))
|
||||
return false;
|
||||
|
||||
- old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
|
||||
- while (old) {
|
||||
- compare = xtables_match_prefer(old, me);
|
||||
- if (compare == 0) {
|
||||
- fprintf(stderr,
|
||||
- "%s: match `%s' already registered.\n",
|
||||
- xt_params->program_name, me->name);
|
||||
- exit(1);
|
||||
- }
|
||||
-
|
||||
- /* Now we have two (or more) options, check compatibility. */
|
||||
- rn = (old->real_name != NULL) ? old->real_name : old->name;
|
||||
- if (compare > 0) {
|
||||
- /* Kernel tells old isn't compatible anymore??? */
|
||||
- if (!compatible_match_revision(rn, old->revision)) {
|
||||
- /* Delete old one. */
|
||||
- for (i = &xtables_matches; *i != old;)
|
||||
- i = &(*i)->next;
|
||||
- *i = old->next;
|
||||
- }
|
||||
- pos = old;
|
||||
- old = old->next;
|
||||
- if (!old)
|
||||
- break;
|
||||
- if (!extension_cmp(me->name, old->name, old->family))
|
||||
- break;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* Found right old */
|
||||
- pos = old;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (!pos) {
|
||||
+ if (!prev) {
|
||||
/* Append to list. */
|
||||
for (i = &xtables_matches; *i; i = &(*i)->next);
|
||||
- } else if (compare < 0) {
|
||||
- /* Prepend it */
|
||||
- for (i = &xtables_matches; *i != pos; i = &(*i)->next);
|
||||
- } else if (compare > 0) {
|
||||
+ } else {
|
||||
/* Append it */
|
||||
- i = &pos->next;
|
||||
- pos = pos->next;
|
||||
+ i = &prev->next;
|
||||
+ prev = prev->next;
|
||||
}
|
||||
|
||||
- me->next = pos;
|
||||
+ me->next = prev;
|
||||
*i = me;
|
||||
|
||||
me->m = NULL;
|
||||
@@ -1214,11 +1189,11 @@ void xtables_register_target(struct xtables_target *me)
|
||||
#endif
|
||||
}
|
||||
|
||||
-static bool xtables_fully_register_pending_target(struct xtables_target *me)
|
||||
+static bool xtables_fully_register_pending_target(struct xtables_target *me,
|
||||
+ struct xtables_target *prev)
|
||||
{
|
||||
- struct xtables_target **i, *old, *pos = NULL;
|
||||
+ struct xtables_target **i;
|
||||
const char *rn;
|
||||
- int compare;
|
||||
|
||||
if (strcmp(me->name, "standard") != 0) {
|
||||
/* See if new target can be used. */
|
||||
@@ -1227,54 +1202,17 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me)
|
||||
return false;
|
||||
}
|
||||
|
||||
- old = xtables_find_target(me->name, XTF_DURING_LOAD);
|
||||
- while (old) {
|
||||
- compare = xtables_target_prefer(old, me);
|
||||
- if (compare == 0) {
|
||||
- fprintf(stderr,
|
||||
- "%s: target `%s' already registered.\n",
|
||||
- xt_params->program_name, me->name);
|
||||
- exit(1);
|
||||
- }
|
||||
-
|
||||
- /* Now we have two (or more) options, check compatibility. */
|
||||
- rn = (old->real_name != NULL) ? old->real_name : old->name;
|
||||
- if (compare > 0) {
|
||||
- /* Kernel tells old isn't compatible anymore??? */
|
||||
- if (!compatible_target_revision(rn, old->revision)) {
|
||||
- /* Delete old one. */
|
||||
- for (i = &xtables_targets; *i != old;)
|
||||
- i = &(*i)->next;
|
||||
- *i = old->next;
|
||||
- }
|
||||
- pos = old;
|
||||
- old = old->next;
|
||||
- if (!old)
|
||||
- break;
|
||||
- if (!extension_cmp(me->name, old->name, old->family))
|
||||
- break;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* Found right old */
|
||||
- pos = old;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (!pos) {
|
||||
+ if (!prev) {
|
||||
/* Prepend to list. */
|
||||
i = &xtables_targets;
|
||||
- pos = xtables_targets;
|
||||
- } else if (compare < 0) {
|
||||
- /* Prepend it */
|
||||
- for (i = &xtables_targets; *i != pos; i = &(*i)->next);
|
||||
- } else if (compare > 0) {
|
||||
+ prev = xtables_targets;
|
||||
+ } else {
|
||||
/* Append it */
|
||||
- i = &pos->next;
|
||||
- pos = pos->next;
|
||||
+ i = &prev->next;
|
||||
+ prev = prev->next;
|
||||
}
|
||||
|
||||
- me->next = pos;
|
||||
+ me->next = prev;
|
||||
*i = me;
|
||||
|
||||
me->t = NULL;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,52 @@
|
||||
From cfcafd3638cdc06a8b4a1d267e58b5ad1e35922c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue, 22 Sep 2020 20:01:15 +0200
|
||||
Subject: [PATCH] libxtables: Register multiple extensions in ascending order
|
||||
|
||||
The newly introduced ordered insert algorithm in
|
||||
xtables_register_{match,target}() works best if extensions of same name
|
||||
are passed in ascending revisions. Since this is the case in about all
|
||||
extensions' arrays, iterate over them from beginning to end.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit b5f1a3beac1d1f2b96c8be8ebec450f5ea758090)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
libxtables/xtables.c | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
|
||||
index 409128333e0e6..28ffffedd8147 100644
|
||||
--- a/libxtables/xtables.c
|
||||
+++ b/libxtables/xtables.c
|
||||
@@ -1095,9 +1095,10 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me,
|
||||
|
||||
void xtables_register_matches(struct xtables_match *match, unsigned int n)
|
||||
{
|
||||
- do {
|
||||
- xtables_register_match(&match[--n]);
|
||||
- } while (n > 0);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ xtables_register_match(&match[i]);
|
||||
}
|
||||
|
||||
void xtables_register_target(struct xtables_target *me)
|
||||
@@ -1223,9 +1224,10 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me,
|
||||
|
||||
void xtables_register_targets(struct xtables_target *target, unsigned int n)
|
||||
{
|
||||
- do {
|
||||
- xtables_register_target(&target[--n]);
|
||||
- } while (n > 0);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ xtables_register_target(&target[i]);
|
||||
}
|
||||
|
||||
/* receives a list of xtables_rule_match, release them */
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,53 @@
|
||||
From f5185f4efad409fc7ec4ae05267b642ee4103a6c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 4 Dec 2020 17:44:51 +0100
|
||||
Subject: [PATCH] tests/shell: Test for fixed extension registration
|
||||
|
||||
Use strace to look at iptables-restore behaviour with typically
|
||||
problematic input (conntrack revision 0 is no longer supported by
|
||||
current kernels) to make sure the fix in commit a1eaaceb0460b
|
||||
("libxtables: Simplify pending extension registration") is still
|
||||
effective.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 93d0c97e8b6713f51ba679e01a1338d4f9076e7c)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../0017-pointless-compat-checks_0 | 25 +++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
create mode 100755 iptables/tests/shell/testcases/ipt-restore/0017-pointless-compat-checks_0
|
||||
|
||||
diff --git a/iptables/tests/shell/testcases/ipt-restore/0017-pointless-compat-checks_0 b/iptables/tests/shell/testcases/ipt-restore/0017-pointless-compat-checks_0
|
||||
new file mode 100755
|
||||
index 0000000000000..cf73de32df409
|
||||
--- /dev/null
|
||||
+++ b/iptables/tests/shell/testcases/ipt-restore/0017-pointless-compat-checks_0
|
||||
@@ -0,0 +1,25 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# A bug in extension registration would leave unsupported older extension
|
||||
+# revisions in pending list and get compatibility checked again for each rule
|
||||
+# using them. With SELinux enabled, the resulting socket() call per rule leads
|
||||
+# to significant slowdown (~50% performance in worst cases).
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+strace --version >/dev/null || { echo "skip for missing strace"; exit 0; }
|
||||
+
|
||||
+RULESET="$(
|
||||
+ echo "*filter"
|
||||
+ for ((i = 0; i < 100; i++)); do
|
||||
+ echo "-A FORWARD -m conntrack --ctstate NEW"
|
||||
+ done
|
||||
+ echo "COMMIT"
|
||||
+)"
|
||||
+
|
||||
+cmd="$XT_MULTI iptables-restore"
|
||||
+socketcount=$(strace -esocket $cmd <<< "$RULESET" 2>&1 | wc -l)
|
||||
+
|
||||
+# unpatched iptables-restore would open 111 sockets,
|
||||
+# patched only 12 but keep a certain margin for future changes
|
||||
+[[ $socketcount -lt 20 ]]
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 6adcdca2aaf8cba6ee452c88f41ad8695bebdcfc Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue, 6 Oct 2020 19:07:19 +0200
|
||||
Subject: [PATCH] extensions: libipt_icmp: Fix translation of type 'any'
|
||||
|
||||
By itself, '-m icmp --icmp-type any' is a noop, it matches any icmp
|
||||
types. Yet nft_ipv4_xlate() does not emit an 'ip protocol' match if
|
||||
there's an extension with same name present in the rule. Luckily, legacy
|
||||
iptables demands icmp match to be prepended by '-p icmp', so we can
|
||||
assume this is present and just emit the 'ip protocol' match from icmp
|
||||
xlate callback.
|
||||
|
||||
Fixes: aa158ca0fda65 ("extensions: libipt_icmp: Add translation to nft")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
(cherry picked from commit ad4b17b98bbedf93d2182a4dc9a37e9cf3adfe1b)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
extensions/libipt_icmp.c | 5 +++++
|
||||
extensions/libipt_icmp.txlate | 3 +++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
|
||||
index e76257c54708c..e5e236613f39f 100644
|
||||
--- a/extensions/libipt_icmp.c
|
||||
+++ b/extensions/libipt_icmp.c
|
||||
@@ -256,6 +256,11 @@ static int icmp_xlate(struct xt_xlate *xl,
|
||||
if (!type_xlate_print(xl, info->type, info->code[0],
|
||||
info->code[1]))
|
||||
return 0;
|
||||
+ } else {
|
||||
+ /* '-m icmp --icmp-type any' is a noop by itself,
|
||||
+ * but it eats a (mandatory) previous '-p icmp' so
|
||||
+ * emit it here */
|
||||
+ xt_xlate_add(xl, "ip protocol icmp");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
diff --git a/extensions/libipt_icmp.txlate b/extensions/libipt_icmp.txlate
|
||||
index 434f8cc4eb1ae..a2aec8e26df75 100644
|
||||
--- a/extensions/libipt_icmp.txlate
|
||||
+++ b/extensions/libipt_icmp.txlate
|
||||
@@ -6,3 +6,6 @@ nft add rule ip filter INPUT icmp type destination-unreachable counter accept
|
||||
|
||||
iptables-translate -t filter -A INPUT -m icmp ! --icmp-type 3 -j ACCEPT
|
||||
nft add rule ip filter INPUT icmp type != destination-unreachable counter accept
|
||||
+
|
||||
+iptables-translate -t filter -A INPUT -m icmp --icmp-type any -j ACCEPT
|
||||
+nft add rule ip filter INPUT ip protocol icmp counter accept
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 1695f552d3947299e54978bcd5bc1cdc3a5c14f7 Mon Sep 17 00:00:00 2001
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Wed, 15 Apr 2020 18:16:41 +0200
|
||||
Subject: [PATCH] extensions: libxt_CT: add translation for NOTRACK
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
(cherry picked from commit f3d4a3ddbcfca15a00dd9758f481420038f6de10)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
extensions/libxt_CT.c | 16 ++++++++++++++++
|
||||
extensions/libxt_NOTRACK.txlate | 2 ++
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100644 extensions/libxt_NOTRACK.txlate
|
||||
|
||||
diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c
|
||||
index 371b21766c56c..fbbbe2660e9fc 100644
|
||||
--- a/extensions/libxt_CT.c
|
||||
+++ b/extensions/libxt_CT.c
|
||||
@@ -348,6 +348,20 @@ static void notrack_ct2_tg_init(struct xt_entry_target *target)
|
||||
info->flags = XT_CT_NOTRACK | XT_CT_NOTRACK_ALIAS;
|
||||
}
|
||||
|
||||
+static int xlate_ct1_tg(struct xt_xlate *xl,
|
||||
+ const struct xt_xlate_tg_params *params)
|
||||
+{
|
||||
+ struct xt_ct_target_info_v1 *info =
|
||||
+ (struct xt_ct_target_info_v1 *)params->target->data;
|
||||
+
|
||||
+ if (info->flags & XT_CT_NOTRACK)
|
||||
+ xt_xlate_add(xl, "notrack");
|
||||
+ else
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static struct xtables_target ct_target_reg[] = {
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
@@ -387,6 +401,7 @@ static struct xtables_target ct_target_reg[] = {
|
||||
.alias = ct_print_name_alias,
|
||||
.x6_parse = ct_parse_v1,
|
||||
.x6_options = ct_opts_v1,
|
||||
+ .xlate = xlate_ct1_tg,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
@@ -418,6 +433,7 @@ static struct xtables_target ct_target_reg[] = {
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
|
||||
.init = notrack_ct2_tg_init,
|
||||
+ .xlate = xlate_ct1_tg,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
diff --git a/extensions/libxt_NOTRACK.txlate b/extensions/libxt_NOTRACK.txlate
|
||||
new file mode 100644
|
||||
index 0000000000000..9d35619d3dbdd
|
||||
--- /dev/null
|
||||
+++ b/extensions/libxt_NOTRACK.txlate
|
||||
@@ -0,0 +1,2 @@
|
||||
+iptables-translate -A PREROUTING -t raw -j NOTRACK
|
||||
+nft add rule ip raw PREROUTING counter notrack
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 6d8a390bd13bac294ff9de225a49fe9e4de2d6e5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 7 Aug 2020 13:48:28 +0200
|
||||
Subject: [PATCH] nft: Fix command name in ip6tables error message
|
||||
|
||||
Upon errors, ip6tables-nft would prefix its error messages with
|
||||
'iptables:' instead of 'ip6tables:'. Turns out the command name was
|
||||
hard-coded, use 'progname' variable instead.
|
||||
While being at it, merge the two mostly identical fprintf() calls into
|
||||
one.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
(cherry picked from commit 3be40dcfb5af1438b6abdbda45a1e3b59c104e13)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
iptables/xtables-standalone.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/iptables/xtables-standalone.c b/iptables/xtables-standalone.c
|
||||
index 022d5dd44abbf..b5b7ccaf4e660 100644
|
||||
--- a/iptables/xtables-standalone.c
|
||||
+++ b/iptables/xtables-standalone.c
|
||||
@@ -74,14 +74,10 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
|
||||
nft_fini(&h);
|
||||
|
||||
if (!ret) {
|
||||
- if (errno == EINVAL) {
|
||||
- fprintf(stderr, "iptables: %s. "
|
||||
- "Run `dmesg' for more information.\n",
|
||||
- nft_strerror(errno));
|
||||
- } else {
|
||||
- fprintf(stderr, "iptables: %s.\n",
|
||||
- nft_strerror(errno));
|
||||
- }
|
||||
+ fprintf(stderr, "%s: %s.%s\n", progname, nft_strerror(errno),
|
||||
+ (errno == EINVAL ?
|
||||
+ " Run `dmesg' for more information." : ""));
|
||||
+
|
||||
if (errno == EAGAIN)
|
||||
exit(RESOURCE_PROBLEM);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,206 @@
|
||||
From c5f07a7d718f812f916686926567adbac6c1b125 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu, 6 Aug 2020 18:52:34 +0200
|
||||
Subject: [PATCH] tests: shell: Merge and extend return codes test
|
||||
|
||||
Merge scripts for iptables and ip6tables, they were widely identical.
|
||||
Also extend the test by one check (removing a non-existent rule with
|
||||
valid chain and target) and quote the error messages where differences
|
||||
are deliberately ignored.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
(cherry picked from commit cd3e83d1b04fd2683f0fb06e496ee5be08a96b4f)
|
||||
|
||||
Conflicts:
|
||||
iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
|
||||
iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
-> Missing upstream commit a7f1e208cdf9c ("nft: split parsing from
|
||||
netlink commands") which added a few tests to both files.
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
.../testcases/ip6tables/0004-return-codes_0 | 38 -------
|
||||
.../testcases/iptables/0004-return-codes_0 | 104 ++++++++++--------
|
||||
2 files changed, 58 insertions(+), 84 deletions(-)
|
||||
delete mode 100755 iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
|
||||
|
||||
diff --git a/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0 b/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
|
||||
deleted file mode 100755
|
||||
index f023b7915498e..0000000000000
|
||||
--- a/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
|
||||
+++ /dev/null
|
||||
@@ -1,38 +0,0 @@
|
||||
-#!/bin/sh
|
||||
-
|
||||
-# make sure error return codes are as expected useful cases
|
||||
-# (e.g. commands to check ruleset state)
|
||||
-
|
||||
-global_rc=0
|
||||
-
|
||||
-cmd() { # (rc, cmd, [args ...])
|
||||
- rc_exp=$1; shift
|
||||
-
|
||||
- $XT_MULTI "$@"
|
||||
- rc=$?
|
||||
-
|
||||
- [ $rc -eq $rc_exp ] || {
|
||||
- echo "---> expected $rc_exp, got $rc for command '$@'"
|
||||
- global_rc=1
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-# test chain creation
|
||||
-cmd 0 ip6tables -N foo
|
||||
-cmd 1 ip6tables -N foo
|
||||
-# iptables-nft allows this - bug or feature?
|
||||
-#cmd 2 ip6tables -N "invalid name"
|
||||
-
|
||||
-# test rule adding
|
||||
-cmd 0 ip6tables -A INPUT -j ACCEPT
|
||||
-cmd 1 ip6tables -A noexist -j ACCEPT
|
||||
-
|
||||
-# test rule checking
|
||||
-cmd 0 ip6tables -C INPUT -j ACCEPT
|
||||
-cmd 1 ip6tables -C FORWARD -j ACCEPT
|
||||
-cmd 1 ip6tables -C nonexist -j ACCEPT
|
||||
-cmd 2 ip6tables -C INPUT -j foobar
|
||||
-cmd 2 ip6tables -C INPUT -m foobar -j ACCEPT
|
||||
-cmd 3 ip6tables -t foobar -C INPUT -j ACCEPT
|
||||
-
|
||||
-exit $global_rc
|
||||
diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
index ce02e0bcb128b..67f1698945753 100755
|
||||
--- a/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
+++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
@@ -13,69 +13,81 @@ cmd() { # (rc, msg, cmd, [args ...])
|
||||
msg_exp="$1"; shift
|
||||
}
|
||||
|
||||
- msg="$($XT_MULTI "$@" 2>&1 >/dev/null)"
|
||||
- rc=$?
|
||||
+ for ipt in iptables ip6tables; do
|
||||
+ msg="$($XT_MULTI $ipt "$@" 2>&1 >/dev/null)"
|
||||
+ rc=$?
|
||||
|
||||
- [ $rc -eq $rc_exp ] || {
|
||||
- echo "---> expected return code $rc_exp, got $rc for command '$@'"
|
||||
- global_rc=1
|
||||
- }
|
||||
+ [ $rc -eq $rc_exp ] || {
|
||||
+ echo "---> expected return code $rc_exp, got $rc for command '$ipt $@'"
|
||||
+ global_rc=1
|
||||
+ }
|
||||
|
||||
- [ -n "$msg_exp" ] || return
|
||||
- grep -q "$msg_exp" <<< $msg || {
|
||||
- echo "---> expected error message '$msg_exp', got '$msg' for command '$@'"
|
||||
- global_rc=1
|
||||
- }
|
||||
+ [ -n "$msg_exp" ] || continue
|
||||
+ msg_exp_full="${ipt}$msg_exp"
|
||||
+ grep -q "$msg_exp_full" <<< $msg || {
|
||||
+ echo "---> expected error message '$msg_exp_full', got '$msg' for command '$ipt $@'"
|
||||
+ global_rc=1
|
||||
+ }
|
||||
+ done
|
||||
}
|
||||
|
||||
-EEXIST_F="File exists."
|
||||
-EEXIST="Chain already exists."
|
||||
-ENOENT="No chain/target/match by that name."
|
||||
-E2BIG_I="Index of insertion too big."
|
||||
-E2BIG_D="Index of deletion too big."
|
||||
-E2BIG_R="Index of replacement too big."
|
||||
-EBADRULE="Bad rule (does a matching rule exist in that chain?)."
|
||||
-ENOTGT="Couldn't load target \`foobar':No such file or directory"
|
||||
-ENOMTH="Couldn't load match \`foobar':No such file or directory"
|
||||
-ENOTBL="can't initialize iptables table \`foobar': Table does not exist"
|
||||
+EEXIST_F=": File exists."
|
||||
+EEXIST=": Chain already exists."
|
||||
+ENOENT=": No chain/target/match by that name."
|
||||
+E2BIG_I=": Index of insertion too big."
|
||||
+E2BIG_D=": Index of deletion too big."
|
||||
+E2BIG_R=": Index of replacement too big."
|
||||
+EBADRULE=": Bad rule (does a matching rule exist in that chain?)."
|
||||
+#ENOTGT=" v[0-9\.]* [^ ]*: Couldn't load target \`foobar':No such file or directory"
|
||||
+ENOMTH=" v[0-9\.]* [^ ]*: Couldn't load match \`foobar':No such file or directory"
|
||||
+ENOTBL=": can't initialize iptables table \`foobar': Table does not exist"
|
||||
|
||||
# test chain creation
|
||||
-cmd 0 iptables -N foo
|
||||
-cmd 1 "$EEXIST" iptables -N foo
|
||||
+cmd 0 -N foo
|
||||
+cmd 1 "$EEXIST" -N foo
|
||||
# iptables-nft allows this - bug or feature?
|
||||
-#cmd 2 iptables -N "invalid name"
|
||||
+#cmd 2 -N "invalid name"
|
||||
|
||||
# test chain flushing/zeroing
|
||||
-cmd 0 iptables -F foo
|
||||
-cmd 0 iptables -Z foo
|
||||
-cmd 1 "$ENOENT" iptables -F bar
|
||||
-cmd 1 "$ENOENT" iptables -Z bar
|
||||
+cmd 0 -F foo
|
||||
+cmd 0 -Z foo
|
||||
+cmd 1 "$ENOENT" -F bar
|
||||
+cmd 1 "$ENOENT" -Z bar
|
||||
|
||||
# test chain rename
|
||||
-cmd 0 iptables -E foo bar
|
||||
-cmd 1 "$EEXIST_F" iptables -E foo bar
|
||||
+cmd 0 -E foo bar
|
||||
+cmd 1 "$EEXIST_F" -E foo bar
|
||||
|
||||
# test rule adding
|
||||
-cmd 0 iptables -A INPUT -j ACCEPT
|
||||
-cmd 1 "$ENOENT" iptables -A noexist -j ACCEPT
|
||||
+cmd 0 -A INPUT -j ACCEPT
|
||||
+cmd 1 "$ENOENT" -A noexist -j ACCEPT
|
||||
+# next three differ:
|
||||
+# legacy: Couldn't load target `foobar':No such file or directory
|
||||
+# nft: Chain 'foobar' does not exist
|
||||
+cmd 2 "" -I INPUT -j foobar
|
||||
+cmd 2 "" -R INPUT 1 -j foobar
|
||||
+cmd 2 "" -D INPUT -j foobar
|
||||
+cmd 1 "$EBADRULE" -D INPUT -p tcp --dport 22 -j ACCEPT
|
||||
|
||||
# test rulenum commands
|
||||
-cmd 1 "$E2BIG_I" iptables -I INPUT 23 -j ACCEPT
|
||||
-cmd 1 "$E2BIG_D" iptables -D INPUT 23
|
||||
-cmd 1 "$E2BIG_R" iptables -R INPUT 23 -j ACCEPT
|
||||
-cmd 1 "$ENOENT" iptables -I nonexist 23 -j ACCEPT
|
||||
-cmd 1 "$ENOENT" iptables -D nonexist 23
|
||||
-cmd 1 "$ENOENT" iptables -R nonexist 23 -j ACCEPT
|
||||
+cmd 1 "$E2BIG_I" -I INPUT 23 -j ACCEPT
|
||||
+cmd 1 "$E2BIG_D" -D INPUT 23
|
||||
+cmd 1 "$E2BIG_R" -R INPUT 23 -j ACCEPT
|
||||
+cmd 1 "$ENOENT" -I nonexist 23 -j ACCEPT
|
||||
+cmd 1 "$ENOENT" -D nonexist 23
|
||||
+cmd 1 "$ENOENT" -R nonexist 23 -j ACCEPT
|
||||
|
||||
# test rule checking
|
||||
-cmd 0 iptables -C INPUT -j ACCEPT
|
||||
-cmd 1 "$EBADRULE" iptables -C FORWARD -j ACCEPT
|
||||
-cmd 1 "$BADRULE" iptables -C nonexist -j ACCEPT
|
||||
-cmd 2 "$ENOMTH" iptables -C INPUT -m foobar -j ACCEPT
|
||||
+cmd 0 -C INPUT -j ACCEPT
|
||||
+cmd 1 "$EBADRULE" -C FORWARD -j ACCEPT
|
||||
+cmd 1 "$BADRULE" -C nonexist -j ACCEPT
|
||||
+cmd 2 "$ENOMTH" -C INPUT -m foobar -j ACCEPT
|
||||
# messages of those don't match, but iptables-nft ones are actually nicer.
|
||||
-#cmd 2 "$ENOTGT" iptables -C INPUT -j foobar
|
||||
-#cmd 3 "$ENOTBL" iptables -t foobar -C INPUT -j ACCEPT
|
||||
-cmd 2 "" iptables -C INPUT -j foobar
|
||||
-cmd 3 "" iptables -t foobar -C INPUT -j ACCEPT
|
||||
+# legacy: Couldn't load target `foobar':No such file or directory
|
||||
+# nft: Chain 'foobar' does not exist
|
||||
+cmd 2 "" -C INPUT -j foobar
|
||||
+# legacy: can't initialize ip6tables table `foobar': Table does not exist (do you need to insmod?)
|
||||
+# nft: table 'foobar' does not exist
|
||||
+cmd 3 "" -t foobar -C INPUT -j ACCEPT
|
||||
|
||||
exit $global_rc
|
||||
--
|
||||
2.28.0
|
||||
|
177
SOURCES/0043-extensions-dccp-Fix-for-DCCP-type-INVALID.patch
Normal file
177
SOURCES/0043-extensions-dccp-Fix-for-DCCP-type-INVALID.patch
Normal file
@ -0,0 +1,177 @@
|
||||
From 98794894774a39927bc975921fc9e40f00db937b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed, 2 Dec 2020 13:37:06 +0100
|
||||
Subject: [PATCH] extensions: dccp: Fix for DCCP type 'INVALID'
|
||||
|
||||
Support for matching on invalid DCCP type field values was pretty
|
||||
broken: While RFC4340 declares any type value from 10 to 15 invalid, the
|
||||
extension's type name 'INVALID' mapped to type value 10 only. Fix this
|
||||
by introduction of INVALID_OTHER_TYPE_MASK which has the remaining
|
||||
invalid type's bits set and apply it if bit 10 is set after parsing the
|
||||
type list. When printing, stop searching type names after printing
|
||||
'INVALID' - unless numeric output was requested. The latter prints all
|
||||
actual type values. Since parsing types in numeric form is not
|
||||
supported, changing the output should not break existing scripts.
|
||||
|
||||
When translating into nftables syntax, the code returned prematurely if
|
||||
'INVALID' was among the list of types - thereby emitting invalid syntax.
|
||||
Instead print a real match for invalid types by use of a range
|
||||
expression.
|
||||
|
||||
While being at it, fix syntax of translator output: If only
|
||||
'--dccp-types' was translated, the output contained an extra 'dccp'. On
|
||||
the other hand, if '--sport' and '--dport' was present, a required
|
||||
'dccp' between the translations of both was missing.
|
||||
|
||||
Fixes: e40b11d7ef827 ("add support for new 'dccp' protocol match")
|
||||
Fixes: c94a998724143 ("extensions: libxt_dccp: Add translation to nft")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
(cherry picked from commit 4bcbc8e11a2764f4537dc405962f83cd072cccfe)
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
extensions/libxt_dccp.c | 58 ++++++++++++++++++++++--------------
|
||||
extensions/libxt_dccp.txlate | 12 ++++++--
|
||||
2 files changed, 45 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c
|
||||
index 5e67c264db2a9..aea3e20be4818 100644
|
||||
--- a/extensions/libxt_dccp.c
|
||||
+++ b/extensions/libxt_dccp.c
|
||||
@@ -76,6 +76,9 @@ static const char *const dccp_pkt_types[] = {
|
||||
[DCCP_PKT_INVALID] = "INVALID",
|
||||
};
|
||||
|
||||
+/* Bits for type values 11-15 */
|
||||
+#define INVALID_OTHER_TYPE_MASK 0xf800
|
||||
+
|
||||
static uint16_t
|
||||
parse_dccp_types(const char *typestring)
|
||||
{
|
||||
@@ -95,6 +98,9 @@ parse_dccp_types(const char *typestring)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unknown DCCP type `%s'", ptr);
|
||||
}
|
||||
+ if (typemask & (1 << DCCP_PKT_INVALID))
|
||||
+ typemask |= INVALID_OTHER_TYPE_MASK;
|
||||
+
|
||||
|
||||
free(buffer);
|
||||
return typemask;
|
||||
@@ -193,9 +199,13 @@ print_types(uint16_t types, int inverted, int numeric)
|
||||
|
||||
if (numeric)
|
||||
printf("%u", i);
|
||||
- else
|
||||
+ else {
|
||||
printf("%s", dccp_pkt_types[i]);
|
||||
|
||||
+ if (i == DCCP_PKT_INVALID)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
types &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
@@ -288,6 +298,7 @@ static const char *const dccp_pkt_types_xlate[] = {
|
||||
[DCCP_PKT_RESET] = "reset",
|
||||
[DCCP_PKT_SYNC] = "sync",
|
||||
[DCCP_PKT_SYNCACK] = "syncack",
|
||||
+ [DCCP_PKT_INVALID] = "10-15",
|
||||
};
|
||||
|
||||
static int dccp_type_xlate(const struct xt_dccp_info *einfo,
|
||||
@@ -296,10 +307,10 @@ static int dccp_type_xlate(const struct xt_dccp_info *einfo,
|
||||
bool have_type = false, set_need = false;
|
||||
uint16_t types = einfo->typemask;
|
||||
|
||||
- if (types & (1 << DCCP_PKT_INVALID))
|
||||
- return 0;
|
||||
-
|
||||
- xt_xlate_add(xl, " dccp type%s ", einfo->invflags ? " !=" : "");
|
||||
+ if (types & INVALID_OTHER_TYPE_MASK) {
|
||||
+ types &= ~INVALID_OTHER_TYPE_MASK;
|
||||
+ types |= 1 << DCCP_PKT_INVALID;
|
||||
+ }
|
||||
|
||||
if ((types != 0) && !(types == (types & -types))) {
|
||||
xt_xlate_add(xl, "{");
|
||||
@@ -335,34 +346,37 @@ static int dccp_xlate(struct xt_xlate *xl,
|
||||
char *space = "";
|
||||
int ret = 1;
|
||||
|
||||
- xt_xlate_add(xl, "dccp ");
|
||||
-
|
||||
if (einfo->flags & XT_DCCP_SRC_PORTS) {
|
||||
+ xt_xlate_add(xl, "dccp sport%s %u",
|
||||
+ einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
|
||||
+ einfo->spts[0]);
|
||||
+
|
||||
if (einfo->spts[0] != einfo->spts[1])
|
||||
- xt_xlate_add(xl, "sport%s %u-%u",
|
||||
- einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
|
||||
- einfo->spts[0], einfo->spts[1]);
|
||||
- else
|
||||
- xt_xlate_add(xl, "sport%s %u",
|
||||
- einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
|
||||
- einfo->spts[0]);
|
||||
+ xt_xlate_add(xl, "-%u", einfo->spts[1]);
|
||||
+
|
||||
space = " ";
|
||||
}
|
||||
|
||||
if (einfo->flags & XT_DCCP_DEST_PORTS) {
|
||||
+ xt_xlate_add(xl, "%sdccp dport%s %u", space,
|
||||
+ einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
|
||||
+ einfo->dpts[0]);
|
||||
+
|
||||
if (einfo->dpts[0] != einfo->dpts[1])
|
||||
- xt_xlate_add(xl, "%sdport%s %u-%u", space,
|
||||
- einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
|
||||
- einfo->dpts[0], einfo->dpts[1]);
|
||||
- else
|
||||
- xt_xlate_add(xl, "%sdport%s %u", space,
|
||||
- einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
|
||||
- einfo->dpts[0]);
|
||||
+ xt_xlate_add(xl, "-%u", einfo->dpts[1]);
|
||||
+
|
||||
+ space = " ";
|
||||
}
|
||||
|
||||
- if (einfo->flags & XT_DCCP_TYPE)
|
||||
+ if (einfo->flags & XT_DCCP_TYPE && einfo->typemask) {
|
||||
+ xt_xlate_add(xl, "%sdccp type%s ", space,
|
||||
+ einfo->invflags & XT_DCCP_TYPE ? " !=" : "");
|
||||
ret = dccp_type_xlate(einfo, xl);
|
||||
|
||||
+ space = " ";
|
||||
+ }
|
||||
+
|
||||
+ /* FIXME: no dccp option support in nftables yet */
|
||||
if (einfo->flags & XT_DCCP_OPTION)
|
||||
ret = 0;
|
||||
|
||||
diff --git a/extensions/libxt_dccp.txlate b/extensions/libxt_dccp.txlate
|
||||
index b47dc65f5bc4f..ea853f6acf627 100644
|
||||
--- a/extensions/libxt_dccp.txlate
|
||||
+++ b/extensions/libxt_dccp.txlate
|
||||
@@ -7,8 +7,14 @@ nft add rule ip filter INPUT dccp dport 100-200 counter
|
||||
iptables-translate -A INPUT -p dccp -m dccp ! --dport 100
|
||||
nft add rule ip filter INPUT dccp dport != 100 counter
|
||||
|
||||
-iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK
|
||||
-nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack} counter
|
||||
+iptables-translate -A INPUT -p dccp -m dccp --dccp-types CLOSE
|
||||
+nft add rule ip filter INPUT dccp type close counter
|
||||
+
|
||||
+iptables-translate -A INPUT -p dccp -m dccp --dccp-types INVALID
|
||||
+nft add rule ip filter INPUT dccp type 10-15 counter
|
||||
+
|
||||
+iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK,INVALID
|
||||
+nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack, 10-15} counter
|
||||
|
||||
iptables-translate -A INPUT -p dccp -m dccp --sport 200 --dport 100
|
||||
-nft add rule ip filter INPUT dccp sport 200 dport 100 counter
|
||||
+nft add rule ip filter INPUT dccp sport 200 dccp dport 100 counter
|
||||
--
|
||||
2.28.0
|
||||
|
@ -134,7 +134,7 @@ load_sysctl() {
|
||||
echo -n $"Loading sysctl settings: "
|
||||
ret=0
|
||||
for item in $IPTABLES_SYSCTL_LOAD_LIST; do
|
||||
fgrep -hs $item /etc/sysctl.d/* | sysctl -p - >/dev/null
|
||||
fgrep -hs $item /etc/sysctl.d/*.conf | sysctl -p - >/dev/null
|
||||
let ret+=$?;
|
||||
done
|
||||
[ $ret -eq 0 ] && success || failure
|
||||
|
@ -17,7 +17,7 @@ Name: iptables
|
||||
Summary: Tools for managing Linux kernel packet filtering capabilities
|
||||
URL: http://www.netfilter.org/projects/iptables
|
||||
Version: 1.8.4
|
||||
Release: 14%{?dist}
|
||||
Release: 17%{?dist}
|
||||
Source: %{url}/files/%{name}-%{version}.tar.bz2
|
||||
Source1: iptables.init
|
||||
Source2: iptables-config
|
||||
@ -59,6 +59,24 @@ Patch22: 0022-nfnl_osf-Improve-error-handling.patch
|
||||
Patch23: 0023-nft-cache-Reset-genid-when-rebuilding-cache.patch
|
||||
Patch24: 0024-nft-Fix-for-F-in-iptables-dumps.patch
|
||||
Patch25: 0025-tests-shell-Test-F-in-dump-files.patch
|
||||
Patch26: 0026-nft-Make-batch_add_chain-return-the-added-batch-obje.patch
|
||||
Patch27: 0027-nft-Fix-error-reporting-for-refreshed-transactions.patch
|
||||
Patch28: 0028-nft-Fix-for-concurrent-noflush-restore-calls.patch
|
||||
Patch29: 0029-tests-shell-Improve-concurrent-noflush-restore-test-.patch
|
||||
Patch30: 0030-nft-cache-Make-nft_rebuild_cache-respect-fake-cache.patch
|
||||
Patch31: 0031-nft-Fix-for-broken-address-mask-match-detection.patch
|
||||
Patch32: 0032-nft-Optimize-class-based-IP-prefix-matches.patch
|
||||
Patch33: 0033-ebtables-Optimize-masked-MAC-address-matches.patch
|
||||
Patch34: 0034-tests-shell-Add-test-for-bitwise-avoidance-fixes.patch
|
||||
Patch35: 0035-libxtables-Make-sure-extensions-register-in-revision.patch
|
||||
Patch36: 0036-libxtables-Simplify-pending-extension-registration.patch
|
||||
Patch37: 0037-libxtables-Register-multiple-extensions-in-ascending.patch
|
||||
Patch38: 0038-tests-shell-Test-for-fixed-extension-registration.patch
|
||||
Patch39: 0039-extensions-libipt_icmp-Fix-translation-of-type-any.patch
|
||||
Patch40: 0040-extensions-libxt_CT-add-translation-for-NOTRACK.patch
|
||||
Patch41: 0041-nft-Fix-command-name-in-ip6tables-error-message.patch
|
||||
Patch42: 0042-tests-shell-Merge-and-extend-return-codes-test.patch
|
||||
Patch43: 0043-extensions-dccp-Fix-for-DCCP-type-INVALID.patch
|
||||
|
||||
# pf.os: ISC license
|
||||
# iptables-apply: Artistic Licence 2.0
|
||||
@ -467,6 +485,31 @@ done
|
||||
%doc %{_mandir}/man8/ebtables*.8*
|
||||
|
||||
%changelog
|
||||
* Thu Dec 10 2020 Phil Sutter <psutter@redhat.com> - 1.8.4-17
|
||||
- extensions: dccp: Fix for DCCP type 'INVALID'
|
||||
- tests: shell: Merge and extend return codes test
|
||||
- nft: Fix command name in ip6tables error message
|
||||
- extensions: libxt_CT: add translation for NOTRACK
|
||||
- extensions: libipt_icmp: Fix translation of type 'any'
|
||||
- tests/shell: Test for fixed extension registration
|
||||
- libxtables: Register multiple extensions in ascending order
|
||||
- libxtables: Simplify pending extension registration
|
||||
- libxtables: Make sure extensions register in revision order
|
||||
|
||||
* Wed Oct 28 2020 Phil Sutter <psutter@redhat.com> - 1.8.4-16
|
||||
- tests/shell: Add test for bitwise avoidance fixes
|
||||
- ebtables: Optimize masked MAC address matches
|
||||
- nft: Optimize class-based IP prefix matches
|
||||
- nft: Fix for broken address mask match detection
|
||||
- nft: cache: Make nft_rebuild_cache() respect fake cache
|
||||
- tests: shell: Improve concurrent noflush restore test a bit
|
||||
- nft: Fix for concurrent noflush restore calls
|
||||
- nft: Fix error reporting for refreshed transactions
|
||||
- nft: Make batch_add_chain() return the added batch object
|
||||
|
||||
* Sat Aug 15 2020 Phil Sutter <psutter@redhat.com> - 1.8.4-15
|
||||
- Ignore sysctl files not suffixed '.conf'
|
||||
|
||||
* Wed Jun 24 2020 Phil Sutter <psutter@redhat.com> - 1.8.4-14
|
||||
- nft: Fix for '-F' in iptables dumps
|
||||
- tests: shell: Test -F in dump files
|
||||
|
Loading…
Reference in New Issue
Block a user