diff --git a/SOURCES/0071-netlink-remove-unused-parameter-from-netlink_gen_stm.patch b/SOURCES/0071-netlink-remove-unused-parameter-from-netlink_gen_stm.patch new file mode 100644 index 0000000..d254375 --- /dev/null +++ b/SOURCES/0071-netlink-remove-unused-parameter-from-netlink_gen_stm.patch @@ -0,0 +1,134 @@ +From cf85778a263a34aa2aeee565f3e046693164a097 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Jan 2022 20:37:56 +0100 +Subject: [PATCH] netlink: remove unused parameter from + netlink_gen_stmt_stateful() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594 +Upstream Status: nftables commit 3f3e897f42965 + +commit 3f3e897f429659ff6c8387245d0d4115952a6c31 +Author: Pablo Neira Ayuso +Date: Wed Mar 11 13:02:26 2020 +0100 + + netlink: remove unused parameter from netlink_gen_stmt_stateful() + + Remove context from netlink_gen_stmt_stateful(). + + Signed-off-by: Pablo Neira Ayuso +--- + src/netlink_linearize.c | 36 +++++++++++++----------------------- + 1 file changed, 13 insertions(+), 23 deletions(-) + +diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c +index 28b0e6a..f5c6116 100644 +--- a/src/netlink_linearize.c ++++ b/src/netlink_linearize.c +@@ -780,9 +780,7 @@ static void netlink_gen_objref_stmt(struct netlink_linearize_ctx *ctx, + nftnl_rule_add_expr(ctx->nlr, nle); + } + +-static struct nftnl_expr * +-netlink_gen_connlimit_stmt(struct netlink_linearize_ctx *ctx, +- const struct stmt *stmt) ++static struct nftnl_expr *netlink_gen_connlimit_stmt(const struct stmt *stmt) + { + struct nftnl_expr *nle; + +@@ -795,9 +793,7 @@ netlink_gen_connlimit_stmt(struct netlink_linearize_ctx *ctx, + return nle; + } + +-static struct nftnl_expr * +-netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx, +- const struct stmt *stmt) ++static struct nftnl_expr *netlink_gen_counter_stmt(const struct stmt *stmt) + { + struct nftnl_expr *nle; + +@@ -814,9 +810,7 @@ netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx, + return nle; + } + +-static struct nftnl_expr * +-netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx, +- const struct stmt *stmt) ++static struct nftnl_expr *netlink_gen_limit_stmt(const struct stmt *stmt) + { + struct nftnl_expr *nle; + +@@ -832,9 +826,7 @@ netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx, + return nle; + } + +-static struct nftnl_expr * +-netlink_gen_quota_stmt(struct netlink_linearize_ctx *ctx, +- const struct stmt *stmt) ++static struct nftnl_expr *netlink_gen_quota_stmt(const struct stmt *stmt) + { + struct nftnl_expr *nle; + +@@ -846,19 +838,17 @@ netlink_gen_quota_stmt(struct netlink_linearize_ctx *ctx, + return nle; + } + +-static struct nftnl_expr * +-netlink_gen_stmt_stateful(struct netlink_linearize_ctx *ctx, +- const struct stmt *stmt) ++static struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt) + { + switch (stmt->ops->type) { + case STMT_CONNLIMIT: +- return netlink_gen_connlimit_stmt(ctx, stmt); ++ return netlink_gen_connlimit_stmt(stmt); + case STMT_COUNTER: +- return netlink_gen_counter_stmt(ctx, stmt); ++ return netlink_gen_counter_stmt(stmt); + case STMT_LIMIT: +- return netlink_gen_limit_stmt(ctx, stmt); ++ return netlink_gen_limit_stmt(stmt); + case STMT_QUOTA: +- return netlink_gen_quota_stmt(ctx, stmt); ++ return netlink_gen_quota_stmt(stmt); + default: + BUG("unknown stateful statement type %s\n", stmt->ops->name); + } +@@ -1307,7 +1297,7 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, + + if (stmt->set.stmt) + nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, +- netlink_gen_stmt_stateful(ctx, stmt->set.stmt), 0); ++ netlink_gen_stmt_stateful(stmt->set.stmt), 0); + } + + static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, +@@ -1337,7 +1327,7 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, + + if (stmt->map.stmt) + nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, +- netlink_gen_stmt_stateful(ctx, stmt->map.stmt), 0); ++ netlink_gen_stmt_stateful(stmt->map.stmt), 0); + + nftnl_rule_add_expr(ctx->nlr, nle); + } +@@ -1369,7 +1359,7 @@ static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx, + nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name); + nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id); + nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, +- netlink_gen_stmt_stateful(ctx, stmt->meter.stmt), 0); ++ netlink_gen_stmt_stateful(stmt->meter.stmt), 0); + nftnl_rule_add_expr(ctx->nlr, nle); + } + +@@ -1415,7 +1405,7 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, + case STMT_COUNTER: + case STMT_LIMIT: + case STMT_QUOTA: +- nle = netlink_gen_stmt_stateful(ctx, stmt); ++ nle = netlink_gen_stmt_stateful(stmt); + nftnl_rule_add_expr(ctx->nlr, nle); + break; + case STMT_NOTRACK: +-- +2.31.1 + diff --git a/SOURCES/0072-src-support-for-restoring-element-counters.patch b/SOURCES/0072-src-support-for-restoring-element-counters.patch new file mode 100644 index 0000000..ad66222 --- /dev/null +++ b/SOURCES/0072-src-support-for-restoring-element-counters.patch @@ -0,0 +1,150 @@ +From 0db42cc2d2647ec61441e29445c9f6e0f8946613 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Jan 2022 20:37:56 +0100 +Subject: [PATCH] src: support for restoring element counters + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594 +Upstream Status: nftables commit 1fe6089ddd87e + +commit 1fe6089ddd87ee7869d24c0f8849951220cc9b85 +Author: Pablo Neira Ayuso +Date: Wed Mar 11 13:00:01 2020 +0100 + + src: support for restoring element counters + + This patch allows you to restore counters in dynamic sets: + + table ip test { + set test { + type ipv4_addr + size 65535 + flags dynamic,timeout + timeout 30d + gc-interval 1d + elements = { 192.168.10.13 expires 19d23h52m27s576ms counter packets 51 bytes 17265 } + } + chain output { + type filter hook output priority 0; + update @test { ip saddr } + } + } + + You can also add counters to elements from the control place, ie. + + table ip test { + set test { + type ipv4_addr + size 65535 + elements = { 192.168.2.1 counter packets 75 bytes 19043 } + } + + chain output { + type filter hook output priority filter; policy accept; + ip daddr @test + } + } + + Signed-off-by: Pablo Neira Ayuso +--- + include/netlink.h | 1 + + src/netlink.c | 3 +++ + src/netlink_linearize.c | 2 +- + src/parser_bison.y | 36 +++++++++++++++++++++++++++++++++++- + 4 files changed, 40 insertions(+), 2 deletions(-) + +diff --git a/include/netlink.h b/include/netlink.h +index 88d12ba..059092e 100644 +--- a/include/netlink.h ++++ b/include/netlink.h +@@ -97,6 +97,7 @@ extern void netlink_gen_data(const struct expr *expr, + extern void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder, + unsigned int len, + struct nft_data_linearize *data); ++extern struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt); + + extern struct expr *netlink_alloc_value(const struct location *loc, + const struct nft_data_delinearize *nld); +diff --git a/src/netlink.c b/src/netlink.c +index 64e51e5..825c2cc 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -136,6 +136,9 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, + if (elem->expiration) + nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION, + elem->expiration); ++ if (elem->stmt) ++ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_EXPR, ++ netlink_gen_stmt_stateful(elem->stmt), 0); + if (elem->comment || expr->elem_flags) { + udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); + if (!udbuf) +diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c +index f5c6116..3fa1339 100644 +--- a/src/netlink_linearize.c ++++ b/src/netlink_linearize.c +@@ -838,7 +838,7 @@ static struct nftnl_expr *netlink_gen_quota_stmt(const struct stmt *stmt) + return nle; + } + +-static struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt) ++struct nftnl_expr *netlink_gen_stmt_stateful(const struct stmt *stmt) + { + switch (stmt->ops->type) { + case STMT_CONNLIMIT: +diff --git a/src/parser_bison.y b/src/parser_bison.y +index d38ec30..2cdf8ec 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -3654,7 +3654,7 @@ meter_key_expr_alloc : concat_expr + ; + + set_elem_expr : set_elem_expr_alloc +- | set_elem_expr_alloc set_elem_options ++ | set_elem_expr_alloc set_elem_expr_options + ; + + set_elem_expr_alloc : set_lhs_expr +@@ -3684,6 +3684,40 @@ set_elem_option : TIMEOUT time_spec + } + ; + ++set_elem_expr_options : set_elem_expr_option ++ { ++ $$ = $0; ++ } ++ | set_elem_expr_options set_elem_expr_option ++ ; ++ ++set_elem_expr_option : TIMEOUT time_spec ++ { ++ $0->timeout = $2; ++ } ++ | EXPIRES time_spec ++ { ++ $0->expiration = $2; ++ } ++ | COUNTER ++ { ++ $0->stmt = counter_stmt_alloc(&@$); ++ } ++ | COUNTER PACKETS NUM BYTES NUM ++ { ++ struct stmt *stmt; ++ ++ stmt = counter_stmt_alloc(&@$); ++ stmt->counter.packets = $3; ++ stmt->counter.bytes = $5; ++ $0->stmt = stmt; ++ } ++ | comment_spec ++ { ++ $0->comment = $1; ++ } ++ ; ++ + set_lhs_expr : concat_rhs_expr + | wildcard_expr + ; +-- +2.31.1 + diff --git a/SOURCES/0073-evaluate-attempt-to-set_eval-flag-if-dynamic-updates.patch b/SOURCES/0073-evaluate-attempt-to-set_eval-flag-if-dynamic-updates.patch new file mode 100644 index 0000000..670afae --- /dev/null +++ b/SOURCES/0073-evaluate-attempt-to-set_eval-flag-if-dynamic-updates.patch @@ -0,0 +1,127 @@ +From 48021b277a1ab92480c43e1fa7573b00e33f5212 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 14 Jan 2022 11:39:17 +0100 +Subject: [PATCH] evaluate: attempt to set_eval flag if dynamic updates + requested + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2039594 +Upstream Status: nftables commit 8d443adfcc8c1 +Conflicts: +* Context change due to missing commit 242965f452e64 + ("src: add support for multi-statement in dynamic sets and maps") +* Adjusted test-case: Due to missing kernel commit 7b1394892de8d + ("netfilter: nft_dynset: relax superfluous check on set updates"), + 'update' statement is allowed only if timeout flag is present + +commit 8d443adfcc8c19effd6be9a9c903ee96e374f2e8 +Author: Florian Westphal +Date: Tue Jan 11 12:08:59 2022 +0100 + + evaluate: attempt to set_eval flag if dynamic updates requested + + When passing no upper size limit, the dynset expression forces + an internal 64k upperlimit. + + In some cases, this can result in 'nft -f' to restore the ruleset. + Avoid this by always setting the EVAL flag on a set definition when + we encounter packet-path update attempt in the batch. + + Reported-by: Yi Chen + Suggested-by: Pablo Neira Ayuso + Signed-off-by: Florian Westphal +--- + src/evaluate.c | 11 +++++++ + .../testcases/sets/dumps/dynset_missing.nft | 12 +++++++ + tests/shell/testcases/sets/dynset_missing | 32 +++++++++++++++++++ + 3 files changed, 55 insertions(+) + create mode 100644 tests/shell/testcases/sets/dumps/dynset_missing.nft + create mode 100755 tests/shell/testcases/sets/dynset_missing + +diff --git a/src/evaluate.c b/src/evaluate.c +index 00ec20b..9381f23 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -3076,6 +3076,8 @@ static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt) + + static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt) + { ++ struct set *this_set; ++ + expr_set_context(&ctx->ectx, NULL, 0); + if (expr_evaluate(ctx, &stmt->set.set) < 0) + return -1; +@@ -3103,6 +3105,15 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt) + "meter statement must be stateful"); + } + ++ this_set = stmt->set.set->set; ++ ++ /* Make sure EVAL flag is set on set definition so that kernel ++ * picks a set that allows updates from the packet path. ++ * ++ * Alternatively we could error out in case 'flags dynamic' was ++ * not given, but we can repair this here. ++ */ ++ this_set->flags |= NFT_SET_EVAL; + return 0; + } + +diff --git a/tests/shell/testcases/sets/dumps/dynset_missing.nft b/tests/shell/testcases/sets/dumps/dynset_missing.nft +new file mode 100644 +index 0000000..fdb1b97 +--- /dev/null ++++ b/tests/shell/testcases/sets/dumps/dynset_missing.nft +@@ -0,0 +1,12 @@ ++table ip test { ++ set dlist { ++ type ipv4_addr ++ size 65535 ++ flags dynamic,timeout ++ } ++ ++ chain output { ++ type filter hook output priority filter; policy accept; ++ udp dport 1234 update @dlist { ip daddr } counter packets 0 bytes 0 ++ } ++} +diff --git a/tests/shell/testcases/sets/dynset_missing b/tests/shell/testcases/sets/dynset_missing +new file mode 100755 +index 0000000..89afcd5 +--- /dev/null ++++ b/tests/shell/testcases/sets/dynset_missing +@@ -0,0 +1,32 @@ ++#!/bin/bash ++ ++set -e ++ ++$NFT -f /dev/stdin < $tmpfile ++ ++# this restore works, because set is still the rhash backend. ++$NFT -f $tmpfile # success ++$NFT flush ruleset ++ ++# fails without commit 'attempt to set_eval flag if dynamic updates requested', ++# because set in $tmpfile has 'size x' but no 'flags dynamic'. ++$NFT -f $tmpfile +-- +2.31.1 + diff --git a/SOURCES/0074-evaluate-fix-inet-nat-with-no-layer-3-info.patch b/SOURCES/0074-evaluate-fix-inet-nat-with-no-layer-3-info.patch new file mode 100644 index 0000000..c9fae43 --- /dev/null +++ b/SOURCES/0074-evaluate-fix-inet-nat-with-no-layer-3-info.patch @@ -0,0 +1,49 @@ +From 1fe92af5a03608b94e8e1e2ff26e24adfe2ea09a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 21 Jan 2022 12:35:39 +0100 +Subject: [PATCH] evaluate: fix inet nat with no layer 3 info + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2030773 +Upstream Status: nftables commit 9a36033ce5063 + +commit 9a36033ce50638a403d1421935cdd1287ee5de6b +Author: Pablo Neira Ayuso +Date: Tue Jul 20 18:59:44 2021 +0200 + + evaluate: fix inet nat with no layer 3 info + + nft currently reports: + + Error: Could not process rule: Protocol error + add rule inet x y meta l4proto tcp dnat to :80 + ^^^^ + + default to NFPROTO_INET family, otherwise kernel bails out EPROTO when + trying to load the conntrack helper. + + Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1428 + Signed-off-by: Pablo Neira Ayuso +--- + src/evaluate.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/evaluate.c b/src/evaluate.c +index 9381f23..e495faf 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -2757,9 +2757,10 @@ static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt) + stmt->nat.family = ctx->pctx.family; + return 0; + case NFPROTO_INET: +- if (!stmt->nat.addr) ++ if (!stmt->nat.addr) { ++ stmt->nat.family = NFPROTO_INET; + return 0; +- ++ } + if (stmt->nat.family != NFPROTO_UNSPEC) + return 0; + +-- +2.31.1 + diff --git a/SOURCES/0075-tests-py-add-dnat-to-port-without-defining-destinati.patch b/SOURCES/0075-tests-py-add-dnat-to-port-without-defining-destinati.patch new file mode 100644 index 0000000..f4e0e5e --- /dev/null +++ b/SOURCES/0075-tests-py-add-dnat-to-port-without-defining-destinati.patch @@ -0,0 +1,86 @@ +From eeba2cd956485d3059dabf86a7ad8dd59ee682dd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 4 Feb 2022 14:18:44 +0100 +Subject: [PATCH] tests: py: add dnat to port without defining destination + address + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2030773 +Upstream Status: nftables commit 0f27e258b37a5 +Conflicts: Context changes due to missing commit ae1d822630e6d + ("src: context tracking for multiple transport protocols") + +commit 0f27e258b37a592233d6ad5381cd1fae65e57514 +Author: Pablo Neira Ayuso +Date: Thu Jul 22 17:43:56 2021 +0200 + + tests: py: add dnat to port without defining destination address + + Add a test to cover dnat to port without destination address. + + Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1428 + Signed-off-by: Pablo Neira Ayuso +--- + tests/py/inet/dnat.t | 1 + + tests/py/inet/dnat.t.json | 20 ++++++++++++++++++++ + tests/py/inet/dnat.t.payload | 8 ++++++++ + 3 files changed, 29 insertions(+) + +diff --git a/tests/py/inet/dnat.t b/tests/py/inet/dnat.t +index fcdf943..6beceda 100644 +--- a/tests/py/inet/dnat.t ++++ b/tests/py/inet/dnat.t +@@ -6,6 +6,7 @@ iifname "foo" tcp dport 80 redirect to :8080;ok + + iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2;ok + iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443;ok ++meta l4proto tcp dnat to :80;ok;meta l4proto 6 dnat to :80 + + dnat ip to ct mark map { 0x00000014 : 1.2.3.4};ok + dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4};ok +diff --git a/tests/py/inet/dnat.t.json b/tests/py/inet/dnat.t.json +index ac6dac6..f88e9cf 100644 +--- a/tests/py/inet/dnat.t.json ++++ b/tests/py/inet/dnat.t.json +@@ -164,3 +164,23 @@ + } + ] + ++# meta l4proto tcp dnat to :80 ++[ ++ { ++ "match": { ++ "left": { ++ "meta": { ++ "key": "l4proto" ++ } ++ }, ++ "op": "==", ++ "right": 6 ++ } ++ }, ++ { ++ "dnat": { ++ "port": 80 ++ } ++ } ++] ++ +diff --git a/tests/py/inet/dnat.t.payload b/tests/py/inet/dnat.t.payload +index b81caf7..6d8569d 100644 +--- a/tests/py/inet/dnat.t.payload ++++ b/tests/py/inet/dnat.t.payload +@@ -52,3 +52,11 @@ inet test-inet prerouting + [ payload load 4b @ network header + 16 => reg 9 ] + [ lookup reg 1 set __map%d dreg 1 ] + [ nat dnat ip addr_min reg 1 addr_max reg 0 ] ++ ++# meta l4proto tcp dnat to :80 ++inet ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x00000006 ] ++ [ immediate reg 1 0x00005000 ] ++ [ nat dnat inet proto_min reg 1 flags 0x2 ] ++ +-- +2.31.1 + diff --git a/SOURCES/0076-mnl-do-not-build-nftnl_set-element-list.patch b/SOURCES/0076-mnl-do-not-build-nftnl_set-element-list.patch new file mode 100644 index 0000000..9e9c18d --- /dev/null +++ b/SOURCES/0076-mnl-do-not-build-nftnl_set-element-list.patch @@ -0,0 +1,214 @@ +From bd940a4efd2b5897f8a8e58ec7733417b3710e1e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 8 Dec 2021 13:28:49 +0100 +Subject: [PATCH] mnl: do not build nftnl_set element list + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2047821 +Upstream Status: nftables commit b4b234f5a29e8 +Conflicts: Context change due to missing commit 66746e7dedeb0 + ("src: support for nat with interval concatenation"). + +commit b4b234f5a29e819045679acd95820a7457d4d7de +Author: Pablo Neira Ayuso +Date: Thu Nov 4 12:53:11 2021 +0100 + + mnl: do not build nftnl_set element list + + Do not call alloc_setelem_cache() to build the set element list in + nftnl_set. Instead, translate one single set element expression to + nftnl_set_elem object at a time and use this object to build the netlink + header. + + Using a huge test set containing 1.1 million element blocklist, this + patch is reducing userspace memory consumption by 40%. + + Signed-off-by: Pablo Neira Ayuso +--- + include/netlink.h | 2 + + src/mnl.c | 112 ++++++++++++++++++++++++++++++++++++---------- + src/netlink.c | 4 +- + 3 files changed, 93 insertions(+), 25 deletions(-) + +diff --git a/include/netlink.h b/include/netlink.h +index 059092e..3443582 100644 +--- a/include/netlink.h ++++ b/include/netlink.h +@@ -56,6 +56,8 @@ struct netlink_ctx { + + extern struct nftnl_expr *alloc_nft_expr(const char *name); + extern void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls); ++struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, ++ const struct expr *expr); + + extern struct nftnl_table *netlink_table_alloc(const struct nlmsghdr *nlh); + extern struct nftnl_chain *netlink_chain_alloc(const struct nlmsghdr *nlh); +diff --git a/src/mnl.c b/src/mnl.c +index 23341e6..44cf1a4 100644 +--- a/src/mnl.c ++++ b/src/mnl.c +@@ -1201,33 +1201,102 @@ static int set_elem_cb(const struct nlmsghdr *nlh, void *data) + return MNL_CB_OK; + } + +-static int mnl_nft_setelem_batch(struct nftnl_set *nls, ++static bool mnl_nft_attr_nest_overflow(struct nlmsghdr *nlh, ++ const struct nlattr *from, ++ const struct nlattr *to) ++{ ++ int len = (void *)to + to->nla_len - (void *)from; ++ ++ /* The attribute length field is 16 bits long, thus the maximum payload ++ * that an attribute can convey is UINT16_MAX. In case of overflow, ++ * discard the last attribute that did not fit into the nest. ++ */ ++ if (len > UINT16_MAX) { ++ nlh->nlmsg_len -= to->nla_len; ++ return true; ++ } ++ return false; ++} ++ ++static void netlink_dump_setelem(const struct nftnl_set_elem *nlse, ++ struct netlink_ctx *ctx) ++{ ++ FILE *fp = ctx->nft->output.output_fp; ++ char buf[4096]; ++ ++ if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp) ++ return; ++ ++ nftnl_set_elem_snprintf(buf, sizeof(buf), nlse, NFTNL_OUTPUT_DEFAULT, 0); ++ fprintf(fp, "\t%s", buf); ++} ++ ++static void netlink_dump_setelem_done(struct netlink_ctx *ctx) ++{ ++ FILE *fp = ctx->nft->output.output_fp; ++ ++ if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp) ++ return; ++ ++ fprintf(fp, "\n"); ++} ++ ++static int mnl_nft_setelem_batch(const struct nftnl_set *nls, + struct nftnl_batch *batch, + enum nf_tables_msg_types cmd, +- unsigned int flags, uint32_t seqnum) ++ unsigned int flags, uint32_t seqnum, ++ const struct expr *set, ++ struct netlink_ctx *ctx) + { ++ struct nlattr *nest1, *nest2; ++ struct nftnl_set_elem *nlse; + struct nlmsghdr *nlh; +- struct nftnl_set_elems_iter *iter; +- int ret; +- +- iter = nftnl_set_elems_iter_create(nls); +- if (iter == NULL) +- memory_allocation_error(); ++ struct expr *expr = NULL; ++ int i = 0; + + if (cmd == NFT_MSG_NEWSETELEM) + flags |= NLM_F_CREATE; + +- while (nftnl_set_elems_iter_cur(iter)) { +- nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), cmd, +- nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), +- flags, seqnum); +- ret = nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter); +- mnl_nft_batch_continue(batch); +- if (ret <= 0) +- break; ++ if (set) ++ expr = list_first_entry(&set->expressions, struct expr, list); ++ ++next: ++ nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), cmd, ++ nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), ++ flags, seqnum); ++ ++ if (nftnl_set_is_set(nls, NFTNL_SET_TABLE)) { ++ mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, ++ nftnl_set_get_str(nls, NFTNL_SET_TABLE)); ++ } ++ if (nftnl_set_is_set(nls, NFTNL_SET_NAME)) { ++ mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, ++ nftnl_set_get_str(nls, NFTNL_SET_NAME)); + } ++ if (nftnl_set_is_set(nls, NFTNL_SET_ID)) { ++ mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, ++ htonl(nftnl_set_get_u32(nls, NFTNL_SET_ID))); ++ } ++ ++ if (!set || list_empty(&set->expressions)) ++ return 0; + +- nftnl_set_elems_iter_destroy(iter); ++ assert(expr); ++ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS); ++ list_for_each_entry_from(expr, &set->expressions, list) { ++ nlse = alloc_nftnl_setelem(set, expr); ++ nest2 = nftnl_set_elem_nlmsg_build(nlh, nlse, ++i); ++ netlink_dump_setelem(nlse, ctx); ++ nftnl_set_elem_free(nlse); ++ if (mnl_nft_attr_nest_overflow(nlh, nest1, nest2)) { ++ mnl_attr_nest_end(nlh, nest1); ++ mnl_nft_batch_continue(batch); ++ goto next; ++ } ++ } ++ mnl_attr_nest_end(nlh, nest1); ++ mnl_nft_batch_continue(batch); ++ netlink_dump_setelem_done(ctx); + + return 0; + } +@@ -1249,11 +1318,10 @@ int mnl_nft_setelem_add(struct netlink_ctx *ctx, const struct set *set, + if (h->set_id) + nftnl_set_set_u32(nls, NFTNL_SET_ID, h->set_id); + +- alloc_setelem_cache(expr, nls); + netlink_dump_set(nls, ctx); + +- err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_NEWSETELEM, flags, +- ctx->seqnum); ++ err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_NEWSETELEM, ++ flags, ctx->seqnum, expr, ctx); + nftnl_set_free(nls); + + return err; +@@ -1306,12 +1374,10 @@ int mnl_nft_setelem_del(struct netlink_ctx *ctx, const struct cmd *cmd) + else if (h->handle.id) + nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id); + +- if (cmd->expr) +- alloc_setelem_cache(cmd->expr, nls); + netlink_dump_set(nls, ctx); + + err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_DELSETELEM, 0, +- ctx->seqnum); ++ ctx->seqnum, cmd->expr, ctx); + nftnl_set_free(nls); + + return err; +diff --git a/src/netlink.c b/src/netlink.c +index 825c2cc..f8c97d0 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -95,8 +95,8 @@ struct nftnl_expr *alloc_nft_expr(const char *name) + return nle; + } + +-static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, +- const struct expr *expr) ++struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set, ++ const struct expr *expr) + { + const struct expr *elem, *data; + struct nftnl_set_elem *nlse; +-- +2.31.1 + diff --git a/SPECS/nftables.spec b/SPECS/nftables.spec index c449e23..1462bc8 100644 --- a/SPECS/nftables.spec +++ b/SPECS/nftables.spec @@ -1,5 +1,6 @@ %define rpmversion 0.9.3 -%define specrelease 24 +%define specrelease 25 +%define libnftnl_ver 1.1.5-5 Name: nftables Version: %{rpmversion} @@ -87,6 +88,12 @@ Patch67: 0067-segtree-Fix-segfault-when-restoring-a-huge-interval-.pa Patch68: 0068-tests-cover-baecd1cf2685-segtree-Fix-segfault-when-r.patch Patch69: 0069-tests-shell-NFT-needs-to-be-invoked-unquoted.patch Patch70: 0070-tests-shell-better-parameters-for-the-interval-stack.patch +Patch71: 0071-netlink-remove-unused-parameter-from-netlink_gen_stm.patch +Patch72: 0072-src-support-for-restoring-element-counters.patch +Patch73: 0073-evaluate-attempt-to-set_eval-flag-if-dynamic-updates.patch +Patch74: 0074-evaluate-fix-inet-nat-with-no-layer-3-info.patch +Patch75: 0075-tests-py-add-dnat-to-port-without-defining-destinati.patch +Patch76: 0076-mnl-do-not-build-nftnl_set-element-list.patch BuildRequires: autogen BuildRequires: autoconf @@ -98,14 +105,14 @@ BuildRequires: bison BuildRequires: libmnl-devel BuildRequires: gmp-devel BuildRequires: readline-devel -BuildRequires: pkgconfig(libnftnl) >= 1.1.5-3 +BuildRequires: pkgconfig(libnftnl) >= %{libnftnl_ver} BuildRequires: systemd BuildRequires: asciidoc BuildRequires: iptables-devel BuildRequires: jansson-devel BuildRequires: python3-devel -Requires: libnftnl >= 1.1.5-3 +Requires: libnftnl >= %{libnftnl_ver} %description Netfilter Tables userspace utilities. @@ -203,6 +210,14 @@ touch -r %{SOURCE2} $RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py %{python3_sitelib}/nftables/ %changelog +* Fri Feb 04 2022 Phil Sutter [0.9.3-25.el8] +- mnl: do not build nftnl_set element list (Phil Sutter) [2047821] +- tests: py: add dnat to port without defining destination address (Phil Sutter) [2030773] +- evaluate: fix inet nat with no layer 3 info (Phil Sutter) [2030773] +- evaluate: attempt to set_eval flag if dynamic updates requested (Phil Sutter) [2039594] +- src: support for restoring element counters (Phil Sutter) [2039594] +- netlink: remove unused parameter from netlink_gen_stmt_stateful() (Phil Sutter) [2039594] + * Wed Dec 08 2021 Phil Sutter [0.9.3-24.el8] - tests: shell: better parameters for the interval stack overflow test (Phil Sutter) [1908127] - tests: shell: $NFT needs to be invoked unquoted (Phil Sutter) [1908127]