From 702ac2b72c0e8fb570ef30dd942472bf5d4146b8 Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado Gomez" Date: Mon, 21 Sep 2020 15:28:23 +0200 Subject: src: add comment support for chains This patch enables the user to specify a comment when adding a chain. Relies on kernel space supporting userdata for chains. > nft add table ip filter > nft add chain ip filter input { comment "test"\; type filter hook input priority 0\; policy accept\; } > list ruleset table ip filter { chain input { comment "test" type filter hook input priority filter; policy accept; } } Signed-off-by: Jose M. Guisado Gomez Signed-off-by: Pablo Neira Ayuso --- src/mnl.c | 11 +++++++++++ src/netlink.c | 32 ++++++++++++++++++++++++++++++++ src/parser_bison.y | 8 ++++++++ src/rule.c | 3 +++ 4 files changed, 54 insertions(+) (limited to 'src') diff --git a/src/mnl.c b/src/mnl.c index 6699b917..adb55d4d 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -601,6 +601,7 @@ err: int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd, unsigned int flags) { + struct nftnl_udata_buf *udbuf; int priority, policy, i = 0; struct nftnl_chain *nlc; unsigned int ifname_len; @@ -661,6 +662,16 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd, xfree(dev_array); } + if (cmd->chain->comment) { + udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); + if (!udbuf) + memory_allocation_error(); + if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_CHAIN_COMMENT, cmd->chain->comment)) + memory_allocation_error(); + nftnl_chain_set_data(nlc, NFTNL_CHAIN_USERDATA, nftnl_udata_buf_data(udbuf), + nftnl_udata_buf_len(udbuf)); + nftnl_udata_buf_free(udbuf); + } } netlink_dump_chain(nlc, ctx); diff --git a/src/netlink.c b/src/netlink.c index 6912b018..f8ac2b9e 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -472,12 +472,34 @@ void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx) fprintf(fp, "\n"); } +static int chain_parse_udata_cb(const struct nftnl_udata *attr, void *data) +{ + unsigned char *value = nftnl_udata_get(attr); + uint8_t type = nftnl_udata_type(attr); + const struct nftnl_udata **tb = data; + uint8_t len = nftnl_udata_len(attr); + + switch (type) { + case NFTNL_UDATA_CHAIN_COMMENT: + if (value[len - 1] != '\0') + return -1; + break; + default: + return 0; + } + tb[type] = attr; + return 0; +} + struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx, const struct nftnl_chain *nlc) { + const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {}; int priority, policy, len = 0, i; const char * const *dev_array; struct chain *chain; + const char *udata; + uint32_t ulen; chain = chain_alloc(nftnl_chain_get_str(nlc, NFTNL_CHAIN_NAME)); chain->handle.family = @@ -534,6 +556,16 @@ struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx, chain->flags |= CHAIN_F_BASECHAIN; } + if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_USERDATA)) { + udata = nftnl_chain_get_data(nlc, NFTNL_CHAIN_USERDATA, &ulen); + if (nftnl_udata_parse(udata, ulen, chain_parse_udata_cb, ud) < 0) { + netlink_io_error(ctx, NULL, "Cannot parse userdata"); + return NULL; + } + if (ud[NFTNL_UDATA_CHAIN_COMMENT]) + chain->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_CHAIN_COMMENT])); + } + return chain; } diff --git a/src/parser_bison.y b/src/parser_bison.y index 524903fd..9bf4f71f 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1723,6 +1723,14 @@ chain_block : /* empty */ { $$ = $-1; } list_add_tail(&$2->list, &$1->rules); $$ = $1; } + | chain_block comment_spec stmt_separator + { + if (already_set($1->comment, &@2, state)) { + xfree($2); + YYERROR; + } + $1->comment = $2; + } ; subchain_block : /* empty */ { $$ = $-1; } diff --git a/src/rule.c b/src/rule.c index dabb3579..d75b36c4 100644 --- a/src/rule.c +++ b/src/rule.c @@ -929,6 +929,7 @@ void chain_free(struct chain *chain) xfree(chain->dev_array); expr_free(chain->priority.expr); expr_free(chain->policy); + xfree(chain->comment); xfree(chain); } @@ -1220,6 +1221,8 @@ static void chain_print_declaration(const struct chain *chain, nft_print(octx, "\tchain %s {", chain->handle.chain.name); if (nft_output_handle(octx)) nft_print(octx, " # handle %" PRIu64, chain->handle.handle.id); + if (chain->comment) + nft_print(octx, "\n\t\tcomment \"%s\"", chain->comment); nft_print(octx, "\n"); if (chain->flags & CHAIN_F_BASECHAIN) { nft_print(octx, "\t\ttype %s hook %s", chain->type, -- cgit v1.2.3