diff --git a/0001-Add-support-for-table-s-persist-flag.patch b/0001-Add-support-for-table-s-persist-flag.patch new file mode 100644 index 0000000..3dca01e --- /dev/null +++ b/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 - < [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]