[PATCH nftables v2 3/3] src: add comment support when adding tables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
v2 does not include empty tests file as previous patch version

 include/rule.h                                |  1 +
 src/mnl.c                                     | 18 +++++++++--
 src/netlink.c                                 | 32 +++++++++++++++++++
 src/parser_bison.y                            |  4 +++
 src/rule.c                                    |  5 +++
 .../testcases/optionals/comments_table_0      |  6 ++++
 .../optionals/dumps/comments_table_0.nft      |  3 ++
 7 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100755 tests/shell/testcases/optionals/comments_table_0
 create mode 100644 tests/shell/testcases/optionals/dumps/comments_table_0.nft

diff --git a/include/rule.h b/include/rule.h
index caca63d0..1167b1fb 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -159,6 +159,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..c79d6c4f 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -832,16 +832,30 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
 {
 	struct nftnl_table *nlt;
 	struct nlmsghdr *nlh;
+	struct nftnl_udata_buf *udbuf;
 
 	nlt = nftnl_table_alloc();
 	if (nlt == NULL)
 		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 20b3cdf5..813f33c1 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -583,10 +583,32 @@ int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h)
 	return 0;
 }
 
+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)
 {
 	struct table *table;
+	const struct nftnl_udata *ud[NFTNL_UDATA_TABLE_MAX + 1] = {};
+	const char *udata;
+	uint32_t ulen;
 
 	table = table_alloc();
 	table->handle.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
@@ -594,6 +616,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 7e094ff6..937468c1 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 2b5685c2..775e05c2 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1317,6 +1317,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)
@@ -1414,6 +1416,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..57d632e6
--- /dev/null
+++ b/tests/shell/testcases/optionals/comments_table_0
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# comments are shown
+
+$NFT add table test { comment \"test_comment\"\; }
+$NFT -a list table test | grep '\"test_comment\"' >/dev/null
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"
+}
-- 
2.27.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux