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