]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add comment support for chains
authorJose M. Guisado Gomez <guigom@riseup.net>
Mon, 21 Sep 2020 13:28:23 +0000 (15:28 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 30 Sep 2020 10:09:18 +0000 (12:09 +0200)
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 <guigom@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/rule.h
src/mnl.c
src/netlink.c
src/parser_bison.y
src/rule.c
tests/shell/testcases/optionals/comments_chain_0 [new file with mode: 0755]
tests/shell/testcases/optionals/dumps/comments_chain_0.nft [new file with mode: 0644]

index 837005b16eb9f5cd1dc27465a833f0939756b766..ffe8daab6f1cf760d6c44599693844ef5135b7dd 100644 (file)
@@ -225,6 +225,7 @@ struct chain {
        struct location         location;
        unsigned int            refcnt;
        uint32_t                flags;
+       const char              *comment;
        struct {
                struct location         loc;
                struct prio_spec        priority;
index 6699b917c450eca12f395043810c1f114b6e74c8..adb55d4dec90386aab609ccf43fa156a8e198796 100644 (file)
--- 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);
 
index 6912b018ba5c864d3335cbf8031218f48f4e897b..f8ac2b9e3665f3a62d8e13fa51d25488562386c1 100644 (file)
@@ -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;
 }
 
index 524903fd80d37b77a0ac1f4b5651c8b21ae47e44..9bf4f71f1f66531220ba078a1f8fe93d94a7dee7 100644 (file)
@@ -1723,6 +1723,14 @@ chain_block              :       /* empty */     { $$ = $<chain>-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 */     { $$ = $<chain>-1; }
index dabb35791a164be64ff8d67bcf574e65b7e4d229..d75b36c4eb0d9cc8b3a2664a89a79a9b673b161d 100644 (file)
@@ -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,
diff --git a/tests/shell/testcases/optionals/comments_chain_0 b/tests/shell/testcases/optionals/comments_chain_0
new file mode 100755 (executable)
index 0000000..fba961c
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+EXPECTED='table ip test_table {
+       chain test_chain {
+               comment "test"
+       }
+}
+'
+
+set -e
+
+$NFT -f - <<< "$EXPECTED"
diff --git a/tests/shell/testcases/optionals/dumps/comments_chain_0.nft b/tests/shell/testcases/optionals/dumps/comments_chain_0.nft
new file mode 100644 (file)
index 0000000..be3d8f3
--- /dev/null
@@ -0,0 +1,5 @@
+table ip test_table {
+       chain test_chain {
+               comment "test"
+       }
+}