]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add comment support when adding tables
authorJose M. Guisado Gomez <guigom@riseup.net>
Fri, 21 Aug 2020 16:40:30 +0000 (18:40 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 28 Aug 2020 17:48:20 +0000 (19:48 +0200)
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 <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_table_0 [new file with mode: 0755]
tests/shell/testcases/optionals/dumps/comments_table_0.nft [new file with mode: 0644]

index 62d25be2106eca0941ec529f8f7e69e07ece3333..56f1951f4d8958bb76e270f714e566a55e747fbd 100644 (file)
@@ -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);
index 388eff8fa4ccb5eae08789760caabbae3fd62dfa..cdcf94909d912e00acace58187b61433e04bacb8 100644 (file)
--- 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,
index 0db5e175a7e31d5b2f2ef92a4a7bb8a2393aa31e..a107f492e8ede9a46f98b3e4ca3859e56113ba6f 100644 (file)
@@ -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;
 }
 
index d4e994175fea69cf0cbe075c9bb8db581b85f33e..95adc48fdd7b1bd4b822f6e096afc47c17a762db 100644 (file)
@@ -1533,6 +1533,10 @@ table_options            :       FLAGS           STRING
                                        YYERROR;
                                }
                        }
+                       |       comment_spec
+                       {
+                               $<table>0->comment = $1;
+                       }
                        ;
 
 table_block            :       /* empty */     { $$ = $<table>-1; }
index a925d84487606d8222d4321dacb7a68ca89f53d4..2c4b5dbe2e9cc7514d6434dcabb4d787da4fc66e 100644 (file)
@@ -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 (executable)
index 0000000..a0dfd74
--- /dev/null
@@ -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 (file)
index 0000000..32ae3c2
--- /dev/null
@@ -0,0 +1,3 @@
+table ip test {
+       comment "test_comment"
+}