diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-05-09 17:46:54 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-05-11 18:18:35 +0200 |
commit | d486c9e626405e829221b82d7355558005b26d8a (patch) | |
tree | a704df09df488b31302a9c6caa7bd855c295baa2 /src | |
parent | 8d586177b843af5e77f10e3f0c532341648582d0 (diff) |
datatype: add hint error handler
If user provides a symbol that cannot be parsed and the datatype provides
an error handler, provide a hint through the misspell infrastructure.
For instance:
# cat test.nft
table ip x {
map y {
typeof ip saddr : verdict
elements = { 1.2.3.4 : filter_server1 }
}
}
# nft -f test.nft
test.nft:4:26-39: Error: Could not parse netfilter verdict; did you mean `jump filter_server1'?
elements = { 1.2.3.4 : filter_server1 }
^^^^^^^^^^^^^^
While at it, normalize error to "Could not parse symbolic %s expression".
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/datatype.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/datatype.c b/src/datatype.c index 2cefd0f3..da802a18 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -124,6 +124,7 @@ struct error_record *symbol_parse(struct parse_ctx *ctx, const struct expr *sym, struct expr **res) { const struct datatype *dtype = sym->dtype; + struct error_record *erec; assert(sym->etype == EXPR_SYMBOL); @@ -137,8 +138,14 @@ struct error_record *symbol_parse(struct parse_ctx *ctx, const struct expr *sym, res); } while ((dtype = dtype->basetype)); - return error(&sym->location, - "Can't parse symbolic %s expressions", + dtype = sym->dtype; + if (dtype->err) { + erec = dtype->err(sym); + if (erec) + return erec; + } + + return error(&sym->location, "Could not parse symbolic %s expression", sym->dtype->desc); } @@ -367,11 +374,41 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) } } +static struct error_record *verdict_type_error(const struct expr *sym) +{ + /* Skip jump and goto from fuzzy match to provide better error + * reporting, fall back to `jump chain' if no clue. + */ + static const char *verdict_array[] = { + "continue", "break", "return", "accept", "drop", "queue", + "stolen", NULL, + }; + struct string_misspell_state st; + int i; + + string_misspell_init(&st); + + for (i = 0; verdict_array[i] != NULL; i++) { + string_misspell_update(sym->identifier, verdict_array[i], + (void *)verdict_array[i], &st); + } + + if (st.obj) { + return error(&sym->location, "Could not parse %s; did you mean `%s'?", + sym->dtype->desc, st.obj); + } + + /* assume user would like to jump to chain as a hint. */ + return error(&sym->location, "Could not parse %s; did you mean `jump %s'?", + sym->dtype->desc, sym->identifier); +} + const struct datatype verdict_type = { .type = TYPE_VERDICT, .name = "verdict", .desc = "netfilter verdict", .print = verdict_type_print, + .err = verdict_type_error, }; static const struct symbol_table nfproto_tbl = { |