Mixing nftables and iptables-nft in the same table doesn't work, but some people do this. v1.8.8 ignored rules it could not represent in iptables syntax, v1.8.9 bails in this case. Add parsing of meta mark expressions so iptables-nft can render them as -j MARK rules. This is flawed, nft has features that have no corresponding syntax in iptables, but we can't undo this. Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1659 Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- iptables/nft-ruleparse.c | 83 +++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/iptables/nft-ruleparse.c b/iptables/nft-ruleparse.c index edbbfa40e9c4..44b9bcc268f4 100644 --- a/iptables/nft-ruleparse.c +++ b/iptables/nft-ruleparse.c @@ -84,6 +84,37 @@ nft_create_match(struct nft_xt_ctx *ctx, return match->m->data; } +static void * +nft_create_target(struct nft_xt_ctx *ctx, + struct iptables_command_state *cs, + const char *name) +{ + struct xtables_target *target; + struct xt_entry_target *t; + unsigned int size; + + target = xtables_find_target(name, XTF_TRY_LOAD); + if (!target) { + ctx->errmsg = "target not found"; + return NULL; + } + + 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, name); + + target->t = t; + + xs_init_target(target); + + ctx->h->ops->rule_parse->target(target, ctx->cs); + + return target->t->data; +} + static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters) { counters->pcnt = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS); @@ -112,23 +143,14 @@ static bool nft_parse_meta_set_common(struct nft_xt_ctx* ctx, return false; } - if (sreg->immediate.data[0] == 0) { - ctx->errmsg = "meta sreg immediate is 0"; - return false; - } - return true; } 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); sreg = nft_xt_ctx_get_sreg(ctx, sregnum); @@ -140,7 +162,13 @@ static void nft_parse_meta_set(struct nft_xt_ctx *ctx, if (!nft_parse_meta_set_common(ctx, sreg)) return; - targname = "TRACE"; + if (sreg->immediate.data[0] == 0) { + ctx->errmsg = "meta sreg immediate is 0"; + return; + } + + if (nft_create_target(ctx, ctx->cs, "TRACE")) + return; break; case NFT_META_BRI_BROUTE: if (!nft_parse_meta_set_common(ctx, sreg)) @@ -148,27 +176,28 @@ static void nft_parse_meta_set(struct nft_xt_ctx *ctx, ctx->cs->jumpto = "DROP"; return; - default: - ctx->errmsg = "meta sreg key not supported"; - return; - } - - target = xtables_find_target(targname, XTF_TRY_LOAD); - if (target == NULL) { - ctx->errmsg = "target TRACE not found"; - return; - } + case NFT_META_MARK: { + struct xt_mark_tginfo2 *mt; - size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size; + if (!nft_parse_meta_set_common(ctx, sreg)) + return; - t = xtables_calloc(1, size); - t->u.target_size = size; - t->u.user.revision = target->revision; - strcpy(t->u.user.name, targname); + mt = nft_create_target(ctx, ctx->cs, "MARK"); + if (!mt) + return; - target->t = t; + mt->mark = sreg->immediate.data[0]; + if (sreg->bitwise.set) + mt->mask = sreg->bitwise.mask[0]; + else + mt->mask = ~0u; - ctx->h->ops->rule_parse->target(target, ctx->cs); + return; + } + default: + ctx->errmsg = "meta sreg key not supported"; + return; + } } static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e) -- 2.41.0