From 0100e69baee2e3a7e4bf5f0fb5c824d5c3e81286 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Fri, 24 May 2019 15:06:50 +0200 Subject: [PATCH] src: Allow goto and jump to a variable This patch introduces the use of nft input files variables in 'jump' and 'goto' statements, e.g. define dest = ber add table ip foo add chain ip foo bar {type filter hook input priority 0;} add chain ip foo ber add rule ip foo ber counter add rule ip foo bar jump $dest table ip foo { chain bar { type filter hook input priority filter; policy accept; jump ber } chain ber { counter packets 71 bytes 6664 } } Signed-off-by: Fernando Fernandez Mancera Signed-off-by: Pablo Neira Ayuso (cherry picked from commit c64457cff9673fbb41f613a67e158b4d62235c09) Conflicts: -> Adjust for missing commits 72931553828af ("src: expr: add expression etype") and 68e76238749fb ("src: expr: add and use expr_name helper"). Signed-off-by: Phil Sutter --- src/datatype.c | 11 ++++++++++ src/evaluate.c | 7 +++++++ src/parser_bison.y | 3 ++- .../shell/testcases/nft-f/0018jump_variable_0 | 19 ++++++++++++++++++ .../shell/testcases/nft-f/0019jump_variable_1 | 20 +++++++++++++++++++ .../shell/testcases/nft-f/0020jump_variable_1 | 20 +++++++++++++++++++ .../nft-f/dumps/0018jump_variable_0.nft | 8 ++++++++ 7 files changed, 87 insertions(+), 1 deletion(-) create mode 100755 tests/shell/testcases/nft-f/0018jump_variable_0 create mode 100755 tests/shell/testcases/nft-f/0019jump_variable_1 create mode 100755 tests/shell/testcases/nft-f/0020jump_variable_1 create mode 100644 tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft diff --git a/src/datatype.c b/src/datatype.c index f7defa37ff196..5791a6a41599e 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -308,11 +308,22 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) } } +static struct error_record *verdict_type_parse(const struct expr *sym, + struct expr **res) +{ + *res = constant_expr_alloc(&sym->location, &string_type, + BYTEORDER_HOST_ENDIAN, + (strlen(sym->identifier) + 1) * BITS_PER_BYTE, + sym->identifier); + return NULL; +} + const struct datatype verdict_type = { .type = TYPE_VERDICT, .name = "verdict", .desc = "netfilter verdict", .print = verdict_type_print, + .parse = verdict_type_parse, }; static const struct symbol_table nfproto_tbl = { diff --git a/src/evaluate.c b/src/evaluate.c index 5f0f3b36fd99f..8e15e71d8a33b 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1850,6 +1850,13 @@ static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt) if (stmt->expr->chain != NULL) { if (expr_evaluate(ctx, &stmt->expr->chain) < 0) return -1; + if ((stmt->expr->chain->ops->type != EXPR_SYMBOL && + stmt->expr->chain->ops->type != EXPR_VALUE) || + stmt->expr->chain->symtype != SYMBOL_VALUE) { + return stmt_error(ctx, stmt, + "invalid verdict chain expression %s\n", + stmt->expr->chain->ops->name); + } } break; case EXPR_MAP: diff --git a/src/parser_bison.y b/src/parser_bison.y index 08dce52cebd1e..2e8ebde34eee6 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -3475,7 +3475,8 @@ verdict_expr : ACCEPT } ; -chain_expr : identifier +chain_expr : variable_expr + | identifier { $$ = constant_expr_alloc(&@$, &string_type, BYTEORDER_HOST_ENDIAN, diff --git a/tests/shell/testcases/nft-f/0018jump_variable_0 b/tests/shell/testcases/nft-f/0018jump_variable_0 new file mode 100755 index 0000000000000..003a1bdf701f1 --- /dev/null +++ b/tests/shell/testcases/nft-f/0018jump_variable_0 @@ -0,0 +1,19 @@ +#!/bin/bash + +# Tests use of variables in jump statements + +set -e + +RULESET=" +define dest = ber + +table ip foo { + chain bar { + jump \$dest + } + + chain ber { + } +}" + +$NFT -f - <<< "$RULESET" diff --git a/tests/shell/testcases/nft-f/0019jump_variable_1 b/tests/shell/testcases/nft-f/0019jump_variable_1 new file mode 100755 index 0000000000000..bda861c91df31 --- /dev/null +++ b/tests/shell/testcases/nft-f/0019jump_variable_1 @@ -0,0 +1,20 @@ +#!/bin/bash + +# Tests use of variables in jump statements + +set -e + +RULESET=" +define dest = { 1024 } + +table ip foo { + chain bar { + jump \$dest + } + + chain ber { + } +}" + +$NFT -f - <<< "$RULESET" && exit 1 +exit 0 diff --git a/tests/shell/testcases/nft-f/0020jump_variable_1 b/tests/shell/testcases/nft-f/0020jump_variable_1 new file mode 100755 index 0000000000000..f753058f24f64 --- /dev/null +++ b/tests/shell/testcases/nft-f/0020jump_variable_1 @@ -0,0 +1,20 @@ +#!/bin/bash + +# Tests use of variables in jump statements + +set -e + +RULESET=" +define dest = * + +table ip foo { + chain bar { + jump \$dest + } + + chain ber { + } +}" + +$NFT -f - <<< "$RULESET" && exit 1 +exit 0 diff --git a/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft new file mode 100644 index 0000000000000..0ddaf07f0ea3b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft @@ -0,0 +1,8 @@ +table ip foo { + chain bar { + jump ber + } + + chain ber { + } +} -- 2.21.0