# cat test.nft
 define test = "1.2.3.4"

 table ip x {
        chain y {
                ip saddr $text
        }
 }
 # nft -f test.nft
 test.nft:5:13-16: Error: unknown identifier 'text'; did you mean identifier 
‘test’?
                 ip saddr $text
                           ^^^^

Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>
---
 include/rule.h     |  2 ++
 src/parser_bison.y | 12 ++++++++++--
 src/rule.c         | 18 ++++++++++++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index 88fed62e7cba..dc5e5b87f933 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -112,6 +112,8 @@ extern void symbol_bind(struct scope *scope, const char 
*identifier,
 extern int symbol_unbind(const struct scope *scope, const char *identifier);
 extern struct symbol *symbol_lookup(const struct scope *scope,
                                    const char *identifier);
+struct symbol *symbol_lookup_fuzzy(const struct scope *scope,
+                                  const char *identifier);
 struct symbol *symbol_get(const struct scope *scope, const char *identifier);
 
 enum table_flags {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index dfe306837624..e73e1ecd0805 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -3078,8 +3078,16 @@ variable_expr            :       '$'     identifier
 
                                sym = symbol_get(scope, $2);
                                if (!sym) {
-                                       erec_queue(error(&@2, "unknown 
identifier '%s'", $2),
-                                                  state->msgs);
+                                       sym = symbol_lookup_fuzzy(scope, $2);
+                                       if (sym) {
+                                               erec_queue(error(&@2, "unknown 
identifier '%s'; "
+                                                                     "did you 
mean identifier ‘%s’?",
+                                                                     $2, 
sym->identifier),
+                                                          state->msgs);
+                                       } else {
+                                               erec_queue(error(&@2, "unknown 
identifier '%s'", $2),
+                                                          state->msgs);
+                                       }
                                        xfree($2);
                                        YYERROR;
                                }
diff --git a/src/rule.c b/src/rule.c
index 0a3c1970c83a..ad3001294c65 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -692,6 +692,24 @@ struct symbol *symbol_lookup(const struct scope *scope, 
const char *identifier)
        return NULL;
 }
 
+struct symbol *symbol_lookup_fuzzy(const struct scope *scope,
+                                  const char *identifier)
+{
+       struct string_misspell_state st;
+       struct symbol *sym;
+
+       string_misspell_init(&st);
+
+       while (scope != NULL) {
+               list_for_each_entry(sym, &scope->symbols, list)
+                       string_misspell_update(sym->identifier, identifier,
+                                              sym, &st);
+
+               scope = scope->parent;
+       }
+       return st.obj;
+}
+
 static const char * const chain_type_str_array[] = {
        "filter",
        "nat",
-- 
2.11.0


Reply via email to