]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
parser: evaluate commands immediately after parsing
authorPatrick McHardy <kaber@trash.net>
Tue, 4 Feb 2014 08:09:27 +0000 (08:09 +0000)
committerPatrick McHardy <kaber@trash.net>
Tue, 4 Feb 2014 08:17:47 +0000 (08:17 +0000)
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>
include/parser.h
include/rule.h
src/evaluate.c
src/main.c
src/parser.y

index 7a1c2dbe9fdcd64166be026237393690d4728f7c..92beab28d62e94e6706d6e68939690927818704c 100644 (file)
@@ -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);
index 47dd6ab9a85e2f697cb612eb2a7b939f02dc57e3..e06444eb0379c0b82de507a0c670ed5c9a1a3412 100644 (file)
@@ -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);
 
index a01d2a53b80077d3b986c8069c387d3f9edebc47..8e51a63b4486fdddfc7c697f3dbf48b2046e96d2 100644 (file)
@@ -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;
-}
index 2320a826143897b48908dcdfa616ade1eb7fd880..9d505776d85fe043ddfbf0567d0a15ff726d02cc 100644 (file)
@@ -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);
 }
 
index 0dad036cf3026236cdde471a4b18e6ed5e91c0c8..cc0aed697ee4f3218d46790a9f3dbca91a24aa4d 100644 (file)
@@ -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;