]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: combine extended netlink error reporting with mispelling support
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 18 Feb 2020 11:59:24 +0000 (12:59 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 19 Feb 2020 16:28:52 +0000 (17:28 +0100)
Preliminary support: only for the deletion command, 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
src/cmd.c [new file with mode: 0644]
src/libnftables.c

index 04a4a619a5302077d6f8401e5a5aa2d4aee06563..42f24f35ce7a59ea4d72b5596b2063839ba79ccd 100644 (file)
@@ -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 (file)
index 0000000..c8ea449
--- /dev/null
+++ b/src/cmd.c
@@ -0,0 +1,159 @@
+#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) {
+               if (err->err == ENOENT) {
+                       nft_cmd_enoent(ctx, cmd, loc, err->err);
+                       return;
+               }
+       } else {
+               loc = &cmd->location;
+       }
+
+       netlink_io_error(ctx, loc, "Could not process rule: %s",
+                        strerror(err->err));
+}
index eaa4736c397ddebc60047cf45250022c6666ad78..32da0a29ee215bbf7a9810c0eeef4c7a6c604d2f 100644 (file)
 #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);