[PATCH nft 2/2] datatype: add hint on error handler

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
---
 include/datatype.h |  1 +
 src/datatype.c     | 41 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/include/datatype.h b/include/datatype.h
index 391d6ac8b4bd..4b59790b67f9 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -167,6 +167,7 @@ struct datatype {
 	struct error_record		*(*parse)(struct parse_ctx *ctx,
 						  const struct expr *sym,
 						  struct expr **res);
+	struct error_record		*(*err)(const struct expr *sym);
 	void				(*describe)(struct output_ctx *octx);
 	const struct symbol_table	*sym_tbl;
 	unsigned int			refcnt;
diff --git a/src/datatype.c b/src/datatype.c
index 2cefd0f3f10e..da802a18bccd 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 = {
-- 
2.30.2




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux