]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft-ruleparse: Introduce nft_create_target()
authorPhil Sutter <phil@nwl.cc>
Tue, 31 Jan 2023 18:55:57 +0000 (19:55 +0100)
committerPhil Sutter <phil@nwl.cc>
Thu, 10 Aug 2023 11:44:12 +0000 (13:44 +0200)
Like nft_create_match(), this is a small wrapper around the typical
target extension lookup and (standard) init code.

To use it from nft_parse_target() and nft_parse_log(), introduce an
inner variant which accepts the target payload size as parameter.

The call to rule_parse_ops::target callback was problematic with
standard target, because the callbacks initialized
iptables_command_state::jumpto with the target name, "standard" in that
case. Perform its tasks in nft_create_target(), keep it only for bridge
family's special handling of watcher "targets".

Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft-ruleparse-arp.c
iptables/nft-ruleparse-bridge.c
iptables/nft-ruleparse-ipv4.c
iptables/nft-ruleparse-ipv6.c
iptables/nft-ruleparse.c
iptables/nft-ruleparse.h

index b68fb06d8e0f96b977df153275bba851ffd51821..d80ca922955cfec68a5de67d4db2d23332991703 100644 (file)
@@ -164,5 +164,4 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
 struct nft_ruleparse_ops nft_ruleparse_ops_arp = {
        .meta           = nft_arp_parse_meta,
        .payload        = nft_arp_parse_payload,
-       .target         = nft_ipv46_parse_target,
 };
index 50fb92833046abf74e12c86eca9f6208d2136230..c6cc9af5ea198515ed3b9ac7510ebc73c7343f28 100644 (file)
@@ -406,11 +406,10 @@ static void nft_bridge_parse_target(struct xtables_target *t,
        if (strcmp(t->name, "log") == 0 ||
            strcmp(t->name, "nflog") == 0) {
                parse_watcher(t, &cs->match_list, false);
+               cs->jumpto = NULL;
+               cs->target = NULL;
                return;
        }
-
-       cs->target = t;
-       cs->jumpto = t->name;
 }
 
 struct nft_ruleparse_ops nft_ruleparse_ops_bridge = {
index c87e159cc5fec69043f5fea60b06f33731b4f36f..491cbf42c7754e00db4d6cf2aed214cae0aca720 100644 (file)
@@ -131,5 +131,4 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
 struct nft_ruleparse_ops nft_ruleparse_ops_ipv4 = {
        .meta           = nft_ipv4_parse_meta,
        .payload        = nft_ipv4_parse_payload,
-       .target         = nft_ipv46_parse_target,
 };
index af55420b737663156203418e658a4a94fb9400fc..7581b8636e601f30d29a6bb35b94214421ecd49f 100644 (file)
@@ -108,5 +108,4 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
 struct nft_ruleparse_ops nft_ruleparse_ops_ipv6 = {
        .meta           = nft_ipv6_parse_meta,
        .payload        = nft_ipv6_parse_payload,
-       .target         = nft_ipv46_parse_target,
 };
index edbbfa40e9c43bfe8583455b9ab44b5b1b4a55b2..a5eb6d098084a7248ad7ab786f195d908d31017d 100644 (file)
@@ -84,6 +84,40 @@ nft_create_match(struct nft_xt_ctx *ctx,
        return match->m->data;
 }
 
+static void *
+__nft_create_target(struct nft_xt_ctx *ctx, const char *name, size_t tgsize)
+{
+       struct xtables_target *target;
+       size_t size;
+
+       target = xtables_find_target(name, XTF_TRY_LOAD);
+       if (!target)
+               return NULL;
+
+       size = XT_ALIGN(sizeof(*target->t)) + tgsize ?: target->size;
+
+       target->t = xtables_calloc(1, size);
+       target->t->u.target_size = size;
+       target->t->u.user.revision = target->revision;
+       strcpy(target->t->u.user.name, name);
+
+       xs_init_target(target);
+
+       ctx->cs->jumpto = name;
+       ctx->cs->target = target;
+
+       if (ctx->h->ops->rule_parse->target)
+               ctx->h->ops->rule_parse->target(target, ctx->cs);
+
+       return target->t->data;
+}
+
+void *
+nft_create_target(struct nft_xt_ctx *ctx, const char *name)
+{
+       return __nft_create_target(ctx, name, 0);
+}
+
 static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters)
 {
        counters->pcnt = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS);
@@ -123,11 +157,8 @@ static bool nft_parse_meta_set_common(struct nft_xt_ctx* ctx,
 static void nft_parse_meta_set(struct nft_xt_ctx *ctx,
                               struct nftnl_expr *e)
 {
-       struct xtables_target *target;
        struct nft_xt_ctx_reg *sreg;
        enum nft_registers sregnum;
-       struct xt_entry_target *t;
-       unsigned int size;
        const char *targname;
 
        sregnum = nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG);
@@ -153,22 +184,8 @@ static void nft_parse_meta_set(struct nft_xt_ctx *ctx,
                return;
        }
 
-       target = xtables_find_target(targname, XTF_TRY_LOAD);
-       if (target == NULL) {
+       if (!nft_create_target(ctx, targname))
                ctx->errmsg = "target TRACE not found";
-               return;
-       }
-
-       size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
-
-       t = xtables_calloc(1, size);
-       t->u.target_size = size;
-       t->u.user.revision = target->revision;
-       strcpy(t->u.user.name, targname);
-
-       target->t = t;
-
-       ctx->h->ops->rule_parse->target(target, ctx->cs);
 }
 
 static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -515,8 +532,6 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 {
        const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
        struct iptables_command_state *cs = ctx->cs;
-       struct xt_entry_target *t;
-       uint32_t size;
        int verdict;
 
        if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
@@ -566,18 +581,8 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
                return;
        }
 
