[nft PATCH] src: Quote user-defined names

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

 



Nftables claims to allow arbitrary names for ruleset elements (tables,
chains, objects) but suffers from the known problem of lex/yacc trying
to interpret those as keywords. As a workaround, users may quote their
names. Sadly this wasn't supported in most cases and this patch lifts
this restriction.

In order to not print rulesets which are not accepted anymore by 'nft
-f' command, unconditionally quote all names on output.

Note that the same problem existed for interface names. I've tested for
those to work in both netdev family chains and flowtable definitions,
though automatic testing is troublesome since they must exist (and I'm
not sure if test scripts should call iproute2 to add an interface with a
crafted name).

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 src/parser_bison.y                            |  3 +-
 src/rule.c                                    | 28 +++++++++----------
 .../shell/testcases/nft-f/0018quoted-names_0  | 19 +++++++++++++
 3 files changed, 35 insertions(+), 15 deletions(-)
 create mode 100755 tests/shell/testcases/nft-f/0018quoted-names_0

diff --git a/src/parser_bison.y b/src/parser_bison.y
index 02a373cb2289a..fb9b0fcf89baf 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1782,7 +1782,7 @@ flowtable_list_expr	:	flowtable_expr_member
 			|	flowtable_list_expr	COMMA	opt_newline
 			;
 
-flowtable_expr_member	:	STRING
+flowtable_expr_member	:	string
 			{
 				$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
 						       current_scope(state),
@@ -1989,6 +1989,7 @@ chain_policy		:	ACCEPT		{ $$ = NF_ACCEPT; }
 			;
 
 identifier		:	STRING
+			|	QUOTED_STRING
 			;
 
 string			:	STRING
diff --git a/src/rule.c b/src/rule.c
index 73b78c75a267a..f845b5d097c3a 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -433,9 +433,9 @@ static void set_print_declaration(const struct set *set,
 		nft_print(octx, " %s", opts->family);
 
 	if (opts->table != NULL)
-		nft_print(octx, " %s", opts->table);
+		nft_print(octx, " \"%s\"", opts->table);
 
-	nft_print(octx, " %s {", set->handle.set.name);
+	nft_print(octx, " \"%s\" {", set->handle.set.name);
 
 	if (nft_output_handle(octx))
 		nft_print(octx, " # handle %" PRIu64, set->handle.handle.id);
@@ -1062,7 +1062,7 @@ static void chain_print_declaration(const struct chain *chain,
 {
 	char priobuf[STD_PRIO_BUFSIZE];
 
-	nft_print(octx, "\tchain %s {", chain->handle.chain.name);
+	nft_print(octx, "\tchain \"%s\" {", chain->handle.chain.name);
 	if (nft_output_handle(octx))
 		nft_print(octx, " # handle %" PRIu64, chain->handle.handle.id);
 	nft_print(octx, "\n");
@@ -1222,7 +1222,7 @@ static void table_print(const struct table *table, struct output_ctx *octx)
 	const char *delim = "";
 	const char *family = family2str(table->handle.family);
 
-	nft_print(octx, "table %s %s {", family, table->handle.table.name);
+	nft_print(octx, "table %s \"%s\" {", family, table->handle.table.name);
 	if (nft_output_handle(octx))
 		nft_print(octx, " # handle %" PRIu64, table->handle.handle.id);
 	nft_print(octx, "\n");
@@ -1748,7 +1748,7 @@ static void obj_print_data(const struct obj *obj,
 {
 	switch (obj->type) {
 	case NFT_OBJECT_COUNTER:
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
@@ -1763,7 +1763,7 @@ static void obj_print_data(const struct obj *obj,
 		const char *data_unit;
 		uint64_t bytes;
 
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
@@ -1780,14 +1780,14 @@ static void obj_print_data(const struct obj *obj,
 		}
 		break;
 	case NFT_OBJECT_SECMARK:
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
 		nft_print(octx, "%s", obj->secmark.ctx);
 		break;
 	case NFT_OBJECT_CT_HELPER:
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s", opts->nl);
@@ -1801,7 +1801,7 @@ static void obj_print_data(const struct obj *obj,
 			  opts->stmt_separator);
 		break;
 	case NFT_OBJECT_CT_TIMEOUT:
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s", opts->nl);
@@ -1820,7 +1820,7 @@ static void obj_print_data(const struct obj *obj,
 		const char *data_unit;
 		uint64_t rate;
 
-		nft_print(octx, " %s {", obj->handle.obj.name);
+		nft_print(octx, " \"%s\" {", obj->handle.obj.name);
 		if (nft_output_handle(octx))
 			nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
 		nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
@@ -1899,7 +1899,7 @@ static void obj_print_declaration(const struct obj *obj,
 		nft_print(octx, " %s", opts->family);
 
 	if (opts->table != NULL)
-		nft_print(octx, " %s", opts->table);
+		nft_print(octx, " \"%s\"", opts->table);
 
 	obj_print_data(obj, opts, octx);
 
@@ -2015,9 +2015,9 @@ static void flowtable_print_declaration(const struct flowtable *flowtable,
 		nft_print(octx, " %s", opts->family);
 
 	if (opts->table != NULL)
-		nft_print(octx, " %s", opts->table);
+		nft_print(octx, " \"%s\"", opts->table);
 
-	nft_print(octx, " %s {%s", flowtable->handle.flowtable, opts->nl);
+	nft_print(octx, " \"%s\" {%s", flowtable->handle.flowtable, opts->nl);
 
 	nft_print(octx, "%s%shook %s priority %s%s",
 		  opts->tab, opts->tab,
@@ -2028,7 +2028,7 @@ static void flowtable_print_declaration(const struct flowtable *flowtable,
 
 	nft_print(octx, "%s%sdevices = { ", opts->tab, opts->tab);
 	for (i = 0; i < flowtable->dev_array_len; i++) {
-		nft_print(octx, "%s", flowtable->dev_array[i]);
+		nft_print(octx, "\"%s\"", flowtable->dev_array[i]);
 		if (i + 1 != flowtable->dev_array_len)
 			nft_print(octx, ", ");
 	}
diff --git a/tests/shell/testcases/nft-f/0018quoted-names_0 b/tests/shell/testcases/nft-f/0018quoted-names_0
new file mode 100755
index 0000000000000..9655a48d492c0
--- /dev/null
+++ b/tests/shell/testcases/nft-f/0018quoted-names_0
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# Test if keywords are allowed as names if quoted
+
+set -e
+
+# XXX: interface names are arbitrary, too (flowtable, chain)
+RULESET='
+table inet "day" {
+	chain "minute" {}
+	set "hour" { type inet_service; }
+	flowtable "second" { hook ingress priority 0; devices = { lo }; }
+	counter "table" { packets 0 bytes 0 }
+	quota "chain" { 10 bytes }
+}'
+
+$NFT -f - <<< "$RULESET"
+OUTPUT=$($NFT list ruleset)
+$NFT -f - <<< "$OUTPUT"
-- 
2.20.1




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux