]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
libnftables: location-based error reporting for chain type
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 19 May 2021 19:57:41 +0000 (21:57 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 19 May 2021 22:13:35 +0000 (00:13 +0200)
Store the location of the chain type for better error reporting.

Several users that compile custom kernels reported that error
reporting is misleading when accidentally selecting
CONFIG_NFT_NAT=n.

After this patch, a better hint is provided:

 # nft 'add chain x y { type nat hook prerouting priority dstnat; }'
 Error: Could not process rule: No such file or directory
 add chain x y { type nat hook prerouting priority dstnat; }
                      ^^^

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/rule.h
src/mnl.c
src/netlink.c
src/parser_bison.y
src/parser_json.c
src/rule.c

index fbd2c9a79b4740d356d55a1f3ecc33b8279c7c77..f469db55bf601ddc8f1a9f6eeb6f4bbb517487e3 100644 (file)
@@ -213,6 +213,11 @@ struct hook_spec {
        unsigned int    num;
 };
 
+struct chain_type_spec {
+       struct location loc;
+       const char      *str;
+};
+
 /**
  * struct chain - nftables chain
  *
@@ -242,7 +247,7 @@ struct chain {
                struct prio_spec        priority;
                struct hook_spec        hook;
                struct expr             *policy;
-               const char              *type;
+               struct chain_type_spec  type;
                const char              **dev_array;
                struct expr             *dev_expr;
                int                     dev_array_len;
index 1a8e8105707bdc8aff090eac74bd46fba7a3da84..ef45cbd193f9ac7da0ac22ef07a3fbe9d3aee659 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -698,7 +698,7 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
                                        BYTEORDER_HOST_ENDIAN, sizeof(int));
                        nftnl_chain_set_s32(nlc, NFTNL_CHAIN_PRIO, priority);
                        nftnl_chain_set_str(nlc, NFTNL_CHAIN_TYPE,
-                                           cmd->chain->type);
+                                           cmd->chain->type.str);
                }
                if (cmd->chain->dev_expr) {
                        dev_array = xmalloc(sizeof(char *) * 8);
@@ -764,6 +764,12 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
                        nftnl_chain_set_u32(nlc, NFTNL_CHAIN_FLAGS, cmd->chain->flags);
        }
 
+       if (cmd->chain && cmd->chain->flags & CHAIN_F_BASECHAIN) {
+               nftnl_chain_unset(nlc, NFTNL_CHAIN_TYPE);
+               cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->chain->type.loc);
+               mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, cmd->chain->type.str);
+       }
+
        if (cmd->chain && cmd->chain->policy) {
                mpz_export_data(&policy, cmd->chain->policy->value,
                                BYTEORDER_HOST_ENDIAN, sizeof(int));
index 8cdd6d818221867ee169c2839ba97e5f8253b624..6b6fe27762d5ab5b48d67b9381a220b0e867c5c8 100644 (file)
@@ -552,7 +552,7 @@ struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
                                                    BYTEORDER_HOST_ENDIAN,
                                                    sizeof(int) * BITS_PER_BYTE,
                                                    &priority);
-               chain->type          =
+               chain->type.str =
                        xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TYPE));
                policy = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_POLICY);
                chain->policy = constant_expr_alloc(&netlink_location,
index 957fb528665728f6d55f7d7ac9243fc41a363aa8..3a11e6971177e3d0428ad8c7e471bd5dafcf36f0 100644 (file)
@@ -2301,7 +2301,8 @@ hook_spec         :       TYPE            STRING          HOOK            STRING          dev_spec        prio_spec
                                        xfree($2);
                                        YYERROR;
                                }
-                               $<chain>0->type         = xstrdup(chain_type);
+                               $<chain>0->type.loc = @2;
+                               $<chain>0->type.str = xstrdup(chain_type);
                                xfree($2);
 
                                $<chain>0->loc = @$;
index 9b79497c61412a63dd92e45b0bfcbdcc5ea97615..fd0d4fd85a2d488ca2eb3cbe9df5d409ac0ba646 100644 (file)
@@ -2790,7 +2790,7 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root,
 
        chain = chain_alloc(NULL);
        chain->flags |= CHAIN_F_BASECHAIN;
-       chain->type = xstrdup(type);
+       chain->type.str = xstrdup(type);
        chain->priority.expr = constant_expr_alloc(int_loc, &integer_type,
                                                   BYTEORDER_HOST_ENDIAN,
                                                   sizeof(int) * BITS_PER_BYTE,
index 07a541a20bb9c00fe977ab42e1739b53f64df97e..dda1718d69ef0091a4e53dc2298eb02d2ec74104 100644 (file)
@@ -730,7 +730,7 @@ void chain_free(struct chain *chain)
                rule_free(rule);
        handle_free(&chain->handle);
        scope_release(&chain->scope);
-       xfree(chain->type);
+       xfree(chain->type.str);
        expr_free(chain->dev_expr);
        for (i = 0; i < chain->dev_array_len; i++)
                xfree(chain->dev_array[i]);
@@ -1024,7 +1024,7 @@ static void chain_print_declaration(const struct chain *chain,
                nft_print(octx, "\n\t\tcomment \"%s\"", chain->comment);
        nft_print(octx, "\n");
        if (chain->flags & CHAIN_F_BASECHAIN) {
-               nft_print(octx, "\t\ttype %s hook %s", chain->type,
+               nft_print(octx, "\t\ttype %s hook %s", chain->type.str,
                          hooknum2str(chain->handle.family, chain->hook.num));
                if (chain->dev_array_len == 1) {
                        nft_print(octx, " device \"%s\"", chain->dev_array[0]);
@@ -1085,7 +1085,7 @@ void chain_print_plain(const struct chain *chain, struct output_ctx *octx)
                mpz_export_data(&policy, chain->policy->value,
                                BYTEORDER_HOST_ENDIAN, sizeof(int));
                nft_print(octx, " { type %s hook %s priority %s; policy %s; }",
-                         chain->type, chain->hook.name,
+                         chain->type.str, chain->hook.name,
                          prio2str(octx, priobuf, sizeof(priobuf),
                                   chain->handle.family, chain->hook.num,
                                   chain->priority.expr),