diff --git a/SOURCES/0044-nft-cache-Retry-if-kernel-returns-EINTR.patch b/SOURCES/0044-nft-cache-Retry-if-kernel-returns-EINTR.patch deleted file mode 100644 index b9fae4a..0000000 --- a/SOURCES/0044-nft-cache-Retry-if-kernel-returns-EINTR.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 49b00c1d89ab0f0b1a2ebf5bb9207311e8ea164e Mon Sep 17 00:00:00 2001 -From: Phil Sutter -Date: Wed, 4 Aug 2021 17:14:05 +0200 -Subject: [PATCH] nft: cache: Retry if kernel returns EINTR - -In case of parallel ruleset updates, recvfrom() calls may return EINTR. -Due to the fact that cache fetches may get triggered while iterating -over cache elements, __nft_build_cache must not restart based on -comparing before and after generation ID like upstream does. Instead, -just retry the recvfrom() calls until they either succeed or return a -different error than EINTR. ---- - iptables/nft-cache.c | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - -diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c -index 9623b463f0dd5..699dc66a95cd1 100644 ---- a/iptables/nft-cache.c -+++ b/iptables/nft-cache.c -@@ -98,9 +98,12 @@ static int fetch_table_cache(struct nft_handle *h) - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, - NLM_F_DUMP, h->seq); - -+retry: - ret = mnl_talk(h, nlh, nftnl_table_list_cb, list); -- if (ret < 0 && errno == EINTR) -+ if (ret < 0 && errno == EINTR) { - assert(nft_restart(h) >= 0); -+ goto retry; -+ } - - h->cache->tables = list; - -@@ -275,10 +278,11 @@ static int fetch_set_cache(struct nft_handle *h, - NLM_F_DUMP, h->seq); - } - -+retry: - ret = mnl_talk(h, nlh, nftnl_set_list_cb, &d); - if (ret < 0 && errno == EINTR) { - assert(nft_restart(h) >= 0); -- return ret; -+ goto retry; - } - - if (t && set) { -@@ -355,9 +359,12 @@ static int fetch_chain_cache(struct nft_handle *h, - h->seq); - } - -+retry: - ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d); -- if (ret < 0 && errno == EINTR) -+ if (ret < 0 && errno == EINTR) { - assert(nft_restart(h) >= 0); -+ goto retry; -+ } - - return ret; - } -@@ -404,9 +411,12 @@ static int nft_rule_list_update(struct nftnl_chain *c, void *data) - NLM_F_DUMP, h->seq); - nftnl_rule_nlmsg_build_payload(nlh, rule); - -+retry: - ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c); -- if (ret < 0 && errno == EINTR) -+ if (ret < 0 && errno == EINTR) { - assert(nft_restart(h) >= 0); -+ goto retry; -+ } - - nftnl_rule_free(rule); - --- -2.32.0 - diff --git a/SOURCES/0044-xtables-monitor-Fix-ip6tables-rule-printing.patch b/SOURCES/0044-xtables-monitor-Fix-ip6tables-rule-printing.patch new file mode 100644 index 0000000..c0f14d7 --- /dev/null +++ b/SOURCES/0044-xtables-monitor-Fix-ip6tables-rule-printing.patch @@ -0,0 +1,38 @@ +From 538acaef0d8424bd61047e6f1b81e3bc8bd421ec Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 7 Aug 2020 16:42:07 +0200 +Subject: [PATCH] xtables-monitor: Fix ip6tables rule printing + +When printing an ip6tables rule event, false family ops are used as they +are initially looked up for AF_INET and reused no matter the current +rule's family. In practice, this means that nft_rule_print_save() calls +the wrong rule_to_cs, save_rule and clear_cs callbacks. Therefore, if a +rule specifies a source or destination address, the address is not +printed. + +Fix this by performing a family lookup each time rule_cb is called. + +Signed-off-by: Phil Sutter +Acked-by: Pablo Neira Ayuso +(cherry picked from commit ca69b0290dc509d72118f0a054a5c740cb913875) +Signed-off-by: Phil Sutter +--- + iptables/xtables-monitor.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index c2b31dbaa0795..92962a2a95f48 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -93,6 +93,8 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data) + if (arg->nfproto && arg->nfproto != family) + goto err_free; + ++ arg->h->ops = nft_family_ops_lookup(family); ++ + if (arg->is_event) + printf(" EVENT: "); + switch (family) { +-- +2.31.1 + diff --git a/SOURCES/0045-xtables-monitor-fix-rule-printing.patch b/SOURCES/0045-xtables-monitor-fix-rule-printing.patch new file mode 100644 index 0000000..c878ec2 --- /dev/null +++ b/SOURCES/0045-xtables-monitor-fix-rule-printing.patch @@ -0,0 +1,86 @@ +From 0b886ea23e8473e692bdf20ecf4985f44408a132 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Sat, 12 Dec 2020 16:15:32 +0100 +Subject: [PATCH] xtables-monitor: fix rule printing + +trace_print_rule does a rule dump. This prints unrelated rules +in the same chain. Instead the function should only request the +specific handle. + +Furthermore, flush output buffer afterwards so this plays nice when +output isn't a terminal. + +Signed-off-by: Florian Westphal +(cherry picked from commit 07af4da52ab3002c9cb510863b4eb7aaca4fb43b) +Signed-off-by: Phil Sutter +--- + iptables/xtables-monitor.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index 92962a2a95f48..43b9064c3d30e 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -227,12 +227,12 @@ static void trace_print_rule(const struct nftnl_trace *nlt, struct cb_arg *args) + exit(EXIT_FAILURE); + } + +- nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, NLM_F_DUMP, 0); ++ nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, 0, 0); + + nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family); + nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain); + nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table); +- nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle); ++ nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE, handle); + nftnl_rule_nlmsg_build_payload(nlh, r); + nftnl_rule_free(r); + +@@ -248,24 +248,21 @@ static void trace_print_rule(const struct nftnl_trace *nlt, struct cb_arg *args) + } + + portid = mnl_socket_get_portid(nl); +- if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { +- perror("mnl_socket_send"); +- exit(EXIT_FAILURE); +- } ++ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { ++ perror("mnl_socket_send"); ++ exit(EXIT_FAILURE); ++ } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); +- while (ret > 0) { ++ if (ret > 0) { + args->is_event = false; +- ret = mnl_cb_run(buf, ret, 0, portid, rule_cb, args); +- if (ret <= 0) +- break; +- ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); +- } +- if (ret == -1) { +- perror("error"); +- exit(EXIT_FAILURE); +- } +- mnl_socket_close(nl); ++ ret = mnl_cb_run(buf, ret, 0, portid, rule_cb, args); ++ } ++ if (ret == -1) { ++ perror("error"); ++ exit(EXIT_FAILURE); ++ } ++ mnl_socket_close(nl); + } + + static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg *args) +@@ -531,6 +528,7 @@ static int trace_cb(const struct nlmsghdr *nlh, struct cb_arg *arg) + err_free: + nftnl_trace_free(nlt); + err: ++ fflush(stdout); + return MNL_CB_OK; + } + +-- +2.31.1 + diff --git a/SOURCES/0046-xtables-monitor-fix-packet-family-protocol.patch b/SOURCES/0046-xtables-monitor-fix-packet-family-protocol.patch new file mode 100644 index 0000000..67acb11 --- /dev/null +++ b/SOURCES/0046-xtables-monitor-fix-packet-family-protocol.patch @@ -0,0 +1,39 @@ +From d272e1225bf9b31ec0397bd86b39a54da49d5468 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Sat, 12 Dec 2020 16:15:33 +0100 +Subject: [PATCH] xtables-monitor: fix packet family protocol + +This prints the family passed on the command line (which might be 0). +Print the table family instead. + +Signed-off-by: Florian Westphal +(cherry picked from commit 946923b640afc2249cf98743ff60a97291108701) +Signed-off-by: Phil Sutter +--- + iptables/xtables-monitor.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index 43b9064c3d30e..9fa1ca166a61e 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -273,14 +273,14 @@ static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg *arg + uint32_t mark; + char name[IFNAMSIZ]; + +- printf("PACKET: %d %08x ", args->nfproto, nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID)); ++ family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY); ++ printf("PACKET: %d %08x ", family, nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID)); + + if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF)) + printf("IN=%s ", if_indextoname(nftnl_trace_get_u32(nlt, NFTNL_TRACE_IIF), name)); + if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF)) + printf("OUT=%s ", if_indextoname(nftnl_trace_get_u32(nlt, NFTNL_TRACE_OIF), name)); + +- family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY); + nfproto = family; + if (nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) { + nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO); +-- +2.31.1 + diff --git a/SOURCES/0047-xtables-monitor-print-packet-first.patch b/SOURCES/0047-xtables-monitor-print-packet-first.patch new file mode 100644 index 0000000..30ffb03 --- /dev/null +++ b/SOURCES/0047-xtables-monitor-print-packet-first.patch @@ -0,0 +1,102 @@ +From 07f51d26e405b4a328813f35bc27015eb9324330 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Sat, 12 Dec 2020 16:15:34 +0100 +Subject: [PATCH] xtables-monitor: print packet first + +The trace mode should first print the packet that was received and +then the rule/verdict. + +Furthermore, the monitor did sometimes print an extra newline. + +After this patch, output is more consistent with nft monitor. + +Signed-off-by: Florian Westphal +(cherry picked from commit 180ba723d0b305fab9287d3bc5f845a43d9eb793) +Signed-off-by: Phil Sutter +--- + iptables/xtables-monitor.c | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index 9fa1ca166a61e..23e828988bb8b 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -106,6 +106,7 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data) + printf("-0 "); + break; + default: ++ puts(""); + goto err_free; + } + +@@ -433,9 +434,18 @@ static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg *arg + mark = nftnl_trace_get_u32(nlt, NFTNL_TRACE_MARK); + if (mark) + printf("MARK=0x%x ", mark); ++ puts(""); ++} ++ ++static void trace_print_hdr(const struct nftnl_trace *nlt) ++{ ++ printf(" TRACE: %d %08x %s:%s", nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY), ++ nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID), ++ nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE), ++ nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN)); + } + +-static void print_verdict(struct nftnl_trace *nlt, uint32_t verdict) ++static void print_verdict(const struct nftnl_trace *nlt, uint32_t verdict) + { + const char *chain; + +@@ -496,35 +506,37 @@ static int trace_cb(const struct nlmsghdr *nlh, struct cb_arg *arg) + arg->nfproto != nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY)) + goto err_free; + +- printf(" TRACE: %d %08x %s:%s", nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY), +- nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID), +- nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE), +- nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN)); +- + switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) { + case NFT_TRACETYPE_RULE: + verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT); +- printf(":rule:0x%llx:", (unsigned long long)nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE)); +- print_verdict(nlt, verdict); + +- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE)) +- trace_print_rule(nlt, arg); + if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) || + nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER)) + trace_print_packet(nlt, arg); ++ ++ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE)) { ++ trace_print_hdr(nlt); ++ printf(":rule:0x%" PRIx64":", nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE)); ++ print_verdict(nlt, verdict); ++ printf(" "); ++ trace_print_rule(nlt, arg); ++ } + break; + case NFT_TRACETYPE_POLICY: ++ trace_print_hdr(nlt); + printf(":policy:"); + verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_POLICY); + + print_verdict(nlt, verdict); ++ puts(""); + break; + case NFT_TRACETYPE_RETURN: ++ trace_print_hdr(nlt); + printf(":return:"); + trace_print_return(nlt); ++ puts(""); + break; + } +- puts(""); + err_free: + nftnl_trace_free(nlt); + err: +-- +2.31.1 + diff --git a/SOURCES/0048-xtables-monitor.patch b/SOURCES/0048-xtables-monitor.patch new file mode 100644 index 0000000..128393b --- /dev/null +++ b/SOURCES/0048-xtables-monitor.patch @@ -0,0 +1,31 @@ +From d64511250cf43ae11e18964cc0dccf9c2d6c3973 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Mon, 14 Dec 2020 17:11:23 +0100 +Subject: [PATCH] xtables-monitor: + +'LL=0x304' is not very convenient, print LOOPBACK instead. + +Signed-off-by: Florian Westphal +(cherry picked from commit 98ed6f6fc6d97663a33de67afff60196052880b1) +Signed-off-by: Phil Sutter +--- + iptables/xtables-monitor.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c +index 23e828988bb8b..88033a59526d2 100644 +--- a/iptables/xtables-monitor.c ++++ b/iptables/xtables-monitor.c +@@ -306,6 +306,9 @@ static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg *arg + printf("MACDST=%s ", ether_ntoa((const void *)eh->h_dest)); + printf("MACPROTO=%04x ", ntohs(eh->h_proto)); + break; ++ case ARPHRD_LOOPBACK: ++ printf("LOOPBACK "); ++ break; + default: + printf("LL=0x%x ", type); + for (i = 0 ; i < len; i++) +-- +2.31.1 + diff --git a/SOURCES/0049-nft-Fix-bitwise-expression-avoidance-detection.patch b/SOURCES/0049-nft-Fix-bitwise-expression-avoidance-detection.patch new file mode 100644 index 0000000..32ee3e9 --- /dev/null +++ b/SOURCES/0049-nft-Fix-bitwise-expression-avoidance-detection.patch @@ -0,0 +1,74 @@ +From f2d177c3a7a6a7154aabfab6047c510e0cee428e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 19 Feb 2021 16:54:57 +0100 +Subject: [PATCH] nft: Fix bitwise expression avoidance detection + +Byte-boundary prefix detection was too sloppy: Any data following the +first zero-byte was ignored. Add a follow-up loop making sure there are +no stray bits in the designated host part. + +Fixes: 323259001d617 ("nft: Optimize class-based IP prefix matches") +Signed-off-by: Phil Sutter +(cherry picked from commit 330f5df03ad589b46865ceedf2a54cf10a4225ba) +Signed-off-by: Phil Sutter +--- + iptables/nft-shared.c | 4 +++- + .../testcases/ip6tables/0004-address-masks_0 | 24 +++++++++++++++++++ + 2 files changed, 27 insertions(+), 1 deletion(-) + create mode 100755 iptables/tests/shell/testcases/ip6tables/0004-address-masks_0 + +diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c +index 2aae0a3a49dfe..7f757d38ecaec 100644 +--- a/iptables/nft-shared.c ++++ b/iptables/nft-shared.c +@@ -166,7 +166,7 @@ void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset, + { + const unsigned char *m = mask; + bool bitwise = false; +- int i; ++ int i, j; + + for (i = 0; i < len; i++) { + if (m[i] != 0xff) { +@@ -174,6 +174,8 @@ void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset, + break; + } + } ++ for (j = i + 1; !bitwise && j < len; j++) ++ bitwise = !!m[j]; + + if (!bitwise) + len = i; +diff --git a/iptables/tests/shell/testcases/ip6tables/0004-address-masks_0 b/iptables/tests/shell/testcases/ip6tables/0004-address-masks_0 +new file mode 100755 +index 0000000000000..7eb42f08da975 +--- /dev/null ++++ b/iptables/tests/shell/testcases/ip6tables/0004-address-masks_0 +@@ -0,0 +1,24 @@ ++#!/bin/bash ++ ++set -e ++ ++$XT_MULTI ip6tables-restore < +Date: Tue, 2 Mar 2021 14:50:07 +0100 +Subject: [PATCH] xtables-translate: Fix translation of odd netmasks + +Iptables supports netmasks which are not prefixes to match on (or +ignore) arbitrary bits in an address. Yet nftables' prefix notation is +available for real prefixes only, so translation is not as trivial - +print bitmask syntax for those cases. + +Signed-off-by: Phil Sutter +(cherry picked from commit 46f9d3a9a61ee80fa94b7fa7b3b36045c92606ae) +Signed-off-by: Phil Sutter +--- + extensions/generic.txlate | 48 +++++++++++++++++++++++++++++++++++++ + extensions/libxt_standard.t | 12 ++++++++++ + iptables/nft-ipv4.c | 42 ++++++++++++++++++++++---------- + iptables/nft-ipv6.c | 19 ++++++++++++--- + 4 files changed, 106 insertions(+), 15 deletions(-) + +diff --git a/extensions/generic.txlate b/extensions/generic.txlate +index 0e256c3727559..9ae9a5b54c1b9 100644 +--- a/extensions/generic.txlate ++++ b/extensions/generic.txlate +@@ -10,6 +10,54 @@ nft insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter + iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8 + nft add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter + ++iptables-translate -I INPUT -s 10.11.12.13/255.255.0.0 ++nft insert rule ip filter INPUT ip saddr 10.11.0.0/16 counter ++ ++iptables-translate -I INPUT -s 10.11.12.13/255.0.255.0 ++nft insert rule ip filter INPUT ip saddr & 255.0.255.0 == 10.0.12.0 counter ++ ++iptables-translate -I INPUT -s 10.11.12.13/0.255.0.255 ++nft insert rule ip filter INPUT ip saddr & 0.255.0.255 == 0.11.0.13 counter ++ ++iptables-translate -I INPUT ! -s 10.11.12.13/0.255.0.255 ++nft insert rule ip filter INPUT ip saddr & 0.255.0.255 != 0.11.0.13 counter ++ ++iptables-translate -I INPUT -s 0.0.0.0/16 ++nft insert rule ip filter INPUT ip saddr 0.0.0.0/16 counter ++ ++iptables-translate -I INPUT -s 0.0.0.0/0 ++nft insert rule ip filter INPUT counter ++ ++iptables-translate -I INPUT ! -s 0.0.0.0/0 ++nft insert rule ip filter INPUT ip saddr != 0.0.0.0/0 counter ++ ++ip6tables-translate -I INPUT -i iifname -s feed::/16 ++nft insert rule ip6 filter INPUT iifname "iifname" ip6 saddr feed::/16 counter ++ ++ip6tables-translate -A INPUT -i iif+ ! -d feed::/16 ++nft add rule ip6 filter INPUT iifname "iif*" ip6 daddr != feed::/16 counter ++ ++ip6tables-translate -I INPUT -s feed:babe::1/ffff:ff00:: ++nft insert rule ip6 filter INPUT ip6 saddr feed:ba00::/24 counter ++ ++ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/ffff:0:ffff:0:ffff:0:ffff:0 ++nft insert rule ip6 filter INPUT ip6 saddr & ffff:0:ffff:0:ffff:0:ffff:0 == feed:0:c0ff:0:c0be:0:5678:0 counter ++ ++ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff ++nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff == 0:babe:0:ee00:0:1234:0:90ab counter ++ ++ip6tables-translate -I INPUT ! -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff ++nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff != 0:babe:0:ee00:0:1234:0:90ab counter ++ ++ip6tables-translate -I INPUT -s ::/16 ++nft insert rule ip6 filter INPUT ip6 saddr ::/16 counter ++ ++ip6tables-translate -I INPUT -s ::/0 ++nft insert rule ip6 filter INPUT counter ++ ++ip6tables-translate -I INPUT ! -s ::/0 ++nft insert rule ip6 filter INPUT ip6 saddr != ::/0 counter ++ + ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0 + nft insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter + +diff --git a/extensions/libxt_standard.t b/extensions/libxt_standard.t +index 4313f7b7bac9d..56d6da2e5884e 100644 +--- a/extensions/libxt_standard.t ++++ b/extensions/libxt_standard.t +@@ -9,3 +9,15 @@ + -j ACCEPT;=;OK + -j RETURN;=;OK + ! -p 0 -j ACCEPT;=;FAIL ++-s 10.11.12.13/8;-s 10.0.0.0/8;OK ++-s 10.11.12.13/9;-s 10.0.0.0/9;OK ++-s 10.11.12.13/10;-s 10.0.0.0/10;OK ++-s 10.11.12.13/11;-s 10.0.0.0/11;OK ++-s 10.11.12.13/12;-s 10.0.0.0/12;OK ++-s 10.11.12.13/30;-s 10.11.12.12/30;OK ++-s 10.11.12.13/31;-s 10.11.12.12/31;OK ++-s 10.11.12.13/32;-s 10.11.12.13/32;OK ++-s 10.11.12.13/255.0.0.0;-s 10.0.0.0/8;OK ++-s 10.11.12.13/255.128.0.0;-s 10.0.0.0/9;OK ++-s 10.11.12.13/255.0.255.0;-s 10.0.12.0/255.0.255.0;OK ++-s 10.11.12.13/255.0.12.0;-s 10.0.12.0/255.0.12.0;OK +diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c +index 5bd0710781533..af5db31532540 100644 +--- a/iptables/nft-ipv4.c ++++ b/iptables/nft-ipv4.c +@@ -383,6 +383,32 @@ static void nft_ipv4_post_parse(int command, + " source or destination IP addresses"); + } + ++static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr, ++ const struct in_addr *mask, ++ bool inv, struct xt_xlate *xl) ++{ ++ const char *op = inv ? "!= " : ""; ++ int cidr; ++ ++ if (!inv && !addr->s_addr && !mask->s_addr) ++ return; ++ ++ cidr = xtables_ipmask_to_cidr(mask); ++ switch (cidr) { ++ case -1: ++ /* inet_ntoa() is not reentrant */ ++ xt_xlate_add(xl, "%s & %s ", selector, inet_ntoa(*mask)); ++ xt_xlate_add(xl, "%s %s ", inv ? "!=" : "==", inet_ntoa(*addr)); ++ break; ++ case 32: ++ xt_xlate_add(xl, "%s %s%s ", selector, op, inet_ntoa(*addr)); ++ break; ++ default: ++ xt_xlate_add(xl, "%s %s%s/%d ", selector, op, inet_ntoa(*addr), ++ cidr); ++ } ++} ++ + static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl) + { + const struct iptables_command_state *cs = data; +@@ -417,18 +443,10 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl) + } + } + +- if (cs->fw.ip.src.s_addr != 0) { +- xt_xlate_add(xl, "ip saddr %s%s%s ", +- cs->fw.ip.invflags & IPT_INV_SRCIP ? "!= " : "", +- inet_ntoa(cs->fw.ip.src), +- xtables_ipmask_to_numeric(&cs->fw.ip.smsk)); +- } +- if (cs->fw.ip.dst.s_addr != 0) { +- xt_xlate_add(xl, "ip daddr %s%s%s ", +- cs->fw.ip.invflags & IPT_INV_DSTIP ? "!= " : "", +- inet_ntoa(cs->fw.ip.dst), +- xtables_ipmask_to_numeric(&cs->fw.ip.dmsk)); +- } ++ xlate_ipv4_addr("ip saddr", &cs->fw.ip.src, &cs->fw.ip.smsk, ++ cs->fw.ip.invflags & IPT_INV_SRCIP, xl); ++ xlate_ipv4_addr("ip daddr", &cs->fw.ip.dst, &cs->fw.ip.dmsk, ++ cs->fw.ip.invflags & IPT_INV_DSTIP, xl); + + ret = xlate_matches(cs, xl); + if (!ret) +diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c +index 6ece631d85f59..a5481b3f77ac5 100644 +--- a/iptables/nft-ipv6.c ++++ b/iptables/nft-ipv6.c +@@ -337,14 +337,27 @@ static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr, + const struct in6_addr *mask, + int invert, struct xt_xlate *xl) + { ++ const char *op = invert ? "!= " : ""; + char addr_str[INET6_ADDRSTRLEN]; ++ int cidr; + +- if (!invert && IN6_IS_ADDR_UNSPECIFIED(addr)) ++ if (!invert && IN6_IS_ADDR_UNSPECIFIED(addr) && IN6_IS_ADDR_UNSPECIFIED(mask)) + return; + + inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); +- xt_xlate_add(xl, "%s %s%s%s ", selector, invert ? "!= " : "", addr_str, +- xtables_ip6mask_to_numeric(mask)); ++ cidr = xtables_ip6mask_to_cidr(mask); ++ switch (cidr) { ++ case -1: ++ xt_xlate_add(xl, "%s & %s %s %s ", selector, ++ xtables_ip6addr_to_numeric(mask), ++ invert ? "!=" : "==", addr_str); ++ break; ++ case 128: ++ xt_xlate_add(xl, "%s %s%s ", selector, op, addr_str); ++ break; ++ default: ++ xt_xlate_add(xl, "%s %s%s/%d ", selector, op, addr_str, cidr); ++ } + } + + static int nft_ipv6_xlate(const void *data, struct xt_xlate *xl) +-- +2.31.1 + diff --git a/SOURCES/0051-Eliminate-inet_aton-and-inet_ntoa.patch b/SOURCES/0051-Eliminate-inet_aton-and-inet_ntoa.patch new file mode 100644 index 0000000..668cbce --- /dev/null +++ b/SOURCES/0051-Eliminate-inet_aton-and-inet_ntoa.patch @@ -0,0 +1,120 @@ +From 97b85789657bab340fd7aaaf6d41b8f698f9a5b1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 27 Apr 2021 09:12:53 +0200 +Subject: [PATCH] Eliminate inet_aton() and inet_ntoa() + +Both functions are obsolete, replace them by equivalent calls to +inet_pton() and inet_ntop(). + +Signed-off-by: Phil Sutter +(cherry picked from commit acac2dbe64e5120394fa715bb5fe95c42d08b8b3) +--- + extensions/libebt_among.c | 6 ++++-- + iptables/nft-ipv4.c | 23 ++++++++++++++--------- + 2 files changed, 18 insertions(+), 11 deletions(-) + +diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c +index 2b9a1b6566684..7eb898f984bba 100644 +--- a/extensions/libebt_among.c ++++ b/extensions/libebt_among.c +@@ -66,7 +66,7 @@ parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip) + if (sep) { + *sep = '\0'; + +- if (!inet_aton(sep + 1, &pair->in)) ++ if (!inet_pton(AF_INET, sep + 1, &pair->in)) + xtables_error(PARAMETER_PROBLEM, + "Invalid IP address '%s'\n", sep + 1); + } +@@ -194,6 +194,7 @@ static void __bramong_print(struct nft_among_pair *pairs, + int cnt, bool inv, bool have_ip) + { + const char *isep = inv ? "! " : ""; ++ char abuf[INET_ADDRSTRLEN]; + int i; + + for (i = 0; i < cnt; i++) { +@@ -202,7 +203,8 @@ static void __bramong_print(struct nft_among_pair *pairs, + + printf("%s", ether_ntoa(&pairs[i].ether)); + if (pairs[i].in.s_addr != INADDR_ANY) +- printf("=%s", inet_ntoa(pairs[i].in)); ++ printf("=%s", inet_ntop(AF_INET, &pairs[i].in, ++ abuf, sizeof(abuf))); + } + printf(" "); + } +diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c +index af5db31532540..d8c48ce8817b6 100644 +--- a/iptables/nft-ipv4.c ++++ b/iptables/nft-ipv4.c +@@ -136,7 +136,7 @@ static void get_frag(struct nft_xt_ctx *ctx, struct nftnl_expr *e, bool *inv) + + static const char *mask_to_str(uint32_t mask) + { +- static char mask_str[sizeof("255.255.255.255")]; ++ static char mask_str[INET_ADDRSTRLEN]; + uint32_t bits, hmask = ntohl(mask); + struct in_addr mask_addr = { + .s_addr = mask, +@@ -155,7 +155,7 @@ static const char *mask_to_str(uint32_t mask) + if (i >= 0) + sprintf(mask_str, "%u", i); + else +- sprintf(mask_str, "%s", inet_ntoa(mask_addr)); ++ inet_ntop(AF_INET, &mask_addr, mask_str, sizeof(mask_str)); + + return mask_str; + } +@@ -298,10 +298,13 @@ static void nft_ipv4_print_rule(struct nft_handle *h, struct nftnl_rule *r, + static void save_ipv4_addr(char letter, const struct in_addr *addr, + uint32_t mask, int invert) + { ++ char addrbuf[INET_ADDRSTRLEN]; ++ + if (!mask && !invert && !addr->s_addr) + return; + +- printf("%s-%c %s/%s ", invert ? "! " : "", letter, inet_ntoa(*addr), ++ printf("%s-%c %s/%s ", invert ? "! " : "", letter, ++ inet_ntop(AF_INET, addr, addrbuf, sizeof(addrbuf)), + mask_to_str(mask)); + } + +@@ -387,25 +390,27 @@ static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr, + const struct in_addr *mask, + bool inv, struct xt_xlate *xl) + { ++ char mbuf[INET_ADDRSTRLEN], abuf[INET_ADDRSTRLEN]; + const char *op = inv ? "!= " : ""; + int cidr; + + if (!inv && !addr->s_addr && !mask->s_addr) + return; + ++ inet_ntop(AF_INET, addr, abuf, sizeof(abuf)); ++ + cidr = xtables_ipmask_to_cidr(mask); + switch (cidr) { + case -1: +- /* inet_ntoa() is not reentrant */ +- xt_xlate_add(xl, "%s & %s ", selector, inet_ntoa(*mask)); +- xt_xlate_add(xl, "%s %s ", inv ? "!=" : "==", inet_ntoa(*addr)); ++ xt_xlate_add(xl, "%s & %s %s %s ", selector, ++ inet_ntop(AF_INET, mask, mbuf, sizeof(mbuf)), ++ inv ? "!=" : "==", abuf); + break; + case 32: +- xt_xlate_add(xl, "%s %s%s ", selector, op, inet_ntoa(*addr)); ++ xt_xlate_add(xl, "%s %s%s ", selector, op, abuf); + break; + default: +- xt_xlate_add(xl, "%s %s%s/%d ", selector, op, inet_ntoa(*addr), +- cidr); ++ xt_xlate_add(xl, "%s %s%s/%d ", selector, op, abuf, cidr); + } + } + +-- +2.31.1 + diff --git a/SOURCES/0052-xtables-arp-Don-t-use-ARPT_INV_.patch b/SOURCES/0052-xtables-arp-Don-t-use-ARPT_INV_.patch new file mode 100644 index 0000000..a24c2f8 --- /dev/null +++ b/SOURCES/0052-xtables-arp-Don-t-use-ARPT_INV_.patch @@ -0,0 +1,374 @@ +From a5d52efe21e0f0ba6447b48e1646bb7046cb09eb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 3 Nov 2020 12:21:29 +0100 +Subject: [PATCH] xtables-arp: Don't use ARPT_INV_* + +Arptables invflags are partly identical to IPT_INV_* ones but the bits +are differently assigned. Eliminate this incompatibility by definition +of the unique invflags in nft-arp.h on bits that don't collide with +IPT_INV_* ones, then use those in combination with IPT_INV_* ones in +arptables-specific code. + +Note that ARPT_INV_ARPPRO is replaced by IPT_INV_PROTO although these +are in fact different options - yet since '-p' option is not supported +by arptables, this does not lead to a collision. + +Signed-off-by: Phil Sutter +(cherry picked from commit 44457c0805905ea22b4ecf9156648e774dd29155) +--- + iptables/nft-arp.c | 92 ++++++++++++++++-------------------------- + iptables/nft-arp.h | 7 ++++ + iptables/xtables-arp.c | 22 +++++----- + 3 files changed, 53 insertions(+), 68 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 776b55949472b..ec8147dd58c0d 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -134,34 +134,34 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data) + int ret = 0; + + if (fw->arp.iniface[0] != '\0') { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_VIA_IN); ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_VIA_IN); + add_iniface(r, fw->arp.iniface, op); + } + + if (fw->arp.outiface[0] != '\0') { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_VIA_OUT); ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_VIA_OUT); + add_outiface(r, fw->arp.outiface, op); + } + + if (fw->arp.arhrd != 0 || +- fw->arp.invflags & ARPT_INV_ARPHRD) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHRD); ++ fw->arp.invflags & IPT_INV_ARPHRD) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_ARPHRD); + add_payload(r, offsetof(struct arphdr, ar_hrd), 2, + NFT_PAYLOAD_NETWORK_HEADER); + add_cmp_u16(r, fw->arp.arhrd, op); + } + + if (fw->arp.arpro != 0 || +- fw->arp.invflags & ARPT_INV_ARPPRO) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPPRO); ++ fw->arp.invflags & IPT_INV_PROTO) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_PROTO); + add_payload(r, offsetof(struct arphdr, ar_pro), 2, + NFT_PAYLOAD_NETWORK_HEADER); + add_cmp_u16(r, fw->arp.arpro, op); + } + + if (fw->arp.arhln != 0 || +- fw->arp.invflags & ARPT_INV_ARPHLN) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHLN); ++ fw->arp.invflags & IPT_INV_ARPHLN) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_ARPHLN); + add_proto(r, offsetof(struct arphdr, ar_hln), 1, + fw->arp.arhln, op); + } +@@ -169,15 +169,15 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data) + add_proto(r, offsetof(struct arphdr, ar_pln), 1, 4, NFT_CMP_EQ); + + if (fw->arp.arpop != 0 || +- fw->arp.invflags & ARPT_INV_ARPOP) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPOP); ++ fw->arp.invflags & IPT_INV_ARPOP) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_ARPOP); + add_payload(r, offsetof(struct arphdr, ar_op), 2, + NFT_PAYLOAD_NETWORK_HEADER); + add_cmp_u16(r, fw->arp.arpop, op); + } + + if (need_devaddr(&fw->arp.src_devaddr)) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR); ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_SRCDEVADDR); + add_addr(r, NFT_PAYLOAD_NETWORK_HEADER, + sizeof(struct arphdr), + &fw->arp.src_devaddr.addr, +@@ -188,8 +188,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data) + + if (fw->arp.src.s_addr != 0 || + fw->arp.smsk.s_addr != 0 || +- fw->arp.invflags & ARPT_INV_SRCIP) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP); ++ fw->arp.invflags & IPT_INV_SRCIP) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_SRCIP); + add_addr(r, NFT_PAYLOAD_NETWORK_HEADER, + sizeof(struct arphdr) + fw->arp.arhln, + &fw->arp.src.s_addr, &fw->arp.smsk.s_addr, +@@ -198,7 +198,7 @@ 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); ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_TGTDEVADDR); + add_addr(r, NFT_PAYLOAD_NETWORK_HEADER, + sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr), + &fw->arp.tgt_devaddr.addr, +@@ -208,8 +208,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data) + + if (fw->arp.tgt.s_addr != 0 || + fw->arp.tmsk.s_addr != 0 || +- fw->arp.invflags & ARPT_INV_TGTIP) { +- op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP); ++ fw->arp.invflags & IPT_INV_DSTIP) { ++ op = nft_invflags2cmp(fw->arp.invflags, IPT_INV_DSTIP); + 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, +@@ -240,28 +240,6 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data) + return ret; + } + +-static uint16_t ipt_to_arpt_flags(uint8_t invflags) +-{ +- uint16_t result = 0; +- +- if (invflags & IPT_INV_VIA_IN) +- result |= ARPT_INV_VIA_IN; +- +- if (invflags & IPT_INV_VIA_OUT) +- result |= ARPT_INV_VIA_OUT; +- +- if (invflags & IPT_INV_SRCIP) +- result |= ARPT_INV_SRCIP; +- +- if (invflags & IPT_INV_DSTIP) +- result |= ARPT_INV_TGTIP; +- +- if (invflags & IPT_INV_PROTO) +- result |= ARPT_INV_ARPPRO; +- +- return result; +-} +- + static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, + void *data) + { +@@ -273,7 +251,7 @@ static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, + fw->arp.outiface, fw->arp.outiface_mask, + &flags); + +- fw->arp.invflags |= ipt_to_arpt_flags(flags); ++ fw->arp.invflags |= flags; + } + + static void nft_arp_parse_immediate(const char *jumpto, bool nft_goto, +@@ -330,33 +308,33 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + fw->arp.arhrd = ar_hrd; + fw->arp.arhrd_mask = 0xffff; + if (inv) +- fw->arp.invflags |= ARPT_INV_ARPHRD; ++ fw->arp.invflags |= IPT_INV_ARPHRD; + break; + case offsetof(struct arphdr, ar_pro): + get_cmp_data(e, &ar_pro, sizeof(ar_pro), &inv); + fw->arp.arpro = ar_pro; + fw->arp.arpro_mask = 0xffff; + if (inv) +- fw->arp.invflags |= ARPT_INV_ARPPRO; ++ fw->arp.invflags |= IPT_INV_PROTO; + break; + case offsetof(struct arphdr, ar_op): + get_cmp_data(e, &ar_op, sizeof(ar_op), &inv); + fw->arp.arpop = ar_op; + fw->arp.arpop_mask = 0xffff; + if (inv) +- fw->arp.invflags |= ARPT_INV_ARPOP; ++ fw->arp.invflags |= IPT_INV_ARPOP; + break; + case offsetof(struct arphdr, ar_hln): + get_cmp_data(e, &ar_hln, sizeof(ar_hln), &inv); + fw->arp.arhln = ar_hln; + fw->arp.arhln_mask = 0xff; + if (inv) +- fw->arp.invflags |= ARPT_INV_ARPOP; ++ fw->arp.invflags |= IPT_INV_ARPOP; + break; + default: + if (ctx->payload.offset == sizeof(struct arphdr)) { + if (nft_arp_parse_devaddr(ctx, e, &fw->arp.src_devaddr)) +- fw->arp.invflags |= ARPT_INV_SRCDEVADDR; ++ fw->arp.invflags |= IPT_INV_SRCDEVADDR; + } else if (ctx->payload.offset == sizeof(struct arphdr) + + fw->arp.arhln) { + get_cmp_data(e, &addr, sizeof(addr), &inv); +@@ -371,12 +349,12 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + } + + if (inv) +- fw->arp.invflags |= ARPT_INV_SRCIP; ++ fw->arp.invflags |= IPT_INV_SRCIP; + } else if (ctx->payload.offset == sizeof(struct arphdr) + + fw->arp.arhln + + sizeof(struct in_addr)) { + if (nft_arp_parse_devaddr(ctx, e, &fw->arp.tgt_devaddr)) +- fw->arp.invflags |= ARPT_INV_TGTDEVADDR; ++ fw->arp.invflags |= IPT_INV_TGTDEVADDR; + } else if (ctx->payload.offset == sizeof(struct arphdr) + + fw->arp.arhln + + sizeof(struct in_addr) + +@@ -393,7 +371,7 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + } + + if (inv) +- fw->arp.invflags |= ARPT_INV_TGTIP; ++ fw->arp.invflags |= IPT_INV_DSTIP; + } + break; + } +@@ -448,7 +426,7 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + else strcat(iface, "any"); + } + if (print_iface) { +- printf("%s%s-i %s", sep, fw->arp.invflags & ARPT_INV_VIA_IN ? ++ printf("%s%s-i %s", sep, fw->arp.invflags & IPT_INV_VIA_IN ? + "! " : "", iface); + sep = " "; + } +@@ -466,13 +444,13 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + else strcat(iface, "any"); + } + if (print_iface) { +- printf("%s%s-o %s", sep, fw->arp.invflags & ARPT_INV_VIA_OUT ? ++ printf("%s%s-o %s", sep, fw->arp.invflags & IPT_INV_VIA_OUT ? + "! " : "", iface); + sep = " "; + } + + if (fw->arp.smsk.s_addr != 0L) { +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCIP ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_SRCIP + ? "! " : ""); + if (format & FMT_NUMERIC) + sprintf(buf, "%s", addr_to_dotted(&(fw->arp.src))); +@@ -489,7 +467,7 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + break; + if (i == ARPT_DEV_ADDR_LEN_MAX) + goto after_devsrc; +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCDEVADDR ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_SRCDEVADDR + ? "! " : ""); + printf("--src-mac "); + xtables_print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr, +@@ -498,7 +476,7 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + after_devsrc: + + if (fw->arp.tmsk.s_addr != 0L) { +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTIP ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_DSTIP + ? "! " : ""); + if (format & FMT_NUMERIC) + sprintf(buf, "%s", addr_to_dotted(&(fw->arp.tgt))); +@@ -515,7 +493,7 @@ after_devsrc: + break; + if (i == ARPT_DEV_ADDR_LEN_MAX) + goto after_devdst; +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTDEVADDR ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_TGTDEVADDR + ? "! " : ""); + printf("--dst-mac "); + xtables_print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr, +@@ -525,7 +503,7 @@ after_devsrc: + after_devdst: + + if (fw->arp.arhln_mask != 255 || fw->arp.arhln != 6) { +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_ARPHLN + ? "! " : ""); + printf("--h-length %d", fw->arp.arhln); + if (fw->arp.arhln_mask != 255) +@@ -536,7 +514,7 @@ after_devdst: + if (fw->arp.arpop_mask != 0) { + int tmp = ntohs(fw->arp.arpop); + +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPOP ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_ARPOP + ? "! " : ""); + if (tmp <= NUMOPCODES && !(format & FMT_NUMERIC)) + printf("--opcode %s", arp_opcodes[tmp-1]); +@@ -551,7 +529,7 @@ after_devdst: + if (fw->arp.arhrd_mask != 65535 || fw->arp.arhrd != htons(1)) { + uint16_t tmp = ntohs(fw->arp.arhrd); + +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_ARPHRD + ? "! " : ""); + if (tmp == 1 && !(format & FMT_NUMERIC)) + printf("--h-type %s", "Ethernet"); +@@ -565,7 +543,7 @@ after_devdst: + if (fw->arp.arpro_mask != 0) { + int tmp = ntohs(fw->arp.arpro); + +- printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPPRO ++ printf("%s%s", sep, fw->arp.invflags & IPT_INV_PROTO + ? "! " : ""); + if (tmp == 0x0800 && !(format & FMT_NUMERIC)) + printf("--proto-type %s", "IPv4"); +diff --git a/iptables/nft-arp.h b/iptables/nft-arp.h +index 3411fc3d7c7b3..0d93a31f563b1 100644 +--- a/iptables/nft-arp.h ++++ b/iptables/nft-arp.h +@@ -4,4 +4,11 @@ + extern char *arp_opcodes[]; + #define NUMOPCODES 9 + ++/* define invflags which won't collide with IPT ones */ ++#define IPT_INV_SRCDEVADDR 0x0080 ++#define IPT_INV_TGTDEVADDR 0x0100 ++#define IPT_INV_ARPHLN 0x0200 ++#define IPT_INV_ARPOP 0x0400 ++#define IPT_INV_ARPHRD 0x0800 ++ + #endif +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index c8196f08baa59..3f96cb22c3ec0 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -113,22 +113,22 @@ struct xtables_globals arptables_globals = { + static int inverse_for_options[] = + { + /* -n */ 0, +-/* -s */ ARPT_INV_SRCIP, +-/* -d */ ARPT_INV_TGTIP, ++/* -s */ IPT_INV_SRCIP, ++/* -d */ IPT_INV_DSTIP, + /* -p */ 0, + /* -j */ 0, + /* -v */ 0, + /* -x */ 0, +-/* -i */ ARPT_INV_VIA_IN, +-/* -o */ ARPT_INV_VIA_OUT, ++/* -i */ IPT_INV_VIA_IN, ++/* -o */ IPT_INV_VIA_OUT, + /*--line*/ 0, + /* -c */ 0, +-/* 2 */ ARPT_INV_SRCDEVADDR, +-/* 3 */ ARPT_INV_TGTDEVADDR, +-/* -l */ ARPT_INV_ARPHLN, +-/* 4 */ ARPT_INV_ARPOP, +-/* 5 */ ARPT_INV_ARPHRD, +-/* 6 */ ARPT_INV_ARPPRO, ++/* 2 */ IPT_INV_SRCDEVADDR, ++/* 3 */ IPT_INV_TGTDEVADDR, ++/* -l */ IPT_INV_ARPHLN, ++/* 4 */ IPT_INV_ARPOP, ++/* 5 */ IPT_INV_ARPHRD, ++/* 6 */ IPT_INV_PROTO, + }; + + /***********************************************/ +@@ -903,7 +903,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, + &dmasks, &ndaddrs); + + if ((nsaddrs > 1 || ndaddrs > 1) && +- (cs.arp.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP))) ++ (cs.arp.arp.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) + xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" + " source or destination IP addresses"); + +-- +2.31.1 + diff --git a/SOURCES/0053-nft-arp-Make-use-of-ipv4_addr_to_string.patch b/SOURCES/0053-nft-arp-Make-use-of-ipv4_addr_to_string.patch new file mode 100644 index 0000000..0b98179 --- /dev/null +++ b/SOURCES/0053-nft-arp-Make-use-of-ipv4_addr_to_string.patch @@ -0,0 +1,181 @@ +From 201fd565a1ce44b4af11ce9f245b2fa77c026fed Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 27 Apr 2021 10:02:34 +0200 +Subject: [PATCH] nft-arp: Make use of ipv4_addr_to_string() + +This eliminates quite a bit of redundant code apart from also dropping +use of obsolete function gethostbyaddr(). + +Signed-off-by: Phil Sutter +(cherry picked from commit 1e984079817a3c804eae25dea937d63d18c57a6c) +--- + iptables/nft-arp.c | 99 ++++------------------------------------------ + iptables/xshared.c | 6 +-- + iptables/xshared.h | 3 ++ + 3 files changed, 14 insertions(+), 94 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index ec8147dd58c0d..7c61c31a13c40 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -42,78 +42,6 @@ char *arp_opcodes[] = + "ARP_NAK", + }; + +-static char * +-addr_to_dotted(const struct in_addr *addrp) +-{ +- static char buf[20]; +- const unsigned char *bytep; +- +- bytep = (const unsigned char *) &(addrp->s_addr); +- sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]); +- return buf; +-} +- +-static char * +-addr_to_host(const struct in_addr *addr) +-{ +- struct hostent *host; +- +- if ((host = gethostbyaddr((char *) addr, +- sizeof(struct in_addr), AF_INET)) != NULL) +- return (char *) host->h_name; +- +- return (char *) NULL; +-} +- +-static char * +-addr_to_network(const struct in_addr *addr) +-{ +- struct netent *net; +- +- if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL) +- return (char *) net->n_name; +- +- return (char *) NULL; +-} +- +-static char * +-addr_to_anyname(const struct in_addr *addr) +-{ +- char *name; +- +- if ((name = addr_to_host(addr)) != NULL || +- (name = addr_to_network(addr)) != NULL) +- return name; +- +- return addr_to_dotted(addr); +-} +- +-static char * +-mask_to_dotted(const struct in_addr *mask) +-{ +- int i; +- static char buf[22]; +- u_int32_t maskaddr, bits; +- +- maskaddr = ntohl(mask->s_addr); +- +- if (maskaddr == 0xFFFFFFFFL) +- /* we don't want to see "/32" */ +- return ""; +- +- i = 32; +- bits = 0xFFFFFFFEL; +- while (--i >= 0 && maskaddr != bits) +- bits <<= 1; +- if (i >= 0) +- sprintf(buf, "/%d", i); +- else +- /* mask was not a decent combination of 1's and 0's */ +- snprintf(buf, sizeof(buf), "/%s", addr_to_dotted(mask)); +- +- return buf; +-} +- + static bool need_devaddr(struct arpt_devaddr_info *info) + { + int i; +@@ -403,7 +331,6 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + unsigned int format) + { + const struct arpt_entry *fw = &cs->arp; +- char buf[BUFSIZ]; + char iface[IFNAMSIZ+2]; + const char *sep = ""; + int print_iface = 0; +@@ -450,15 +377,10 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + } + + if (fw->arp.smsk.s_addr != 0L) { +- printf("%s%s", sep, fw->arp.invflags & IPT_INV_SRCIP +- ? "! " : ""); +- if (format & FMT_NUMERIC) +- sprintf(buf, "%s", addr_to_dotted(&(fw->arp.src))); +- else +- sprintf(buf, "%s", addr_to_anyname(&(fw->arp.src))); +- strncat(buf, mask_to_dotted(&(fw->arp.smsk)), +- sizeof(buf) - strlen(buf) - 1); +- printf("-s %s", buf); ++ printf("%s%s-s %s", sep, ++ fw->arp.invflags & IPT_INV_SRCIP ? "! " : "", ++ ipv4_addr_to_string(&fw->arp.src, ++ &fw->arp.smsk, format)); + sep = " "; + } + +@@ -476,15 +398,10 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + after_devsrc: + + if (fw->arp.tmsk.s_addr != 0L) { +- printf("%s%s", sep, fw->arp.invflags & IPT_INV_DSTIP +- ? "! " : ""); +- if (format & FMT_NUMERIC) +- sprintf(buf, "%s", addr_to_dotted(&(fw->arp.tgt))); +- else +- sprintf(buf, "%s", addr_to_anyname(&(fw->arp.tgt))); +- strncat(buf, mask_to_dotted(&(fw->arp.tmsk)), +- sizeof(buf) - strlen(buf) - 1); +- printf("-d %s", buf); ++ printf("%s%s-d %s", sep, ++ fw->arp.invflags & IPT_INV_DSTIP ? "! " : "", ++ ipv4_addr_to_string(&fw->arp.tgt, ++ &fw->arp.tmsk, format)); + sep = " "; + } + +diff --git a/iptables/xshared.c b/iptables/xshared.c +index 16c58914e59a5..e3c8072b5ca96 100644 +--- a/iptables/xshared.c ++++ b/iptables/xshared.c +@@ -546,9 +546,9 @@ void debug_print_argv(struct argv_store *store) + } + #endif + +-static const char *ipv4_addr_to_string(const struct in_addr *addr, +- const struct in_addr *mask, +- unsigned int format) ++const char *ipv4_addr_to_string(const struct in_addr *addr, ++ const struct in_addr *mask, ++ unsigned int format) + { + static char buf[BUFSIZ]; + +diff --git a/iptables/xshared.h b/iptables/xshared.h +index 490b19ade5106..e4015c00e2a35 100644 +--- a/iptables/xshared.h ++++ b/iptables/xshared.h +@@ -200,6 +200,9 @@ void debug_print_argv(struct argv_store *store); + # define debug_print_argv(...) /* nothing */ + #endif + ++const char *ipv4_addr_to_string(const struct in_addr *addr, ++ const struct in_addr *mask, ++ unsigned int format); + void print_ipv4_addresses(const struct ipt_entry *fw, unsigned int format); + void print_ipv6_addresses(const struct ip6t_entry *fw6, unsigned int format); + +-- +2.31.1 + diff --git a/SOURCES/0054-extensions-SECMARK-Implement-revision-1.patch b/SOURCES/0054-extensions-SECMARK-Implement-revision-1.patch new file mode 100644 index 0000000..b271812 --- /dev/null +++ b/SOURCES/0054-extensions-SECMARK-Implement-revision-1.patch @@ -0,0 +1,177 @@ +From 3bd3af273ccfa550ed50ad19d4bcd04a29b88f5b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 29 Apr 2021 15:28:59 +0200 +Subject: [PATCH] extensions: SECMARK: Implement revision 1 + +The changed data structure for communication with kernel allows to +exclude the field 'secid' which is populated on kernel side. Thus +this fixes the formerly always failing extension comparison breaking +rule check and rule delete by content. + +Signed-off-by: Phil Sutter +(cherry picked from commit 616800af0da86d151cb695f1376d5ec6ede6fa72) +--- + extensions/libxt_SECMARK.c | 90 +++++++++++++++++++++------- + extensions/libxt_SECMARK.t | 4 ++ + include/linux/netfilter/xt_SECMARK.h | 6 ++ + 3 files changed, 80 insertions(+), 20 deletions(-) + create mode 100644 extensions/libxt_SECMARK.t + +diff --git a/extensions/libxt_SECMARK.c b/extensions/libxt_SECMARK.c +index 6ba8606355daa..24249bd618ffe 100644 +--- a/extensions/libxt_SECMARK.c ++++ b/extensions/libxt_SECMARK.c +@@ -29,6 +29,13 @@ static const struct xt_option_entry SECMARK_opts[] = { + XTOPT_TABLEEND, + }; + ++static const struct xt_option_entry SECMARK_opts_v1[] = { ++ {.name = "selctx", .id = O_SELCTX, .type = XTTYPE_STRING, ++ .flags = XTOPT_MAND | XTOPT_PUT, ++ XTOPT_POINTER(struct xt_secmark_target_info_v1, secctx)}, ++ XTOPT_TABLEEND, ++}; ++ + static void SECMARK_parse(struct xt_option_call *cb) + { + struct xt_secmark_target_info *info = cb->data; +@@ -37,15 +44,23 @@ static void SECMARK_parse(struct xt_option_call *cb) + info->mode = SECMARK_MODE_SEL; + } + +-static void print_secmark(const struct xt_secmark_target_info *info) ++static void SECMARK_parse_v1(struct xt_option_call *cb) ++{ ++ struct xt_secmark_target_info_v1 *info = cb->data; ++ ++ xtables_option_parse(cb); ++ info->mode = SECMARK_MODE_SEL; ++} ++ ++static void print_secmark(__u8 mode, const char *secctx) + { +- switch (info->mode) { ++ switch (mode) { + case SECMARK_MODE_SEL: +- printf("selctx %s", info->secctx); ++ printf("selctx %s", secctx); + break; +- ++ + default: +- xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode); ++ xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", mode); + } + } + +@@ -56,7 +71,17 @@ static void SECMARK_print(const void *ip, const struct xt_entry_target *target, + (struct xt_secmark_target_info*)(target)->data; + + printf(" SECMARK "); +- print_secmark(info); ++ print_secmark(info->mode, info->secctx); ++} ++ ++static void SECMARK_print_v1(const void *ip, ++ const struct xt_entry_target *target, int numeric) ++{ ++ const struct xt_secmark_target_info_v1 *info = ++ (struct xt_secmark_target_info_v1 *)(target)->data; ++ ++ printf(" SECMARK "); ++ print_secmark(info->mode, info->secctx); + } + + static void SECMARK_save(const void *ip, const struct xt_entry_target *target) +@@ -65,24 +90,49 @@ static void SECMARK_save(const void *ip, const struct xt_entry_target *target) + (struct xt_secmark_target_info*)target->data; + + printf(" --"); +- print_secmark(info); ++ print_secmark(info->mode, info->secctx); + } + +-static struct xtables_target secmark_target = { +- .family = NFPROTO_UNSPEC, +- .name = "SECMARK", +- .version = XTABLES_VERSION, +- .revision = 0, +- .size = XT_ALIGN(sizeof(struct xt_secmark_target_info)), +- .userspacesize = XT_ALIGN(sizeof(struct xt_secmark_target_info)), +- .help = SECMARK_help, +- .print = SECMARK_print, +- .save = SECMARK_save, +- .x6_parse = SECMARK_parse, +- .x6_options = SECMARK_opts, ++static void SECMARK_save_v1(const void *ip, ++ const struct xt_entry_target *target) ++{ ++ const struct xt_secmark_target_info_v1 *info = ++ (struct xt_secmark_target_info_v1 *)target->data; ++ ++ printf(" --"); ++ print_secmark(info->mode, info->secctx); ++} ++ ++static struct xtables_target secmark_tg_reg[] = { ++ { ++ .family = NFPROTO_UNSPEC, ++ .name = "SECMARK", ++ .version = XTABLES_VERSION, ++ .revision = 0, ++ .size = XT_ALIGN(sizeof(struct xt_secmark_target_info)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_secmark_target_info)), ++ .help = SECMARK_help, ++ .print = SECMARK_print, ++ .save = SECMARK_save, ++ .x6_parse = SECMARK_parse, ++ .x6_options = SECMARK_opts, ++ }, ++ { ++ .family = NFPROTO_UNSPEC, ++ .name = "SECMARK", ++ .version = XTABLES_VERSION, ++ .revision = 1, ++ .size = XT_ALIGN(sizeof(struct xt_secmark_target_info_v1)), ++ .userspacesize = XT_ALIGN(offsetof(struct xt_secmark_target_info_v1, secid)), ++ .help = SECMARK_help, ++ .print = SECMARK_print_v1, ++ .save = SECMARK_save_v1, ++ .x6_parse = SECMARK_parse_v1, ++ .x6_options = SECMARK_opts_v1, ++ } + }; + + void _init(void) + { +- xtables_register_target(&secmark_target); ++ xtables_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg)); + } +diff --git a/extensions/libxt_SECMARK.t b/extensions/libxt_SECMARK.t +new file mode 100644 +index 0000000000000..39d4c09348bf4 +--- /dev/null ++++ b/extensions/libxt_SECMARK.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++*security ++-j SECMARK --selctx system_u:object_r:firewalld_exec_t:s0;=;OK ++-j SECMARK;;FAIL +diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h +index 989092bd6274b..31760a286a854 100644 +--- a/include/linux/netfilter/xt_SECMARK.h ++++ b/include/linux/netfilter/xt_SECMARK.h +@@ -19,4 +19,10 @@ struct xt_secmark_target_info { + char secctx[SECMARK_SECCTX_MAX]; + }; + ++struct xt_secmark_target_info_v1 { ++ __u8 mode; ++ char secctx[SECMARK_SECCTX_MAX]; ++ __u32 secid; ++}; ++ + #endif /*_XT_SECMARK_H_target */ +-- +2.31.1 + diff --git a/SOURCES/0055-extensions-sctp-Fix-nftables-translation.patch b/SOURCES/0055-extensions-sctp-Fix-nftables-translation.patch new file mode 100644 index 0000000..5253354 --- /dev/null +++ b/SOURCES/0055-extensions-sctp-Fix-nftables-translation.patch @@ -0,0 +1,80 @@ +From b675a15b70215deab520ef1a8e52edad9129328e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 4 May 2021 16:03:24 +0200 +Subject: [PATCH] extensions: sctp: Fix nftables translation + +If both sport and dport was present, incorrect nft syntax was generated. + +Fixes: defc7bd2bac89 ("extensions: libxt_sctp: Add translation to nft") +Signed-off-by: Phil Sutter +(cherry picked from commit a61282ec6a1697bfb40f19d13a28a74559050167) +--- + extensions/libxt_sctp.c | 10 ++++------ + extensions/libxt_sctp.txlate | 10 +++++----- + 2 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c +index 140de2653b1ef..ee4e99ebf11bf 100644 +--- a/extensions/libxt_sctp.c ++++ b/extensions/libxt_sctp.c +@@ -495,15 +495,13 @@ static int sctp_xlate(struct xt_xlate *xl, + if (!einfo->flags) + return 0; + +- xt_xlate_add(xl, "sctp "); +- + if (einfo->flags & XT_SCTP_SRC_PORTS) { + if (einfo->spts[0] != einfo->spts[1]) +- xt_xlate_add(xl, "sport%s %u-%u", ++ xt_xlate_add(xl, "sctp sport%s %u-%u", + einfo->invflags & XT_SCTP_SRC_PORTS ? " !=" : "", + einfo->spts[0], einfo->spts[1]); + else +- xt_xlate_add(xl, "sport%s %u", ++ xt_xlate_add(xl, "sctp sport%s %u", + einfo->invflags & XT_SCTP_SRC_PORTS ? " !=" : "", + einfo->spts[0]); + space = " "; +@@ -511,11 +509,11 @@ static int sctp_xlate(struct xt_xlate *xl, + + if (einfo->flags & XT_SCTP_DEST_PORTS) { + if (einfo->dpts[0] != einfo->dpts[1]) +- xt_xlate_add(xl, "%sdport%s %u-%u", space, ++ xt_xlate_add(xl, "%ssctp dport%s %u-%u", space, + einfo->invflags & XT_SCTP_DEST_PORTS ? " !=" : "", + einfo->dpts[0], einfo->dpts[1]); + else +- xt_xlate_add(xl, "%sdport%s %u", space, ++ xt_xlate_add(xl, "%ssctp dport%s %u", space, + einfo->invflags & XT_SCTP_DEST_PORTS ? " !=" : "", + einfo->dpts[0]); + } +diff --git a/extensions/libxt_sctp.txlate b/extensions/libxt_sctp.txlate +index 72f4641ab021c..0d6c59e183675 100644 +--- a/extensions/libxt_sctp.txlate ++++ b/extensions/libxt_sctp.txlate +@@ -23,16 +23,16 @@ iptables-translate -A INPUT -p sctp ! --dport 50:56 -j ACCEPT + nft add rule ip filter INPUT sctp dport != 50-56 counter accept + + iptables-translate -A INPUT -p sctp --dport 80 --sport 50 -j ACCEPT +-nft add rule ip filter INPUT sctp sport 50 dport 80 counter accept ++nft add rule ip filter INPUT sctp sport 50 sctp dport 80 counter accept + + iptables-translate -A INPUT -p sctp --dport 80:100 --sport 50 -j ACCEPT +-nft add rule ip filter INPUT sctp sport 50 dport 80-100 counter accept ++nft add rule ip filter INPUT sctp sport 50 sctp dport 80-100 counter accept + + iptables-translate -A INPUT -p sctp --dport 80 --sport 50:55 -j ACCEPT +-nft add rule ip filter INPUT sctp sport 50-55 dport 80 counter accept ++nft add rule ip filter INPUT sctp sport 50-55 sctp dport 80 counter accept + + iptables-translate -A INPUT -p sctp ! --dport 80:100 --sport 50 -j ACCEPT +-nft add rule ip filter INPUT sctp sport 50 dport != 80-100 counter accept ++nft add rule ip filter INPUT sctp sport 50 sctp dport != 80-100 counter accept + + iptables-translate -A INPUT -p sctp --dport 80 ! --sport 50:55 -j ACCEPT +-nft add rule ip filter INPUT sctp sport != 50-55 dport 80 counter accept ++nft add rule ip filter INPUT sctp sport != 50-55 sctp dport 80 counter accept +-- +2.31.1 + diff --git a/SOURCES/0056-extensions-sctp-Translate-chunk-types-option.patch b/SOURCES/0056-extensions-sctp-Translate-chunk-types-option.patch new file mode 100644 index 0000000..9a23f2c --- /dev/null +++ b/SOURCES/0056-extensions-sctp-Translate-chunk-types-option.patch @@ -0,0 +1,159 @@ +From 48f38c4224f31d19176df83539501292fcc6092b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 4 May 2021 16:26:42 +0200 +Subject: [PATCH] extensions: sctp: Translate --chunk-types option + +The translation is not fully complete as it is not possible to map 'any' +match type into nft syntax with a single rule. Also, 'only' match type +translation is a bit poor as it explicitly lists all chunk types that +are supposed to be missing. + +Signed-off-by: Phil Sutter +(cherry picked from commit 5818be177110a09120dd8fe4bd2533acbf8da301) +--- + extensions/libxt_sctp.c | 91 ++++++++++++++++++++++++++++-------- + extensions/libxt_sctp.txlate | 6 +++ + 2 files changed, 78 insertions(+), 19 deletions(-) + +diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c +index ee4e99ebf11bf..5d8ab85cacf42 100644 +--- a/extensions/libxt_sctp.c ++++ b/extensions/libxt_sctp.c +@@ -92,28 +92,29 @@ struct sctp_chunk_names { + const char *name; + unsigned int chunk_type; + const char *valid_flags; ++ const char *nftname; + }; + + /*'ALL' and 'NONE' will be treated specially. */ + static const struct sctp_chunk_names sctp_chunk_names[] +-= { { .name = "DATA", .chunk_type = 0, .valid_flags = "----IUBE"}, +- { .name = "INIT", .chunk_type = 1, .valid_flags = "--------"}, +- { .name = "INIT_ACK", .chunk_type = 2, .valid_flags = "--------"}, +- { .name = "SACK", .chunk_type = 3, .valid_flags = "--------"}, +- { .name = "HEARTBEAT", .chunk_type = 4, .valid_flags = "--------"}, +- { .name = "HEARTBEAT_ACK", .chunk_type = 5, .valid_flags = "--------"}, +- { .name = "ABORT", .chunk_type = 6, .valid_flags = "-------T"}, +- { .name = "SHUTDOWN", .chunk_type = 7, .valid_flags = "--------"}, +- { .name = "SHUTDOWN_ACK", .chunk_type = 8, .valid_flags = "--------"}, +- { .name = "ERROR", .chunk_type = 9, .valid_flags = "--------"}, +- { .name = "COOKIE_ECHO", .chunk_type = 10, .valid_flags = "--------"}, +- { .name = "COOKIE_ACK", .chunk_type = 11, .valid_flags = "--------"}, +- { .name = "ECN_ECNE", .chunk_type = 12, .valid_flags = "--------"}, +- { .name = "ECN_CWR", .chunk_type = 13, .valid_flags = "--------"}, +- { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14, .valid_flags = "-------T"}, +- { .name = "ASCONF", .chunk_type = 193, .valid_flags = "--------"}, +- { .name = "ASCONF_ACK", .chunk_type = 128, .valid_flags = "--------"}, +- { .name = "FORWARD_TSN", .chunk_type = 192, .valid_flags = "--------"}, ++= { { .name = "DATA", .chunk_type = 0, .valid_flags = "----IUBE", .nftname = "data" }, ++ { .name = "INIT", .chunk_type = 1, .valid_flags = "--------", .nftname = "init" }, ++ { .name = "INIT_ACK", .chunk_type = 2, .valid_flags = "--------", .nftname = "init-ack" }, ++ { .name = "SACK", .chunk_type = 3, .valid_flags = "--------", .nftname = "sack" }, ++ { .name = "HEARTBEAT", .chunk_type = 4, .valid_flags = "--------", .nftname = "heartbeat" }, ++ { .name = "HEARTBEAT_ACK", .chunk_type = 5, .valid_flags = "--------", .nftname = "heartbeat-ack" }, ++ { .name = "ABORT", .chunk_type = 6, .valid_flags = "-------T", .nftname = "abort" }, ++ { .name = "SHUTDOWN", .chunk_type = 7, .valid_flags = "--------", .nftname = "shutdown" }, ++ { .name = "SHUTDOWN_ACK", .chunk_type = 8, .valid_flags = "--------", .nftname = "shutdown-ack" }, ++ { .name = "ERROR", .chunk_type = 9, .valid_flags = "--------", .nftname = "error" }, ++ { .name = "COOKIE_ECHO", .chunk_type = 10, .valid_flags = "--------", .nftname = "cookie-echo" }, ++ { .name = "COOKIE_ACK", .chunk_type = 11, .valid_flags = "--------", .nftname = "cookie-ack" }, ++ { .name = "ECN_ECNE", .chunk_type = 12, .valid_flags = "--------", .nftname = "ecne" }, ++ { .name = "ECN_CWR", .chunk_type = 13, .valid_flags = "--------", .nftname = "cwr" }, ++ { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14, .valid_flags = "-------T", .nftname = "shutdown-complete" }, ++ { .name = "ASCONF", .chunk_type = 193, .valid_flags = "--------", .nftname = "asconf" }, ++ { .name = "ASCONF_ACK", .chunk_type = 128, .valid_flags = "--------", .nftname = "asconf-ack" }, ++ { .name = "FORWARD_TSN", .chunk_type = 192, .valid_flags = "--------", .nftname = "forward-tsn" }, + }; + + static void +@@ -485,12 +486,52 @@ static void sctp_save(const void *ip, const struct xt_entry_match *match) + } + } + ++static const char *sctp_xlate_chunk(struct xt_xlate *xl, const char *space, ++ const struct xt_sctp_info *einfo, ++ const struct sctp_chunk_names *scn) ++{ ++ bool inv = einfo->invflags & XT_SCTP_CHUNK_TYPES; ++ const struct xt_sctp_flag_info *flag_info = NULL; ++ int i; ++ ++ if (!scn->nftname) ++ return space; ++ ++ if (!SCTP_CHUNKMAP_IS_SET(einfo->chunkmap, scn->chunk_type)) { ++ if (einfo->chunk_match_type != SCTP_CHUNK_MATCH_ONLY) ++ return space; ++ ++ xt_xlate_add(xl, "%ssctp chunk %s %s", space, ++ scn->nftname, inv ? "exists" : "missing"); ++ return " "; ++ } ++ ++ for (i = 0; i < einfo->flag_count; i++) { ++ if (einfo->flag_info[i].chunktype == scn->chunk_type) { ++ flag_info = &einfo->flag_info[i]; ++ break; ++ } ++ } ++ ++ if (!flag_info) { ++ xt_xlate_add(xl, "%ssctp chunk %s %s", space, ++ scn->nftname, inv ? "missing" : "exists"); ++ return " "; ++ } ++ ++ xt_xlate_add(xl, "%ssctp chunk %s flags & 0x%x %s 0x%x", space, ++ scn->nftname, flag_info->flag_mask, ++ inv ? "!=" : "==", flag_info->flag); ++ ++ return " "; ++} ++ + static int sctp_xlate(struct xt_xlate *xl, + const struct xt_xlate_mt_params *params) + { + const struct xt_sctp_info *einfo = + (const struct xt_sctp_info *)params->match->data; +- char *space = ""; ++ const char *space = ""; + + if (!einfo->flags) + return 0; +@@ -516,6 +557,18 @@ static int sctp_xlate(struct xt_xlate *xl, + xt_xlate_add(xl, "%ssctp dport%s %u", space, + einfo->invflags & XT_SCTP_DEST_PORTS ? " !=" : "", + einfo->dpts[0]); ++ space = " "; ++ } ++ ++ if (einfo->flags & XT_SCTP_CHUNK_TYPES) { ++ int i; ++ ++ if (einfo->chunk_match_type == SCTP_CHUNK_MATCH_ANY) ++ return 0; ++ ++ for (i = 0; i < ARRAY_SIZE(sctp_chunk_names); i++) ++ space = sctp_xlate_chunk(xl, space, einfo, ++ &sctp_chunk_names[i]); + } + + return 1; +diff --git a/extensions/libxt_sctp.txlate b/extensions/libxt_sctp.txlate +index 0d6c59e183675..bb817525db8d8 100644 +--- a/extensions/libxt_sctp.txlate ++++ b/extensions/libxt_sctp.txlate +@@ -36,3 +36,9 @@ nft add rule ip filter INPUT sctp sport 50 sctp dport != 80-100 counter accept + + iptables-translate -A INPUT -p sctp --dport 80 ! --sport 50:55 -j ACCEPT + nft add rule ip filter INPUT sctp sport != 50-55 sctp dport 80 counter accept ++ ++iptables-translate -A INPUT -p sctp --chunk-types all INIT,DATA:iUbE,SACK,ABORT:T -j ACCEPT ++nft add rule ip filter INPUT sctp chunk data flags & 0xf == 0x5 sctp chunk init exists sctp chunk sack exists sctp chunk abort flags & 0x1 == 0x1 counter accept ++ ++iptables-translate -A INPUT -p sctp --chunk-types only SHUTDOWN_COMPLETE -j ACCEPT ++nft add rule ip filter INPUT sctp chunk data missing sctp chunk init missing sctp chunk init-ack missing sctp chunk sack missing sctp chunk heartbeat missing sctp chunk heartbeat-ack missing sctp chunk abort missing sctp chunk shutdown missing sctp chunk shutdown-ack missing sctp chunk error missing sctp chunk cookie-echo missing sctp chunk cookie-ack missing sctp chunk ecne missing sctp chunk cwr missing sctp chunk shutdown-complete exists sctp chunk asconf missing sctp chunk asconf-ack missing sctp chunk forward-tsn missing counter accept +-- +2.31.1 + diff --git a/SOURCES/0057-extensions-SECMARK-Use-a-better-context-in-test-case.patch b/SOURCES/0057-extensions-SECMARK-Use-a-better-context-in-test-case.patch new file mode 100644 index 0000000..6498fa6 --- /dev/null +++ b/SOURCES/0057-extensions-SECMARK-Use-a-better-context-in-test-case.patch @@ -0,0 +1,26 @@ +From 2a45c01c4d3892871b3d3d6b67d10cb62abc561e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 16 Jul 2021 21:51:49 +0200 +Subject: [PATCH] extensions: SECMARK: Use a better context in test case + +RHEL SELinux policies don't allow setting +system_u:object_r:firewalld_exec_t:s0 context. Use one instead which has +'packet_type' attribute (identified via +'seinfo -xt | grep packet_type'). +--- + extensions/libxt_SECMARK.t | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/libxt_SECMARK.t b/extensions/libxt_SECMARK.t +index 39d4c09348bf4..295e7a7244902 100644 +--- a/extensions/libxt_SECMARK.t ++++ b/extensions/libxt_SECMARK.t +@@ -1,4 +1,4 @@ + :INPUT,FORWARD,OUTPUT + *security +--j SECMARK --selctx system_u:object_r:firewalld_exec_t:s0;=;OK ++-j SECMARK --selctx system_u:object_r:ssh_server_packet_t:s0;=;OK + -j SECMARK;;FAIL +-- +2.31.1 + diff --git a/SOURCES/0058-nft-cache-Retry-if-kernel-returns-EINTR.patch b/SOURCES/0058-nft-cache-Retry-if-kernel-returns-EINTR.patch new file mode 100644 index 0000000..09af587 --- /dev/null +++ b/SOURCES/0058-nft-cache-Retry-if-kernel-returns-EINTR.patch @@ -0,0 +1,77 @@ +From 681cb811e4cb8c5f22fd0fae60a3533289657705 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 4 Aug 2021 17:14:05 +0200 +Subject: [PATCH] nft: cache: Retry if kernel returns EINTR + +In case of parallel ruleset updates, recvfrom() calls may return EINTR. +Due to the fact that cache fetches may get triggered while iterating +over cache elements, __nft_build_cache must not restart based on +comparing before and after generation ID like upstream does. Instead, +just retry the recvfrom() calls until they either succeed or return a +different error than EINTR. +--- + iptables/nft-cache.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c +index 9623b463f0dd5..699dc66a95cd1 100644 +--- a/iptables/nft-cache.c ++++ b/iptables/nft-cache.c +@@ -98,9 +98,12 @@ static int fetch_table_cache(struct nft_handle *h) + nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, + NLM_F_DUMP, h->seq); + ++retry: + ret = mnl_talk(h, nlh, nftnl_table_list_cb, list); +- if (ret < 0 && errno == EINTR) ++ if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); ++ goto retry; ++ } + + h->cache->tables = list; + +@@ -275,10 +278,11 @@ static int fetch_set_cache(struct nft_handle *h, + NLM_F_DUMP, h->seq); + } + ++retry: + ret = mnl_talk(h, nlh, nftnl_set_list_cb, &d); + if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); +- return ret; ++ goto retry; + } + + if (t && set) { +@@ -355,9 +359,12 @@ static int fetch_chain_cache(struct nft_handle *h, + h->seq); + } + ++retry: + ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d); +- if (ret < 0 && errno == EINTR) ++ if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); ++ goto retry; ++ } + + return ret; + } +@@ -404,9 +411,12 @@ static int nft_rule_list_update(struct nftnl_chain *c, void *data) + NLM_F_DUMP, h->seq); + nftnl_rule_nlmsg_build_payload(nlh, rule); + ++retry: + ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c); +- if (ret < 0 && errno == EINTR) ++ if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); ++ goto retry; ++ } + + nftnl_rule_free(rule); + +-- +2.32.0 + diff --git a/SPECS/iptables.spec b/SPECS/iptables.spec index 12289e4..71c5f1d 100644 --- a/SPECS/iptables.spec +++ b/SPECS/iptables.spec @@ -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: 17%{?dist}.1 +Release: 20%{?dist} Source: %{url}/files/%{name}-%{version}.tar.bz2 Source1: iptables.init Source2: iptables-config @@ -77,7 +77,21 @@ 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 -Patch44: 0044-nft-cache-Retry-if-kernel-returns-EINTR.patch +Patch44: 0044-xtables-monitor-Fix-ip6tables-rule-printing.patch +Patch45: 0045-xtables-monitor-fix-rule-printing.patch +Patch46: 0046-xtables-monitor-fix-packet-family-protocol.patch +Patch47: 0047-xtables-monitor-print-packet-first.patch +Patch48: 0048-xtables-monitor.patch +Patch49: 0049-nft-Fix-bitwise-expression-avoidance-detection.patch +Patch50: 0050-xtables-translate-Fix-translation-of-odd-netmasks.patch +Patch51: 0051-Eliminate-inet_aton-and-inet_ntoa.patch +Patch52: 0052-xtables-arp-Don-t-use-ARPT_INV_.patch +Patch53: 0053-nft-arp-Make-use-of-ipv4_addr_to_string.patch +Patch54: 0054-extensions-SECMARK-Implement-revision-1.patch +Patch55: 0055-extensions-sctp-Fix-nftables-translation.patch +Patch56: 0056-extensions-sctp-Translate-chunk-types-option.patch +Patch57: 0057-extensions-SECMARK-Use-a-better-context-in-test-case.patch +Patch58: 0058-nft-cache-Retry-if-kernel-returns-EINTR.patch # pf.os: ISC license # iptables-apply: Artistic Licence 2.0 @@ -486,9 +500,25 @@ done %doc %{_mandir}/man8/ebtables*.8* %changelog -* Wed Aug 04 2021 Phil Sutter - 1.8.4-17.1 +* Wed Aug 04 2021 Phil Sutter - 1.8.4-20 +- extensions: SECMARK: Use a better context in test case +- extensions: sctp: Translate --chunk-types option +- extensions: sctp: Fix nftables translation +- extensions: SECMARK: Implement revision 1 - nft: cache: Retry if kernel returns EINTR +* Fri Jun 18 2021 Phil Sutter - 1.8.4-19 +- Fix for rpminspect results + +* Mon May 24 2021 Phil Sutter - 1.8.4-18 +- xtables-translate: Fix translation of odd netmasks +- nft: Fix bitwise expression avoidance detection +- xtables-monitor: 'LL=0x304' is not very convenient, print LOOPBACK instead. +- xtables-monitor: print packet first +- xtables-monitor: fix packet family protocol +- xtables-monitor: fix rule printing +- xtables-monitor: Fix ip6tables rule printing + * Thu Dec 10 2020 Phil Sutter - 1.8.4-17 - extensions: dccp: Fix for DCCP type 'INVALID' - tests: shell: Merge and extend return codes test