]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: introduce simple hints on incorrect chain
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 19 Nov 2018 11:22:06 +0000 (12:22 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 19 Nov 2018 12:52:37 +0000 (13:52 +0100)
 # nft list chain x y
 Error: No such file or directory; did you mean chain ‘y’ in table inet ‘x’?
 list chain x y
              ^

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/rule.h
src/evaluate.c
src/rule.c

index a3e0bf117d6836642b0f516f512c0314523199c0..66786bdb21402b513fc78eae738a1e4b0335f36b 100644 (file)
@@ -221,6 +221,9 @@ extern void chain_free(struct chain *chain);
 extern void chain_add_hash(struct chain *chain, struct table *table);
 extern struct chain *chain_lookup(const struct table *table,
                                  const struct handle *h);
+extern struct chain *chain_lookup_fuzzy(const struct handle *h,
+                                       const struct nft_cache *cache,
+                                       const struct table **table);
 
 extern const char *family2str(unsigned int family);
 extern const char *hooknum2str(unsigned int family, unsigned int hooknum);
index d836e18d08401cf021955b6f0d49d10fa1decc78..f1682fa3f6770a795b57421e77a2ae66b2471269 100644 (file)
@@ -181,6 +181,23 @@ static int table_not_found(struct eval_ctx *ctx)
                         family2str(table->handle.family));
 }
 
+static int chain_not_found(struct eval_ctx *ctx)
+{
+       const struct table *table;
+       struct chain *chain;
+
+       chain = chain_lookup_fuzzy(&ctx->cmd->handle, &ctx->nft->cache, &table);
+       if (chain == NULL)
+               return cmd_error(ctx, &ctx->cmd->handle.chain.location,
+                                "%s", strerror(ENOENT));
+
+       return cmd_error(ctx, &ctx->cmd->handle.chain.location,
+                        "%s; did you mean chain ‘%s’ in table %s ‘%s’?",
+                        strerror(ENOENT), chain->handle.chain.name,
+                        family2str(chain->handle.family),
+                        table->handle.table.name);
+}
+
 /*
  * Symbol expression: parse symbol and evaluate resulting expression.
  */
@@ -3109,9 +3126,7 @@ static int rule_translate_index(struct eval_ctx *ctx, struct rule *rule)
 
        chain = chain_lookup(table, &rule->handle);
        if (!chain)
-               return cmd_error(ctx, &rule->handle.chain.location,
-                               "Could not process rule: %s",
-                               strerror(ENOENT));
+               return chain_not_found(ctx);
 
        list_for_each_entry(r, &chain->rules, list) {
                if (++index < rule->handle.index.id)
@@ -3499,9 +3514,8 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
                        return table_not_found(ctx);
 
                if (chain_lookup(table, &cmd->handle) == NULL)
-                       return cmd_error(ctx, &cmd->handle.chain.location,
-                                        "Could not process rule: %s",
-                                        strerror(ENOENT));
+                       return chain_not_found(ctx);
+
                return 0;
        case CMD_OBJ_QUOTA:
                return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
@@ -3646,9 +3660,8 @@ static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd)
                        return table_not_found(ctx);
 
                if (chain_lookup(table, &ctx->cmd->handle) == NULL)
-                       return cmd_error(ctx, &ctx->cmd->handle.chain.location,
-                                        "Could not process rule: %s",
-                                        strerror(ENOENT));
+                       return chain_not_found(ctx);
+
                break;
        default:
                BUG("invalid command object type %u\n", cmd->obj);
index 3553b43def06ea218e8f92e09df7954614f72e38..39f717cabeacc20c914723f67391b4ba54cf92d9 100644 (file)
@@ -762,6 +762,24 @@ struct chain *chain_lookup(const struct table *table, const struct handle *h)
        return NULL;
 }
 
+struct chain *chain_lookup_fuzzy(const struct handle *h,
+                                const struct nft_cache *cache,
+                                const struct table **t)
+{
+       struct table *table;
+       struct chain *chain;
+
+       list_for_each_entry(table, &cache->list, list) {
+               list_for_each_entry(chain, &table->chains, list) {
+                       if (!strcmp(chain->handle.chain.name, h->chain.name)) {
+                               *t = table;
+                               return chain;
+                       }
+               }
+       }
+       return NULL;
+}
+
 const char *family2str(unsigned int family)
 {
        switch (family) {