-       cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
-       if (!cs->target) {
+       if (!nft_create_target(ctx, cs->jumpto))
                ctx->errmsg = "verdict extension not found";
-               return;
-       }
-
-       size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
-       t = xtables_calloc(1, size);
-       t->u.target_size = size;
-       t->u.user.revision = cs->target->revision;
-       strcpy(t->u.user.name, cs->jumpto);
-       cs->target->t = t;
 }
 
 static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -624,27 +629,13 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
        uint32_t tg_len;
        const char *targname = nftnl_expr_get_str(e, NFTNL_EXPR_TG_NAME);
        const void *targinfo = nftnl_expr_get(e, NFTNL_EXPR_TG_INFO, &tg_len);
-       struct xtables_target *target;
-       struct xt_entry_target *t;
-       size_t size;
+       void *data;
 
-       target = xtables_find_target(targname, XTF_TRY_LOAD);
-       if (target == NULL) {
+       data = __nft_create_target(ctx, targname, tg_len);
+       if (!data)
                ctx->errmsg = "target extension not found";
-               return;
-       }
-
-       size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
-
-       t = xtables_calloc(1, size);
-       memcpy(&t->data, targinfo, tg_len);
-       t->u.target_size = size;
-       t->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
-       strcpy(t->u.user.name, target->name);
-
-       target->t = t;
-
-       ctx->h->ops->rule_parse->target(target, ctx->cs);
+       else
+               memcpy(data, targinfo, tg_len);
 }
 
 static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -684,9 +675,6 @@ static void nft_parse_lookup(struct nft_xt_ctx *ctx, struct nft_handle *h,
 
 static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 {
-       struct xtables_target *target;
-       struct xt_entry_target *t;
-       size_t target_size;
        /*
         * In order to handle the longer log-prefix supported by nft, instead of
         * using struct xt_nflog_info, we use a struct with a compatible layout, but
@@ -703,6 +691,8 @@ static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
                .group     = nftnl_expr_get_u16(e, NFTNL_EXPR_LOG_GROUP),
                .threshold = nftnl_expr_get_u16(e, NFTNL_EXPR_LOG_QTHRESHOLD),
        };
+       void *data;
+
        if (nftnl_expr_is_set(e, NFTNL_EXPR_LOG_SNAPLEN)) {
                info.len = nftnl_expr_get_u32(e, NFTNL_EXPR_LOG_SNAPLEN);
                info.flags = XT_NFLOG_F_COPY_LEN;
@@ -711,25 +701,12 @@ static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
                snprintf(info.prefix, sizeof(info.prefix), "%s",
                         nftnl_expr_get_str(e, NFTNL_EXPR_LOG_PREFIX));
 
-       target = xtables_find_target("NFLOG", XTF_TRY_LOAD);
-       if (target == NULL) {
+       data = __nft_create_target(ctx, "NFLOG",
+                                  XT_ALIGN(sizeof(struct xt_nflog_info_nft)));
+       if (!data)
                ctx->errmsg = "NFLOG target extension not found";
-               return;
-       }
-
-       target_size = XT_ALIGN(sizeof(struct xt_entry_target)) +
-                     XT_ALIGN(sizeof(struct xt_nflog_info_nft));
-
-       t = xtables_calloc(1, target_size);
-       t->u.target_size = target_size;
-       strcpy(t->u.user.name, target->name);
-       t->u.user.revision = target->revision;
-
-       target->t = t;
-
-       memcpy(&target->t->data, &info, sizeof(info));
-
-       ctx->h->ops->rule_parse->target(target, ctx->cs);
+       else
+               memcpy(data, &info, sizeof(info));
 }
 
 static void nft_parse_udp_range(struct nft_xt_ctx *ctx,
@@ -1137,13 +1114,6 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
        return 0;
 }
 
-void nft_ipv46_parse_target(struct xtables_target *t,
-                           struct iptables_command_state *cs)
-{
-       cs->target = t;
-       cs->jumpto = t->name;
-}
-
 int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
                 struct iptables_command_state *cs)
 {
index fd083c08ff343c91a2242bb870b1b557f99aafef..25ce05d2e864428d9d128691e181ff4228e81b8c 100644 (file)
@@ -117,6 +117,8 @@ extern struct nft_ruleparse_ops nft_ruleparse_ops_ipv6;
 void *nft_create_match(struct nft_xt_ctx *ctx,
                       struct iptables_command_state *cs,
                       const char *name, bool reuse);
+void *nft_create_target(struct nft_xt_ctx *ctx, const char *name);
+
 
 bool nft_rule_to_iptables_command_state(struct nft_handle *h,
                                        const struct nftnl_rule *r,
@@ -129,9 +131,6 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
               char *iniface, unsigned char *iniface_mask, char *outiface,
               unsigned char *outiface_mask, uint8_t *invflags);
 
-void nft_ipv46_parse_target(struct xtables_target *t,
-                           struct iptables_command_state *cs);
-
 int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
                 struct iptables_command_state *cs);