[PATCH nftables 3/3] src: add comment support for chains

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

 



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@xxxxxxxxxx>
---
 include/rule.h                                |  1 +
 src/mnl.c                                     | 11 +++++++
 src/netlink.c                                 | 32 +++++++++++++++++++
 src/parser_bison.y                            |  8 +++++
 src/rule.c                                    |  3 ++
 .../testcases/optionals/comments_chain_0      | 12 +++++++
 .../optionals/dumps/comments_chain_0.nft      |  5 +++
 7 files changed, 72 insertions(+)
 create mode 100755 tests/shell/testcases/optionals/comments_chain_0
 create mode 100644 tests/shell/testcases/optionals/dumps/comments_chain_0.nft

diff --git a/include/rule.h b/include/rule.h
index 837005b1..ffe8daab 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -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;
diff --git a/src/mnl.c b/src/mnl.c
index ca4f4b2a..3e0de103 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -612,6 +612,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;
@@ -672,6 +673,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 c7ea520c..4c71cd61 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1724,6 +1724,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; }
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,
diff --git a/tests/shell/testcases/optionals/comments_chain_0 b/tests/shell/testcases/optionals/comments_chain_0
new file mode 100755
index 00000000..fba961c7
--- /dev/null
+++ b/tests/shell/testcases/optionals/comments_chain_0
@@ -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
index 00000000..be3d8f33
--- /dev/null
+++ b/tests/shell/testcases/optionals/dumps/comments_chain_0.nft
@@ -0,0 +1,5 @@
+table ip test_table {
+	chain test_chain {
+		comment "test"
+	}
+}
-- 
2.27.0




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

  Powered by Linux