# nft list chain x y Error: No such file or directory; did you mean chain ‘y’ in family ‘inet’? list chain x y ^ Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- include/rule.h | 2 ++ src/evaluate.c | 29 ++++++++++++++++++++--------- src/rule.c | 15 +++++++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/rule.h b/include/rule.h index a3e0bf117d68..331907a96c62 100644 --- a/include/rule.h +++ b/include/rule.h @@ -221,6 +221,8 @@ 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); extern const char *family2str(unsigned int family); extern const char *hooknum2str(unsigned int family, unsigned int hooknum); diff --git a/src/evaluate.c b/src/evaluate.c index 10d88c554e5e..7dd4886d4561 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -181,6 +181,21 @@ static int table_not_found(struct eval_ctx *ctx) family2str(table->handle.family)); } +static int chain_not_found(struct eval_ctx *ctx) +{ + struct chain *chain; + + chain = chain_lookup_fuzzy(&ctx->cmd->handle, &ctx->nft->cache); + 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 family ‘%s’?", + strerror(ENOENT), chain->handle.chain.name, + family2str(chain->handle.family)); +} + /* * Symbol expression: parse symbol and evaluate resulting expression. */ @@ -3109,9 +3124,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 +3512,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 +3658,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); diff --git a/src/rule.c b/src/rule.c index 3553b43def06..3ad31d7224a6 100644 --- a/src/rule.c +++ b/src/rule.c @@ -762,6 +762,21 @@ 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) +{ + 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)) + return chain; + } + } + return NULL; +} + const char *family2str(unsigned int family) { switch (family) { -- 2.11.0