summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/rule.h1
-rw-r--r--src/mnl.c17
-rw-r--r--src/netlink.c32
-rw-r--r--src/parser_bison.y4
-rw-r--r--src/rule.c5
-rwxr-xr-xtests/shell/testcases/optionals/comments_table_05
-rw-r--r--tests/shell/testcases/optionals/dumps/comments_table_0.nft3
7 files changed, 65 insertions, 2 deletions
diff --git a/include/rule.h b/include/rule.h
index 62d25be2..56f1951f 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -162,6 +162,7 @@ struct table {
struct list_head chain_bindings;
enum table_flags flags;
unsigned int refcnt;
+ const char *comment;
};
extern struct table *table_alloc(void);
diff --git a/src/mnl.c b/src/mnl.c
index 388eff8f..cdcf9490 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -830,6 +830,7 @@ err:
int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags)
{
+ struct nftnl_udata_buf *udbuf;
struct nftnl_table *nlt;
struct nlmsghdr *nlh;
@@ -838,10 +839,22 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
memory_allocation_error();
nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
- if (cmd->table)
+ if (cmd->table) {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, cmd->table->flags);
- else
+
+ if (cmd->table->comment) {
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udbuf)
+ memory_allocation_error();
+ if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_TABLE_COMMENT, cmd->table->comment))
+ memory_allocation_error();
+ nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA, nftnl_udata_buf_data(udbuf),
+ nftnl_udata_buf_len(udbuf));
+ nftnl_udata_buf_free(udbuf);
+ }
+ } else {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, 0);
+ }
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_NEWTABLE,
diff --git a/src/netlink.c b/src/netlink.c
index 0db5e175..a107f492 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -537,10 +537,32 @@ struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
return chain;
}
+static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
+{
+ unsigned char *value = nftnl_udata_get(attr);
+ const struct nftnl_udata **tb = data;
+ uint8_t type = nftnl_udata_type(attr);
+ uint8_t len = nftnl_udata_len(attr);
+
+ switch (type) {
+ case NFTNL_UDATA_TABLE_COMMENT:
+ if (value[len - 1] != '\0')
+ return -1;
+ break;
+ default:
+ return 0;
+ }
+ tb[type] = attr;
+ return 0;
+}
+
struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
const struct nftnl_table *nlt)
{
+ const struct nftnl_udata *ud[NFTNL_UDATA_TABLE_MAX + 1] = {};
struct table *table;
+ const char *udata;
+ uint32_t ulen;
table = table_alloc();
table->handle.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
@@ -548,6 +570,16 @@ struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
table->flags = nftnl_table_get_u32(nlt, NFTNL_TABLE_FLAGS);
table->handle.handle.id = nftnl_table_get_u64(nlt, NFTNL_TABLE_HANDLE);
+ if (nftnl_table_is_set(nlt, NFTNL_TABLE_USERDATA)) {
+ udata = nftnl_table_get_data(nlt, NFTNL_TABLE_USERDATA, &ulen);
+ if (nftnl_udata_parse(udata, ulen, table_parse_udata_cb, ud) < 0) {
+ netlink_io_error(ctx, NULL, "Cannot parse userdata");
+ return NULL;
+ }
+ if (ud[NFTNL_UDATA_TABLE_COMMENT])
+ table->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_TABLE_COMMENT]));
+ }
+
return table;
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d4e99417..95adc48f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1533,6 +1533,10 @@ table_options : FLAGS STRING
YYERROR;
}
}
+ | comment_spec
+ {
+ $<table>0->comment = $1;
+ }
;
table_block : /* empty */ { $$ = $<table>-1; }
diff --git a/src/rule.c b/src/rule.c
index a925d844..2c4b5dbe 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1324,6 +1324,8 @@ void table_free(struct table *table)
if (--table->refcnt > 0)
return;
+ if (table->comment)
+ xfree(table->comment);
list_for_each_entry_safe(chain, next, &table->chains, list)
chain_free(chain);
list_for_each_entry_safe(chain, next, &table->chain_bindings, list)
@@ -1422,6 +1424,9 @@ static void table_print(const struct table *table, struct output_ctx *octx)
nft_print(octx, "\n");
table_print_options(table, &delim, octx);
+ if (table->comment)
+ nft_print(octx, "\tcomment \"%s\"\n", table->comment);
+
list_for_each_entry(obj, &table->objs, list) {
nft_print(octx, "%s", delim);
obj_print(obj, octx);
diff --git a/tests/shell/testcases/optionals/comments_table_0 b/tests/shell/testcases/optionals/comments_table_0
new file mode 100755
index 00000000..a0dfd749
--- /dev/null
+++ b/tests/shell/testcases/optionals/comments_table_0
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# comments are shown
+
+$NFT add table test { comment \"test_comment\"\; }
diff --git a/tests/shell/testcases/optionals/dumps/comments_table_0.nft b/tests/shell/testcases/optionals/dumps/comments_table_0.nft
new file mode 100644
index 00000000..32ae3c2d
--- /dev/null
+++ b/tests/shell/testcases/optionals/dumps/comments_table_0.nft
@@ -0,0 +1,3 @@
+table ip test {
+ comment "test_comment"
+}