[PATCH nft,v4 3/3] src: introduce simple hints on incorrect set

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

 



 # nft rule x y ip saddr @y
 Error: No such file or directory; did you mean set ‘y’ in table inet ‘x’?
 rule x y ip saddr @y
                   ^^

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 include/rule.h |  3 +++
 src/evaluate.c | 68 +++++++++++++++++++++++++++++++++++-----------------------
 src/rule.c     | 18 ++++++++++++++++
 3 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index 66786bdb2140..85b9f80d04fe 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -308,6 +308,9 @@ extern void set_add_hash(struct set *set, struct table *table);
 extern struct set *set_lookup(const struct table *table, const char *name);
 extern struct set *set_lookup_global(uint32_t family, const char *table,
 				     const char *name, struct nft_cache *cache);
+extern struct set *set_lookup_fuzzy(const char *set_name,
+				    const struct nft_cache *cache,
+				    const struct table **table);
 extern const char *set_policy2str(uint32_t policy);
 extern void set_print(const struct set *set, struct output_ctx *octx);
 extern void set_print_plain(const struct set *s, struct output_ctx *octx);
diff --git a/src/evaluate.c b/src/evaluate.c
index f1682fa3f677..14c76420d524 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -198,6 +198,23 @@ static int chain_not_found(struct eval_ctx *ctx)
 			 table->handle.table.name);
 }
 
+static int set_not_found(struct eval_ctx *ctx, const struct location *loc,
+			 const char *set_name)
+{
+	const struct table *table;
+	struct set *set;
+
+	set = set_lookup_fuzzy(set_name, &ctx->nft->cache, &table);
+	if (set == NULL)
+		return cmd_error(ctx, loc, "%s", strerror(ENOENT));
+
+	return cmd_error(ctx, loc,
+			 "%s; did you mean set ‘%s’ in table %s ‘%s’?",
+			 strerror(ENOENT), set->handle.set.name,
+				 family2str(set->handle.family),
+				 table->handle.table.name);
+}
+
 /*
  * Symbol expression: parse symbol and evaluate resulting expression.
  */
@@ -229,9 +246,8 @@ static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr)
 
 		set = set_lookup(table, (*expr)->identifier);
 		if (set == NULL)
-			return expr_error(ctx->msgs, *expr,
-					  "Set '%s' does not exist",
-					  (*expr)->identifier);
+			return set_not_found(ctx, &(*expr)->location,
+					     (*expr)->identifier);
 
 		new = set_ref_expr_alloc(&(*expr)->location, set);
 		break;
@@ -2989,9 +3005,8 @@ static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr)
 
 	set = set_lookup(table, ctx->cmd->handle.set.name);
 	if (set == NULL)
-		return cmd_error(ctx, &ctx->cmd->handle.set.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return set_not_found(ctx, &ctx->cmd->handle.set.location,
+				     ctx->cmd->handle.set.name);
 
 	ctx->set = set;
 	expr_set_context(&ctx->ectx, set->key->dtype, set->key->len);
@@ -3426,9 +3441,8 @@ static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
-			return cmd_error(ctx, &ctx->cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
 
 		return setelem_evaluate(ctx, &cmd->expr);
 	default:
@@ -3482,9 +3496,9 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
-			return cmd_error(ctx, &cmd->handle.set.location,
-					  "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	case CMD_OBJ_METER:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
@@ -3493,9 +3507,9 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_EVAL))
-			return cmd_error(ctx, &cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	case CMD_OBJ_MAP:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
@@ -3504,9 +3518,9 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_MAP))
-			return cmd_error(ctx, &cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	case CMD_OBJ_CHAIN:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
@@ -3604,9 +3618,9 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
-			return cmd_error(ctx, &cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	case CMD_OBJ_MAP:
 		ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
@@ -3619,9 +3633,9 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_MAP))
-			return cmd_error(ctx, &ctx->cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	case CMD_OBJ_METER:
 		ret = cache_update(ctx->nft, cmd->op, ctx->msgs);
@@ -3634,9 +3648,9 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_EVAL))
-			return cmd_error(ctx, &ctx->cmd->handle.set.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return set_not_found(ctx, &ctx->cmd->handle.set.location,
+					     ctx->cmd->handle.set.name);
+
 		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
diff --git a/src/rule.c b/src/rule.c
index 39f717cabeac..1fffa39ab243 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -350,6 +350,24 @@ struct set *set_lookup(const struct table *table, const char *name)
 	return NULL;
 }
 
+struct set *set_lookup_fuzzy(const char *set_name,
+			     const struct nft_cache *cache,
+			     const struct table **t)
+{
+	struct table *table;
+	struct set *set;
+
+	list_for_each_entry(table, &cache->list, list) {
+		list_for_each_entry(set, &table->sets, list) {
+			if (!strcmp(set->handle.set.name, set_name)) {
+				*t = table;
+				return set;
+			}
+		}
+	}
+	return NULL;
+}
+
 struct set *set_lookup_global(uint32_t family, const char *table,
 			      const char *name, struct nft_cache *cache)
 {
-- 
2.11.0




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux