All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft] src: combine extended netlink error reporting with mispelling support
@ 2020-02-18 12:46 Pablo Neira Ayuso
  0 siblings, 0 replies; only message in thread
From: Pablo Neira Ayuso @ 2020-02-18 12:46 UTC (permalink / raw)
  To: netfilter-devel

Preliminary support to combine extended netlink error reporting, e.g.

 # nft delete table twst
 Error: No such file or directory; did you mean table ‘test’ in family ip?
 delete table twst
              ^^^^

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/Makefile.am |   1 +
 src/cmd.c           | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/libnftables.c   |  23 +-------
 3 files changed, 160 insertions(+), 21 deletions(-)
 create mode 100644 src/cmd.c

diff --git a/include/Makefile.am b/include/Makefile.am
index 04a4a619a530..42f24f35ce7a 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -3,6 +3,7 @@ SUBDIRS =		linux		\
 
 noinst_HEADERS = 	cli.h		\
 			cache.h		\
+			cmd.h		\
 			datatype.h	\
 			expression.h	\
 			fib.h		\
diff --git a/src/cmd.c b/src/cmd.c
new file mode 100644
index 000000000000..5a50632e28a0
--- /dev/null
+++ b/src/cmd.c
@@ -0,0 +1,157 @@
+#include <nftables/libnftables.h>
+#include <erec.h>
+#include <mnl.h>
+#include <cmd.h>
+#include <parser.h>
+#include <utils.h>
+#include <iface.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int nft_cmd_enoent_table(struct netlink_ctx *ctx, const struct cmd *cmd,
+				struct location *loc)
+{
+	struct table *table;
+
+	table = table_lookup_fuzzy(&cmd->handle, &ctx->nft->cache);
+	if (!table)
+		return 0;
+
+	netlink_io_error(ctx, loc, "%s; did you mean table ‘%s’ in family %s?",
+			 strerror(ENOENT), table->handle.table.name,
+			 family2str(table->handle.family));
+	return 1;
+}
+
+static int nft_cmd_enoent_chain(struct netlink_ctx *ctx, const struct cmd *cmd,
+				struct location *loc)
+{
+	const struct table *table;
+	struct chain *chain;
+
+	chain = chain_lookup_fuzzy(&cmd->handle, &ctx->nft->cache, &table);
+	if (!chain)
+		return 0;
+
+	netlink_io_error(ctx, loc, "%s; did you mean table ‘%s’ in family %s?",
+			 strerror(ENOENT), chain->handle.chain.name,
+			 family2str(table->handle.family),
+			 table->handle.table.name);
+	return 1;
+}
+
+static int nft_cmd_enoent_set(struct netlink_ctx *ctx, const struct cmd *cmd,
+			      struct location *loc)
+{
+	const struct table *table;
+	struct set *set;
+
+	set = set_lookup_fuzzy(cmd->handle.set.name, &ctx->nft->cache, &table);
+	if (!set)
+		return 0;
+
+	netlink_io_error(ctx, loc, "%s; did you mean %s ‘%s’ in table %s ‘%s’?",
+			 strerror(ENOENT),
+			 set_is_map(set->flags) ? "map" : "set",
+			 set->handle.set.name,
+			 family2str(set->handle.family),
+			 table->handle.table.name);
+	return 1;
+}
+
+static int nft_cmd_enoent_obj(struct netlink_ctx *ctx, const struct cmd *cmd,
+			      struct location *loc)
+{
+	const struct table *table;
+	struct obj *obj;
+
+	obj = obj_lookup_fuzzy(cmd->handle.obj.name, &ctx->nft->cache, &table);
+	if (!obj)
+		return 0;
+
+	netlink_io_error(ctx, loc, "%s; did you mean obj ‘%s’ in table %s ‘%s’?",
+			 strerror(ENOENT), obj->handle.obj.name,
+			 family2str(obj->handle.family),
+			 table->handle.table.name);
+	return 1;
+}
+
+static int nft_cmd_enoent_flowtable(struct netlink_ctx *ctx,
+				    const struct cmd *cmd, struct location *loc)
+{
+	const struct table *table;
+	struct flowtable *ft;
+
+	ft = flowtable_lookup_fuzzy(cmd->handle.flowtable.name,
+				    &ctx->nft->cache, &table);
+	if (!ft)
+		return 0;
+
+	netlink_io_error(ctx, loc, "%s; did you mean flowtable ‘%s’ in table %s ‘%s’?",
+			 strerror(ENOENT), ft->handle.flowtable.name,
+			 family2str(ft->handle.family),
+			 table->handle.table.name);
+	return 1;
+}
+
+static void nft_cmd_enoent(struct netlink_ctx *ctx, const struct cmd *cmd,
+			   struct location *loc, int err)
+{
+	int ret = 0;
+
+	switch (cmd->obj) {
+	case CMD_OBJ_TABLE:
+		ret = nft_cmd_enoent_table(ctx, cmd, loc);
+		break;
+	case CMD_OBJ_CHAIN:
+		ret = nft_cmd_enoent_chain(ctx, cmd, loc);
+		break;
+	case CMD_OBJ_SET:
+		ret = nft_cmd_enoent_set(ctx, cmd, loc);
+		break;
+	case CMD_OBJ_COUNTER:
+	case CMD_OBJ_QUOTA:
+	case CMD_OBJ_CT_HELPER:
+	case CMD_OBJ_CT_TIMEOUT:
+	case CMD_OBJ_LIMIT:
+	case CMD_OBJ_SECMARK:
+	case CMD_OBJ_CT_EXPECT:
+	case CMD_OBJ_SYNPROXY:
+		ret = nft_cmd_enoent_obj(ctx, cmd, loc);
+		break;
+	case CMD_OBJ_FLOWTABLE:
+		ret = nft_cmd_enoent_flowtable(ctx, cmd, loc);
+		break;
+	default:
+		break;
+	}
+
+	if (ret)
+		return;
+
+	netlink_io_error(ctx, loc, "Could not process rule: %s", strerror(err));
+}
+
+void nft_cmd_error(struct netlink_ctx *ctx, struct cmd *cmd,
+		   struct mnl_err *err)
+{
+	struct location *loc = NULL;
+	int i;
+
+	for (i = 0; i < cmd->num_attrs; i++) {
+		if (!cmd->attr[i].offset)
+			break;
+		if (cmd->attr[i].offset == err->offset)
+			loc = cmd->attr[i].location;
+	}
+	if (!loc)
+		loc = &cmd->location;
+
+	if (err->err == ENOENT) {
+		nft_cmd_enoent(ctx, cmd, loc, err->err);
+	} else {
+		netlink_io_error(ctx, loc, "Could not process rule: %s",
+				 strerror(err->err));
+	}
+}
diff --git a/src/libnftables.c b/src/libnftables.c
index eaa4736c397d..32da0a29ee21 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -12,30 +12,11 @@
 #include <parser.h>
 #include <utils.h>
 #include <iface.h>
-
+#include <cmd.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
-static void nft_error(struct netlink_ctx *ctx, struct cmd *cmd,
-		      struct mnl_err *err)
-{
-	struct location *loc = NULL;
-	int i;
-
-	for (i = 0; i < cmd->num_attrs; i++) {
-		if (!cmd->attr[i].offset)
-			break;
-		if (cmd->attr[i].offset == err->offset)
-			loc = cmd->attr[i].location;
-	}
-	if (!loc)
-		loc = &cmd->location;
-
-	netlink_io_error(ctx, loc, "Could not process rule: %s",
-			 strerror(err->err));
-}
-
 static int nft_netlink(struct nft_ctx *nft,
 		       struct list_head *cmds, struct list_head *msgs,
 		       struct mnl_socket *nf_sock)
@@ -87,7 +68,7 @@ static int nft_netlink(struct nft_ctx *nft,
 		list_for_each_entry(cmd, cmds, list) {
 			if (err->seqnum == cmd->seqnum ||
 			    err->seqnum == batch_seqnum) {
-				nft_error(&ctx, cmd, err);
+				nft_cmd_error(&ctx, cmd, err);
 				errno = err->err;
 				if (err->seqnum == cmd->seqnum) {
 					mnl_err_list_free(err);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-02-18 12:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-18 12:46 [PATCH nft] src: combine extended netlink error reporting with mispelling support Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.