diff mbox series

[nft,v4,1/3] src: introduce simple hints on incorrect table

Message ID 20181119125456.12459-1-pablo@netfilter.org
State Accepted
Delegated to: Pablo Neira
Headers show
Series [nft,v4,1/3] src: introduce simple hints on incorrect table | expand

Commit Message

Pablo Neira Ayuso Nov. 19, 2018, 12:54 p.m. UTC
This patch adds simple infrastructure to provide a hints to user on
references to incorrect table. While at it, remove "Could not process
rule:" which I think it is implicit in the error.

 # nft rule x y ip saddr @y
 Error: No such file or directory; did you mean table ā€˜xā€™ in family inet?

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/rule.h |   2 ++
 src/evaluate.c | 105 ++++++++++++++++++++++++++-------------------------------
 src/rule.c     |  12 +++++++
 3 files changed, 62 insertions(+), 57 deletions(-)
diff mbox series

Patch

diff --git a/include/rule.h b/include/rule.h
index 197efab49745..a3e0bf117d68 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -153,6 +153,8 @@  extern void table_free(struct table *table);
 extern void table_add_hash(struct table *table, struct nft_cache *cache);
 extern struct table *table_lookup(const struct handle *h,
 				  const struct nft_cache *cache);
+extern struct table *table_lookup_fuzzy(const struct handle *h,
+					const struct nft_cache *cache);
 
 /**
  * enum chain_flags - chain flags
diff --git a/src/evaluate.c b/src/evaluate.c
index d023f47a8eed..d836e18d0840 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -166,6 +166,21 @@  static struct table *table_lookup_global(struct eval_ctx *ctx)
 	return table;
 }
 
+static int table_not_found(struct eval_ctx *ctx)
+{
+	struct table *table;
+
+	table = table_lookup_fuzzy(&ctx->cmd->handle, &ctx->nft->cache);
+	if (table == NULL)
+		return cmd_error(ctx, &ctx->cmd->handle.table.location,
+				 "%s", strerror(ENOENT));
+
+	return cmd_error(ctx, &ctx->cmd->handle.table.location,
+			 "%s; did you mean table ā€˜%sā€™ in family %s?",
+			 strerror(ENOENT), table->handle.table.name,
+			 family2str(table->handle.family));
+}
+
 /*
  * Symbol expression: parse symbol and evaluate resulting expression.
  */
@@ -193,15 +208,14 @@  static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr)
 
 		table = table_lookup_global(ctx);
 		if (table == NULL)
-			return cmd_error(ctx, &ctx->cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
 
 		set = set_lookup(table, (*expr)->identifier);
 		if (set == NULL)
 			return expr_error(ctx->msgs, *expr,
 					  "Set '%s' does not exist",
 					  (*expr)->identifier);
+
 		new = set_ref_expr_alloc(&(*expr)->location, set);
 		break;
 	}
@@ -2954,9 +2968,7 @@  static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr)
 
 	table = table_lookup_global(ctx);
 	if (table == NULL)
-		return cmd_error(ctx, &ctx->cmd->handle.table.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return table_not_found(ctx);
 
 	set = set_lookup(table, ctx->cmd->handle.set.name);
 	if (set == NULL)
@@ -2979,9 +2991,7 @@  static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 
 	table = table_lookup_global(ctx);
 	if (table == NULL)
-		return cmd_error(ctx, &ctx->cmd->handle.table.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return table_not_found(ctx);
 
 	if (!(set->flags & NFT_SET_INTERVAL) && set->automerge)
 		return set_error(ctx, set, "auto-merge only works with interval sets");
@@ -3062,9 +3072,7 @@  static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
 
 	table = table_lookup_global(ctx);
 	if (table == NULL)
-		return cmd_error(ctx, &ctx->cmd->handle.table.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return table_not_found(ctx);
 
 	ft->hooknum = str2hooknum(NFPROTO_NETDEV, ft->hookstr);
 	if (ft->hooknum == NF_INET_NUMHOOKS)
@@ -3097,9 +3105,7 @@  static int rule_translate_index(struct eval_ctx *ctx, struct rule *rule)
 
 	table = table_lookup(&rule->handle, &ctx->nft->cache);
 	if (!table)
-		return cmd_error(ctx, &rule->handle.table.location,
-				"Could not process rule: %s",
-				strerror(ENOENT));
+		return table_not_found(ctx);
 
 	chain = chain_lookup(table, &rule->handle);
 	if (!chain)
@@ -3204,9 +3210,7 @@  static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
 
 	table = table_lookup_global(ctx);
 	if (table == NULL)
-		return cmd_error(ctx, &ctx->cmd->handle.table.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return table_not_found(ctx);
 
 	if (chain == NULL) {
 		if (chain_lookup(table, &ctx->cmd->handle) == NULL) {
@@ -3403,9 +3407,8 @@  static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_SETELEM:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &ctx->cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		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,
@@ -3428,9 +3431,8 @@  static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd,
 
 	table = table_lookup(&cmd->handle, &ctx->nft->cache);
 	if (table == NULL)
-		return cmd_error(ctx, &cmd->handle.table.location,
-				 "Could not process rule: %s",
-				 strerror(ENOENT));
+		return table_not_found(ctx);
+
 	if (obj_lookup(table, cmd->handle.obj.name, obj_type) == NULL)
 		return cmd_error(ctx, &cmd->handle.obj.location,
 				 "Could not process rule: %s",
@@ -3455,16 +3457,14 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		return 0;
 	case CMD_OBJ_SET:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		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,
@@ -3474,9 +3474,8 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_METER:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_EVAL))
 			return cmd_error(ctx, &cmd->handle.set.location,
@@ -3486,9 +3485,8 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_MAP:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		set = set_lookup(table, cmd->handle.set.name);
 		if (set == NULL || !(set->flags & NFT_SET_MAP))
 			return cmd_error(ctx, &cmd->handle.set.location,
@@ -3498,9 +3496,8 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_CHAIN:
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			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",
@@ -3528,9 +3525,8 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		if (cmd->handle.table.name == NULL)
 			return 0;
 		if (table_lookup(&cmd->handle, &ctx->nft->cache) == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		return 0;
 	case CMD_OBJ_CHAINS:
 	case CMD_OBJ_RULESET:
@@ -3558,9 +3554,8 @@  static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
 		if (cmd->handle.table.name == NULL)
 			return 0;
 		if (table_lookup(&cmd->handle, &ctx->nft->cache) == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
@@ -3591,9 +3586,8 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		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,
@@ -3607,9 +3601,8 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &ctx->cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		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,
@@ -3623,9 +3616,8 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 		table = table_lookup(&cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &ctx->cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			return table_not_found(ctx);
+
 		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,
@@ -3651,9 +3643,8 @@  static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd)
 
 		table = table_lookup(&ctx->cmd->handle, &ctx->nft->cache);
 		if (table == NULL)
-			return cmd_error(ctx, &ctx->cmd->handle.table.location,
-					 "Could not process rule: %s",
-					 strerror(ENOENT));
+			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",
diff --git a/src/rule.c b/src/rule.c
index 524db41e7edb..3553b43def06 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1103,6 +1103,18 @@  struct table *table_lookup(const struct handle *h,
 	return NULL;
 }
 
+struct table *table_lookup_fuzzy(const struct handle *h,
+				 const struct nft_cache *cache)
+{
+	struct table *table;
+
+	list_for_each_entry(table, &cache->list, list) {
+		if (!strcmp(table->handle.table.name, h->table.name))
+			return table;
+	}
+	return NULL;
+}
+
 const char *table_flags_name[TABLE_FLAGS_MAX] = {
 	"dormant",
 };