summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2014-02-04 08:09:27 +0000
committerPatrick McHardy <kaber@trash.net>2014-02-04 08:17:47 +0000
commit61236968b7a1b4a4986f9a5c9a5e46d3eb70b799 (patch)
tree49cbec37c5e2bc8e1f748d2ae1626af6c1e7df90
parentf3129a3cc4800321ed2157eb400da8b43398606e (diff)
parser: evaluate commands immediately after parsing
We currently do parsing and evaluation in two seperate stages. This means that if any error occurs during parsing, we won't evaluate the syntactical correct commands and detect possible evaluation errors in them. In order to improve error reporting, change this to evaluate every command as soon as it is fully parsed. With this in place, the ruleset can be fully validated and all errors reported in one step: tests/error.1:6:23-23: Error: syntax error, unexpected newline filter input tcp dport ^ tests/error.1:7:24-26: Error: datatype mismatch, expected internet network service, expression has type Internet protocol filter input tcp dport tcp ~~~~~~~~~ ^^^ tests/error.1:8:24-32: Error: Right hand side of relational expression (==) must be constant filter input tcp dport tcp dport ~~~~~~~~~~^^^^^^^^^ Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/parser.h1
-rw-r--r--include/rule.h2
-rw-r--r--src/evaluate.c13
-rw-r--r--src/main.c8
-rw-r--r--src/parser.y14
5 files changed, 16 insertions, 22 deletions
diff --git a/include/parser.h b/include/parser.h
index 7a1c2dbe..92beab28 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -26,6 +26,7 @@ struct parser_state {
unsigned int scope;
struct list_head cmds;
+ struct eval_ctx ectx;
};
extern void parser_init(struct parser_state *state, struct list_head *msgs);
diff --git a/include/rule.h b/include/rule.h
index 47dd6ab9..e06444eb 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -303,7 +303,7 @@ struct eval_ctx {
struct proto_ctx pctx;
};
-extern int evaluate(struct eval_ctx *ctx, struct list_head *commands);
+extern int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd);
extern struct error_record *rule_postprocess(struct rule *rule);
diff --git a/src/evaluate.c b/src/evaluate.c
index a01d2a53..8e51a63b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1384,7 +1384,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
}
}
-static int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
+int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
{
#ifdef DEBUG
if (debug_level & DEBUG_EVALUATION) {
@@ -1411,14 +1411,3 @@ static int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
BUG("invalid command operation %u\n", cmd->op);
};
}
-
-int evaluate(struct eval_ctx *ctx, struct list_head *commands)
-{
- struct cmd *cmd;
-
- list_for_each_entry(cmd, commands, list) {
- if (cmd_evaluate(ctx, cmd) < 0)
- return -1;
- }
- return 0;
-}
diff --git a/src/main.c b/src/main.c
index 2320a826..9d505776 100644
--- a/src/main.c
+++ b/src/main.c
@@ -216,18 +216,12 @@ out:
int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs)
{
- struct eval_ctx ctx;
- int ret = 0;
+ int ret;
ret = nft_parse(scanner, state);
if (ret != 0 || state->nerrs > 0)
return -1;
- memset(&ctx, 0, sizeof(ctx));
- ctx.msgs = msgs;
- if (evaluate(&ctx, &state->cmds) < 0)
- return -1;
-
return nft_netlink(state, msgs);
}
diff --git a/src/parser.y b/src/parser.y
index 0dad036c..cc0aed69 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -37,6 +37,7 @@ void parser_init(struct parser_state *state, struct list_head *msgs)
init_list_head(&state->top_scope.symbols);
state->msgs = msgs;
state->scopes[0] = scope_init(&state->top_scope, NULL);
+ state->ectx.msgs = msgs;
}
static void yyerror(struct location *loc, void *scanner,
@@ -492,7 +493,11 @@ input : /* empty */
{
if ($2 != NULL) {
$2->location = @2;
- list_add_tail(&$2->list, &state->cmds);
+ if (cmd_evaluate(&state->ectx, $2) < 0) {
+ if (++state->nerrs == max_errors)
+ YYABORT;
+ } else
+ list_add_tail(&$2->list, &state->cmds);
}
}
;
@@ -542,7 +547,12 @@ line : common_block { $$ = NULL; }
*/
if ($1 != NULL) {
$1->location = @1;
- list_add_tail(&$1->list, &state->cmds);
+
+ if (cmd_evaluate(&state->ectx, $1) < 0) {
+ if (++state->nerrs == max_errors)
+ YYABORT;
+ } else
+ list_add_tail(&$1->list, &state->cmds);
}
$$ = NULL;