diff --git a/SOURCES/0001-Add-support-for-table-s-persist-flag.patch b/SOURCES/0001-Add-support-for-table-s-persist-flag.patch new file mode 100644 index 0000000..3dca01e --- /dev/null +++ b/SOURCES/0001-Add-support-for-table-s-persist-flag.patch @@ -0,0 +1,337 @@ +From 450520649ac5ac6f983b40e15e54863aab9d5bd7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 14 Jun 2024 18:30:55 +0200 +Subject: [PATCH] Add support for table's persist flag + +JIRA: https://issues.redhat.com/browse/RHEL-32122 +Upstream Status: nftables commit 4955ae1a81b73f9a61b7fbf1a73e11544513548e +Conflicts: +- Adjusted to missing commit ffd6b4790a728 + ("src: add free_const() and use it instead of xfree()") + +commit 4955ae1a81b73f9a61b7fbf1a73e11544513548e +Author: Phil Sutter +Date: Fri Dec 15 01:10:39 2023 +0100 + + Add support for table's persist flag + + Bison parser lacked support for passing multiple flags, JSON parser + did not support table flags at all. + + Document also 'owner' flag (and describe their relationship in nft.8. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + doc/libnftables-json.adoc | 11 ++++- + doc/nft.txt | 9 ++++ + include/rule.h | 4 +- + src/parser_bison.y | 35 +++++++++------ + src/parser_json.c | 49 ++++++++++++++++++++- + src/rule.c | 12 +++++ + tests/shell/features/table_flag_persist.nft | 3 ++ + tests/shell/testcases/owner/0002-persist | 36 +++++++++++++++ + 8 files changed, 142 insertions(+), 17 deletions(-) + create mode 100644 tests/shell/features/table_flag_persist.nft + create mode 100755 tests/shell/testcases/owner/0002-persist + +diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc +index 3e6e1db..0e424c2 100644 +--- a/doc/libnftables-json.adoc ++++ b/doc/libnftables-json.adoc +@@ -202,12 +202,19 @@ Rename a chain. The new name is expected in a dedicated property named + + === TABLE + [verse] ++____ + *{ "table": { + "family":* 'STRING'*, + "name":* 'STRING'*, +- "handle":* 'NUMBER' ++ "handle":* 'NUMBER'*, ++ "flags":* 'TABLE_FLAGS' + *}}* + ++'TABLE_FLAGS' := 'TABLE_FLAG' | *[* 'TABLE_FLAG_LIST' *]* ++'TABLE_FLAG_LIST' := 'TABLE_FLAG' [*,* 'TABLE_FLAG_LIST' ] ++'TABLE_FLAG' := *"dormant"* | *"owner"* | *"persist"* ++____ ++ + This object describes a table. + + *family*:: +@@ -217,6 +224,8 @@ This object describes a table. + *handle*:: + The table's handle. In input, it is used only in *delete* command as + alternative to *name*. ++*flags*:: ++ The table's flags. + + === CHAIN + [verse] +diff --git a/doc/nft.txt b/doc/nft.txt +index b08e32f..dba1b60 100644 +--- a/doc/nft.txt ++++ b/doc/nft.txt +@@ -343,8 +343,17 @@ return an error. + |Flag | Description + |dormant | + table is not evaluated any more (base chains are unregistered). ++|owner | ++table is owned by the creating process. ++|persist | ++table shall outlive the owning process. + |================= + ++Creating a table with flag *owner* excludes other processes from manipulating ++it or its contents. By default, it will be removed when the process exits. ++Setting flag *persist* will prevent this and the resulting orphaned table will ++accept a new owner, e.g. a restarting daemon maintaining the table. ++ + .*Add, change, delete a table* + --------------------------------------- + # start nft in interactive mode +diff --git a/include/rule.h b/include/rule.h +index 6236d29..a8bb11f 100644 +--- a/include/rule.h ++++ b/include/rule.h +@@ -130,10 +130,12 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier); + enum table_flags { + TABLE_F_DORMANT = (1 << 0), + TABLE_F_OWNER = (1 << 1), ++ TABLE_F_PERSIST = (1 << 2), + }; +-#define TABLE_FLAGS_MAX 2 ++#define TABLE_FLAGS_MAX 3 + + const char *table_flag_name(uint32_t flag); ++unsigned int parse_table_flag(const char *name); + + /** + * struct table - nftables table +diff --git a/src/parser_bison.y b/src/parser_bison.y +index c517dc3..5ced6e1 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -720,6 +720,8 @@ int nft_lex(void *, void *, void *); + %type rule rule_alloc + %destructor { rule_free($$); } rule + ++%type table_flags table_flag ++ + %type set_flag_list set_flag + + %type set_policy_spec +@@ -1874,20 +1876,9 @@ table_block_alloc : /* empty */ + } + ; + +-table_options : FLAGS STRING ++table_options : FLAGS table_flags + { +- if (strcmp($2, "dormant") == 0) { +- $0->flags |= TABLE_F_DORMANT; +- xfree($2); +- } else if (strcmp($2, "owner") == 0) { +- $
0->flags |= TABLE_F_OWNER; +- xfree($2); +- } else { +- erec_queue(error(&@2, "unknown table option %s", $2), +- state->msgs); +- xfree($2); +- YYERROR; +- } ++ $
0->flags |= $2; + } + | comment_spec + { +@@ -1899,6 +1890,24 @@ table_options : FLAGS STRING + } + ; + ++table_flags : table_flag ++ | table_flags COMMA table_flag ++ { ++ $$ = $1 | $3; ++ } ++ ; ++table_flag : STRING ++ { ++ $$ = parse_table_flag($1); ++ xfree($1); ++ if ($$ == 0) { ++ erec_queue(error(&@1, "unknown table option %s", $1), ++ state->msgs); ++ YYERROR; ++ } ++ } ++ ; ++ + table_block : /* empty */ { $$ = $
-1; } + | table_block common_block + | table_block stmt_separator +diff --git a/src/parser_json.c b/src/parser_json.c +index 199241a..9e5b656 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -2941,6 +2941,45 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) + return NULL; + } + ++static int json_parse_table_flags(struct json_ctx *ctx, json_t *root, ++ enum table_flags *flags) ++{ ++ json_t *tmp, *tmp2; ++ size_t index; ++ int flag; ++ ++ if (json_unpack(root, "{s:o}", "flags", &tmp)) ++ return 0; ++ ++ if (json_is_string(tmp)) { ++ flag = parse_table_flag(json_string_value(tmp)); ++ if (flag) { ++ *flags = flag; ++ return 0; ++ } ++ json_error(ctx, "Invalid table flag '%s'.", ++ json_string_value(tmp)); ++ return 1; ++ } ++ if (!json_is_array(tmp)) { ++ json_error(ctx, "Unexpected table flags value."); ++ return 1; ++ } ++ json_array_foreach(tmp, index, tmp2) { ++ if (json_is_string(tmp2)) { ++ flag = parse_table_flag(json_string_value(tmp2)); ++ ++ if (flag) { ++ *flags |= flag; ++ continue; ++ } ++ } ++ json_error(ctx, "Invalid table flag at index %zu.", index); ++ return 1; ++ } ++ return 0; ++} ++ + static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, + enum cmd_ops op, enum cmd_obj obj) + { +@@ -2949,6 +2988,7 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, + .table.location = *int_loc, + }; + struct table *table = NULL; ++ enum table_flags flags = 0; + + if (json_unpack_err(ctx, root, "{s:s}", + "family", &family)) +@@ -2959,6 +2999,9 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, + return NULL; + + json_unpack(root, "{s:s}", "comment", &comment); ++ if (json_parse_table_flags(ctx, root, &flags)) ++ return NULL; ++ + } else if (op == CMD_DELETE && + json_unpack(root, "{s:s}", "name", &h.table.name) && + json_unpack(root, "{s:I}", "handle", &h.handle.id)) { +@@ -2972,10 +3015,12 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, + if (h.table.name) + h.table.name = xstrdup(h.table.name); + +- if (comment) { ++ if (comment || flags) { + table = table_alloc(); + handle_merge(&table->handle, &h); +- table->comment = xstrdup(comment); ++ if (comment) ++ table->comment = xstrdup(comment); ++ table->flags = flags; + } + + if (op == CMD_ADD) +diff --git a/src/rule.c b/src/rule.c +index 739b7a5..a0e151d 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -1208,6 +1208,7 @@ struct table *table_lookup_fuzzy(const struct handle *h, + static const char *table_flags_name[TABLE_FLAGS_MAX] = { + "dormant", + "owner", ++ "persist", + }; + + const char *table_flag_name(uint32_t flag) +@@ -1218,6 +1219,17 @@ const char *table_flag_name(uint32_t flag) + return table_flags_name[flag]; + } + ++unsigned int parse_table_flag(const char *name) ++{ ++ int i; ++ ++ for (i = 0; i < TABLE_FLAGS_MAX; i++) { ++ if (!strcmp(name, table_flags_name[i])) ++ return 1 << i; ++ } ++ return 0; ++} ++ + static void table_print_flags(const struct table *table, const char **delim, + struct output_ctx *octx) + { +diff --git a/tests/shell/features/table_flag_persist.nft b/tests/shell/features/table_flag_persist.nft +new file mode 100644 +index 0000000..0da3e6d +--- /dev/null ++++ b/tests/shell/features/table_flag_persist.nft +@@ -0,0 +1,3 @@ ++table t { ++ flags persist; ++} +diff --git a/tests/shell/testcases/owner/0002-persist b/tests/shell/testcases/owner/0002-persist +new file mode 100755 +index 0000000..cf4b8f1 +--- /dev/null ++++ b/tests/shell/testcases/owner/0002-persist +@@ -0,0 +1,36 @@ ++#!/bin/bash ++ ++# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_owner) ++# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_persist) ++ ++die() { ++ echo "$@" ++ exit 1 ++} ++ ++$NFT -f - < +Date: Tue, 2 Jul 2024 16:41:22 +0200 +Subject: [PATCH] cache: Always set NFT_CACHE_TERSE for list cmd with --terse + +JIRA: https://issues.redhat.com/browse/RHEL-45633 +Upstream Status: nftables commit cd4e947032a57a585b1a457ce03f546afc7ba033 + +commit cd4e947032a57a585b1a457ce03f546afc7ba033 +Author: Phil Sutter +Date: Thu Feb 8 02:10:48 2024 +0100 + + cache: Always set NFT_CACHE_TERSE for list cmd with --terse + + This fixes at least 'nft -t list table ...' and 'nft -t list set ...'. + + Note how --terse handling for 'list sets/maps' remains in place since + setting NFT_CACHE_TERSE does not fully undo NFT_CACHE_SETELEM: setting + both enables fetching of anonymous sets which is pointless for that + command. + + Reported-by: anton.khazan@gmail.com + Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1735 + Suggested-by: Pablo Neira Ayuso + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + src/cache.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 4e89fe1..0ac0f7c 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -230,8 +230,6 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd, + } + if (filter->list.table && filter->list.set) + flags |= NFT_CACHE_TABLE | NFT_CACHE_SET | NFT_CACHE_SETELEM; +- else if (nft_output_terse(&nft->output)) +- flags |= NFT_CACHE_FULL | NFT_CACHE_TERSE; + else + flags |= NFT_CACHE_FULL; + break; +@@ -257,17 +255,15 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd, + flags |= NFT_CACHE_TABLE | NFT_CACHE_FLOWTABLE; + break; + case CMD_OBJ_RULESET: +- if (nft_output_terse(&nft->output)) +- flags |= NFT_CACHE_FULL | NFT_CACHE_TERSE; +- else +- flags |= NFT_CACHE_FULL; +- break; + default: + flags |= NFT_CACHE_FULL; + break; + } + flags |= NFT_CACHE_REFRESH; + ++ if (nft_output_terse(&nft->output)) ++ flags |= NFT_CACHE_TERSE; ++ + return flags; + } + diff --git a/SPECS/nftables.spec b/SPECS/nftables.spec index dc19dc9..e31cf82 100644 --- a/SPECS/nftables.spec +++ b/SPECS/nftables.spec @@ -1,5 +1,5 @@ %define nft_rpmversion 1.0.9 -%define nft_specrelease 1 +%define nft_specrelease 3 Name: nftables Version: %{nft_rpmversion} @@ -19,6 +19,8 @@ Source5: nat.nft Source6: nft-test.stderr.expect Source7: run-tests.stderr.expect +Patch1: 0001-Add-support-for-table-s-persist-flag.patch +Patch2: 0002-cache-Always-set-NFT_CACHE_TERSE-for-list-cmd-with-t.patch BuildRequires: autoconf BuildRequires: automake @@ -131,6 +133,12 @@ cd py/ %files -n python3-nftables -f %{pyproject_files} %changelog +* Tue Jul 02 2024 Phil Sutter [1.0.9-3.el9] +- cache: Always set NFT_CACHE_TERSE for list cmd with --terse (Phil Sutter) [RHEL-45633] + +* Fri Jun 14 2024 Phil Sutter [1.0.9-2.el9] +- Add support for table's persist flag (Phil Sutter) [RHEL-32122] + * Fri Oct 27 2023 Phil Sutter [1.0.9-1.el9] - spec: Utilize pyproject-rpm-macros for the python sub-package (Phil Sutter) [RHEL-14191] - Rebase onto version 1.0.9 (Phil Sutter) [RHEL-14191]