[iptables PATCH 1/3] nft-shared: Lookup matches in iptables_command_state

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Some matches may turn into multiple nft statements (naturally or via
translation). Such statements must parse into a single extension again
in order to rebuild the rule as it was.

Introduce nft_find_match_in_cs() to iterate through the lists and drop
tcp/udp port match caching in struct nft_xt_ctx which is not needed
anymore.

Note: Match reuse is not enabled unconditionally for all matches,
because iptables supports having multiple instances of the same
extension.

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 iptables/nft-shared.c | 70 +++++++++++++++++++++++++------------------
 iptables/nft-shared.h |  4 ---
 2 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 4a7b5406892c4..df3cc6ac994cf 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -304,7 +304,7 @@ static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned
 static struct xtables_match *
 nft_create_match(struct nft_xt_ctx *ctx,
 		 struct iptables_command_state *cs,
-		 const char *name);
+		 const char *name, bool reuse);
 
 static uint32_t get_meta_mask(struct nft_xt_ctx *ctx, enum nft_registers sreg)
 {
@@ -322,7 +322,7 @@ static int parse_meta_mark(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	struct xtables_match *match;
 	uint32_t value;
 
-	match = nft_create_match(ctx, ctx->cs, "mark");
+	match = nft_create_match(ctx, ctx->cs, "mark", false);
 	if (!match)
 		return -1;
 
@@ -344,7 +344,7 @@ static int parse_meta_pkttype(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	struct xtables_match *match;
 	uint8_t value;
 
-	match = nft_create_match(ctx, ctx->cs, "pkttype");
+	match = nft_create_match(ctx, ctx->cs, "pkttype", false);
 	if (!match)
 		return -1;
 
@@ -641,15 +641,39 @@ static void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	dreg->bitwise.set = true;
 }
 
+static struct xtables_match *
+nft_find_match_in_cs(struct iptables_command_state *cs, const char *name)
+{
+	struct xtables_rule_match *rm;
+	struct ebt_match *ebm;
+
+	for (ebm = cs->match_list; ebm; ebm = ebm->next) {
+		if (ebm->ismatch &&
+		    !strcmp(ebm->u.match->m->u.user.name, name))
+			return ebm->u.match;
+	}
+	for (rm = cs->matches; rm; rm = rm->next) {
+		if (!strcmp(rm->match->m->u.user.name, name))
+			return rm->match;
+	}
+	return NULL;
+}
+
 static struct xtables_match *
 nft_create_match(struct nft_xt_ctx *ctx,
 		 struct iptables_command_state *cs,
-		 const char *name)
+		 const char *name, bool reuse)
 {
 	struct xtables_match *match;
 	struct xt_entry_match *m;
 	unsigned int size;
 
+	if (reuse) {
+		match = nft_find_match_in_cs(cs, name);
+		if (match)
+			return match;
+	}
+
 	match = xtables_find_match(name, XTF_TRY_LOAD,
 				   &cs->matches);
 	if (!match)
@@ -671,38 +695,26 @@ nft_create_match(struct nft_xt_ctx *ctx,
 static struct xt_udp *nft_udp_match(struct nft_xt_ctx *ctx,
 			            struct iptables_command_state *cs)
 {
-	struct xt_udp *udp = ctx->tcpudp.udp;
 	struct xtables_match *match;
 
-	if (!udp) {
-		match = nft_create_match(ctx, cs, "udp");
-		if (!match)
-			return NULL;
-
-		udp = (void*)match->m->data;
-		ctx->tcpudp.udp = udp;
-	}
+	match = nft_create_match(ctx, cs, "udp", true);
+	if (!match)
+		return NULL;
 
-	return udp;
+	return (struct xt_udp *)match->m->data;
 }
 
 static struct xt_tcp *nft_tcp_match(struct nft_xt_ctx *ctx,
 			            struct iptables_command_state *cs)
 {
-	struct xt_tcp *tcp = ctx->tcpudp.tcp;
 	struct xtables_match *match;
 
-	if (!tcp) {
-		match = nft_create_match(ctx, cs, "tcp");
-		if (!match) {
-			ctx->errmsg = "tcp match extension not found";
-			return NULL;
-		}
-		tcp = (void*)match->m->data;
-		ctx->tcpudp.tcp = tcp;
+	match = nft_create_match(ctx, cs, "tcp", true);
+	if (!match) {
+		ctx->errmsg = "tcp match extension not found";
+		return NULL;
 	}
-
-	return tcp;
+	return (struct xt_tcp *)match->m->data;
 }
 
 static void nft_parse_udp_range(struct nft_xt_ctx *ctx,
@@ -872,14 +884,14 @@ static void nft_parse_icmp(struct nft_xt_ctx *ctx,
 
 	switch (ctx->h->family) {
 	case NFPROTO_IPV4:
-		match = nft_create_match(ctx, cs, "icmp");
+		match = nft_create_match(ctx, cs, "icmp", false);
 		break;
 	case NFPROTO_IPV6:
 		if (icmp.type == UINT8_MAX) {
 			ctx->errmsg = "icmp6 code with any type match not supported";
 			return;
 		}
-		match = nft_create_match(ctx, cs, "icmp6");
+		match = nft_create_match(ctx, cs, "icmp6", false);
 		break;
 	default:
 		ctx->errmsg = "unexpected family for icmp match";
@@ -1640,10 +1652,10 @@ int nft_parse_hl(struct nft_xt_ctx *ctx,
 	 */
 	switch (ctx->h->family) {
 	case NFPROTO_IPV4:
-		match = nft_create_match(ctx, ctx->cs, "ttl");
+		match = nft_create_match(ctx, ctx->cs, "ttl", false);
 		break;
 	case NFPROTO_IPV6:
-		match = nft_create_match(ctx, ctx->cs, "hl");
+		match = nft_create_match(ctx, ctx->cs, "hl", false);
 		break;
 	default:
 		return -1;
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 07d39131cb0d6..b8bc1a6ce2e93 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -76,10 +76,6 @@ struct nft_xt_ctx {
 	struct nft_handle *h;
 	uint32_t flags;
 	const char *table;
-	union {
-		struct xt_tcp *tcp;
-		struct xt_udp *udp;
-	} tcpudp;
 
 	struct nft_xt_ctx_reg regs[1 + 16];
 
-- 
2.38.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux