From: Jose M. Guisado Gomez Date: Fri, 21 Aug 2020 16:40:30 +0000 (+0200) Subject: src: add comment support when adding tables X-Git-Tag: v0.9.7~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c156232a530b30b6668712eda22bc491b0900283;p=thirdparty%2Fnftables.git src: add comment support when adding tables Adds userdata building logic if a comment is specified when creating a new table. Adds netlink userdata parsing callback function. Relies on kernel supporting userdata for nft_table. Example: > nft add table ip x { comment "test"\; } > nft list ruleset table ip x { comment "test" } Signed-off-by: Jose M. Guisado Gomez Signed-off-by: Pablo Neira Ayuso --- 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 + { + $0->comment = $1; + } ; table_block : /* empty */ { $$ = $
-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" +}