diff mbox series

[iptables] nft-ruleparse: parse meta mark set as MARK target

Message ID 20230803193917.26779-1-fw@strlen.de
State Accepted, archived
Headers show
Series [iptables] nft-ruleparse: parse meta mark set as MARK target | expand

Commit Message

Florian Westphal Aug. 3, 2023, 7:39 p.m. UTC
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@strlen.de>
---
 iptables/nft-ruleparse.c | 83 +++++++++++++++++++++++++++-------------
 1 file changed, 56 insertions(+), 27 deletions(-)

Comments

Phil Sutter Aug. 4, 2023, 4:21 p.m. UTC | #1
On Thu, Aug 03, 2023 at 09:39:13PM +0200, Florian Westphal wrote:
> 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

Intentionally not "Closes:"?

> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  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)

Please hold back a bit, I have a better implementation of this function
lingering locally. Will adjust and submit both in a minute.

Thanks, Phil
Florian Westphal Aug. 4, 2023, 4:22 p.m. UTC | #2
Phil Sutter <phil@nwl.cc> wrote:
> On Thu, Aug 03, 2023 at 09:39:13PM +0200, Florian Westphal wrote:
> > 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
> 
> Intentionally not "Closes:"?

Yes, its unfixable.
diff mbox series

Patch

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)