netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
@ 2023-07-12  9:59 Pablo Neira Ayuso
  2023-07-12 11:05 ` Igor Raits
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Pablo Neira Ayuso @ 2023-07-12  9:59 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw, igor, phil

Add context structure to improve bridge among support which creates an
anonymous set. This context structure specifies the command and it
allows to optionally store a anonymous set.

Use this context to generate native bytecode only if this is an
add/insert/replace command.

This fixes a dangling anonymous set that is created on rule removal.

Fixes: 26753888720d ("nft: bridge: Rudimental among extension support")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
This test passes tests/py and tests/shell.

 iptables/nft-arp.c    |  4 ++--
 iptables/nft-bridge.c |  9 ++++----
 iptables/nft-cmd.c    |  6 ++++-
 iptables/nft-ipv4.c   |  6 ++---
 iptables/nft-ipv6.c   |  6 ++---
 iptables/nft-shared.h |  5 ++--
 iptables/nft.c        | 54 ++++++++++++++++++++++++++++---------------
 iptables/nft.h        |  9 +++++---
 8 files changed, 62 insertions(+), 37 deletions(-)

diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 265de5f88cea..9868966a0368 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -40,8 +40,8 @@ static bool need_devaddr(struct arpt_devaddr_info *info)
 	return false;
 }
 
-static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r,
-		       struct iptables_command_state *cs)
+static int nft_arp_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
+		       struct nftnl_rule *r, struct iptables_command_state *cs)
 {
 	struct arpt_entry *fw = &cs->arp;
 	uint32_t op;
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 6e50950774e6..391a8ab723c1 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -138,7 +138,8 @@ static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
 
 static int
 nft_bridge_add_match(struct nft_handle *h, const struct ebt_entry *fw,
-		     struct nftnl_rule *r, struct xt_entry_match *m)
+		     struct nft_rule_ctx *ctx, struct nftnl_rule *r,
+		     struct xt_entry_match *m)
 {
 	if (!strcmp(m->u.user.name, "802_3") && !(fw->bitmask & EBT_802_3))
 		xtables_error(PARAMETER_PROBLEM,
@@ -152,10 +153,10 @@ nft_bridge_add_match(struct nft_handle *h, const struct ebt_entry *fw,
 		xtables_error(PARAMETER_PROBLEM,
 			      "For IPv6 filtering the protocol must be specified as IPv6.");
 
-	return add_match(h, r, m);
+	return add_match(h, ctx, r, m);
 }
 
-static int nft_bridge_add(struct nft_handle *h,
+static int nft_bridge_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
 			  struct nftnl_rule *r,
 			  struct iptables_command_state *cs)
 {
@@ -217,7 +218,7 @@ static int nft_bridge_add(struct nft_handle *h,
 
 	for (iter = cs->match_list; iter; iter = iter->next) {
 		if (iter->ismatch) {
-			if (nft_bridge_add_match(h, fw, r, iter->u.match->m))
+			if (nft_bridge_add_match(h, fw, ctx, r, iter->u.match->m))
 				break;
 		} else {
 			if (add_target(r, iter->u.watcher->t))
diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
index 7b2fc3a59578..8a824586ad8c 100644
--- a/iptables/nft-cmd.c
+++ b/iptables/nft-cmd.c
@@ -14,12 +14,16 @@
 #include <xtables.h>
 #include "nft.h"
 #include "nft-cmd.h"
+#include <libnftnl/set.h>
 
 struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
 			    const char *table, const char *chain,
 			    struct iptables_command_state *state,
 			    int rulenum, bool verbose)
 {
+	struct nft_rule_ctx ctx = {
+		.command = command,
+	};
 	struct nftnl_rule *rule;
 	struct nft_cmd *cmd;
 
@@ -33,7 +37,7 @@ struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
 	cmd->verbose = verbose;
 
 	if (state) {
-		rule = nft_rule_new(h, chain, table, state);
+		rule = nft_rule_new(h, &ctx, chain, table, state);
 		if (!rule) {
 			nft_cmd_free(cmd);
 			return NULL;
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 2a5d25d8694e..2f10220edd50 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -26,8 +26,8 @@
 #include "nft.h"
 #include "nft-shared.h"
 
-static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
-			struct iptables_command_state *cs)
+static int nft_ipv4_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
+			struct nftnl_rule *r, struct iptables_command_state *cs)
 {
 	struct xtables_rule_match *matchp;
 	uint32_t op;
@@ -84,7 +84,7 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
 	add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO);
 
 	for (matchp = cs->matches; matchp; matchp = matchp->next) {
-		ret = add_match(h, r, matchp->match->m);
+		ret = add_match(h, ctx, r, matchp->match->m);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 658a4f201895..d53f87c1d26e 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -25,8 +25,8 @@
 #include "nft.h"
 #include "nft-shared.h"
 
-static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
-			struct iptables_command_state *cs)
+static int nft_ipv6_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
+			struct nftnl_rule *r, struct iptables_command_state *cs)
 {
 	struct xtables_rule_match *matchp;
 	uint32_t op;
@@ -70,7 +70,7 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
 	add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
 
 	for (matchp = cs->matches; matchp; matchp = matchp->next) {
-		ret = add_match(h, r, matchp->match->m);
+		ret = add_match(h, ctx, r, matchp->match->m);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index a06b263d77c1..4f47058d2ec5 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -35,13 +35,14 @@
 			| FMT_NUMERIC | FMT_NOTABLE)
 #define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
 
+struct nft_rule_ctx;
 struct xtables_args;
 struct nft_handle;
 struct xt_xlate;
 
 struct nft_family_ops {
-	int (*add)(struct nft_handle *h, struct nftnl_rule *r,
-		   struct iptables_command_state *cs);
+	int (*add)(struct nft_handle *h, struct nft_rule_ctx *ctx,
+		   struct nftnl_rule *r, struct iptables_command_state *cs);
 	bool (*is_same)(const struct iptables_command_state *cs_a,
 			const struct iptables_command_state *cs_b);
 	void (*print_payload)(struct nftnl_expr *e,
diff --git a/iptables/nft.c b/iptables/nft.c
index 1cb104e75ccc..59e3fa7079c4 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1154,7 +1154,8 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
 #define NFT_DATATYPE_ETHERADDR	9
 
 static int __add_nft_among(struct nft_handle *h, const char *table,
-			   struct nftnl_rule *r, struct nft_among_pair *pairs,
+			   struct nft_rule_ctx *ctx, struct nftnl_rule *r,
+			   struct nft_among_pair *pairs,
 			   int cnt, bool dst, bool inv, bool ip)
 {
 	uint32_t set_id, type = NFT_DATATYPE_ETHERADDR, len = ETH_ALEN;
@@ -1235,7 +1236,7 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
 	return 0;
 }
 
-static int add_nft_among(struct nft_handle *h,
+static int add_nft_among(struct nft_handle *h, struct nft_rule_ctx *ctx,
 			 struct nftnl_rule *r, struct xt_entry_match *m)
 {
 	struct nft_among_data *data = (struct nft_among_data *)m->data;
@@ -1251,10 +1252,10 @@ static int add_nft_among(struct nft_handle *h,
 	}
 
 	if (data->src.cnt)
-		__add_nft_among(h, table, r, data->pairs, data->src.cnt,
+		__add_nft_among(h, table, ctx, r, data->pairs, data->src.cnt,
 				false, data->src.inv, data->src.ip);
 	if (data->dst.cnt)
-		__add_nft_among(h, table, r, data->pairs + data->src.cnt,
+		__add_nft_among(h, table, ctx, r, data->pairs + data->src.cnt,
 				data->dst.cnt, true, data->dst.inv,
 				data->dst.ip);
 	return 0;
@@ -1462,22 +1463,30 @@ static int add_nft_mark(struct nft_handle *h, struct nftnl_rule *r,
 	return 0;
 }
 
-int add_match(struct nft_handle *h,
+int add_match(struct nft_handle *h, struct nft_rule_ctx *ctx,
 	      struct nftnl_rule *r, struct xt_entry_match *m)
 {
 	struct nftnl_expr *expr;
 	int ret;
 
-	if (!strcmp(m->u.user.name, "limit"))
-		return add_nft_limit(r, m);
-	else if (!strcmp(m->u.user.name, "among"))
-		return add_nft_among(h, r, m);
-	else if (!strcmp(m->u.user.name, "udp"))
-		return add_nft_udp(h, r, m);
-	else if (!strcmp(m->u.user.name, "tcp"))
-		return add_nft_tcp(h, r, m);
-	else if (!strcmp(m->u.user.name, "mark"))
-		return add_nft_mark(h, r, m);
+	switch (ctx->command) {
+	case NFT_COMPAT_RULE_APPEND:
+	case NFT_COMPAT_RULE_INSERT:
+	case NFT_COMPAT_RULE_REPLACE:
+		if (!strcmp(m->u.user.name, "limit"))
+			return add_nft_limit(r, m);
+		else if (!strcmp(m->u.user.name, "among"))
+			return add_nft_among(h, ctx, r, m);
+		else if (!strcmp(m->u.user.name, "udp"))
+			return add_nft_udp(h, r, m);
+		else if (!strcmp(m->u.user.name, "tcp"))
+			return add_nft_tcp(h, r, m);
+		else if (!strcmp(m->u.user.name, "mark"))
+			return add_nft_mark(h, r, m);
+		break;
+	default:
+		break;
+	}
 
 	expr = nftnl_expr_alloc("match");
 	if (expr == NULL)
@@ -1705,7 +1714,8 @@ void add_compat(struct nftnl_rule *r, uint32_t proto, bool inv)
 }
 
 struct nftnl_rule *
-nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
+nft_rule_new(struct nft_handle *h, struct nft_rule_ctx *ctx,
+	     const char *chain, const char *table,
 	     struct iptables_command_state *cs)
 {
 	struct nftnl_rule *r;
@@ -1718,7 +1728,7 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
 	nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
 	nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
 
-	if (h->ops->add(h, r, cs) < 0)
+	if (h->ops->add(h, ctx, r, cs) < 0)
 		goto err;
 
 	return r;
@@ -2878,6 +2888,9 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
 {
 	struct iptables_command_state cs = {};
 	struct nftnl_rule *r, *new_rule;
+	struct nft_rule_ctx ctx = {
+		.command = NFT_COMPAT_RULE_ZERO,
+	};
 	struct nft_chain *c;
 	int ret = 0;
 
@@ -2896,7 +2909,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
 
 	h->ops->rule_to_cs(h, r, &cs);
 	cs.counters.pcnt = cs.counters.bcnt = 0;
-	new_rule = nft_rule_new(h, chain, table, &cs);
+	new_rule = nft_rule_new(h, &ctx, chain, table, &cs);
 	h->ops->clear_cs(&cs);
 
 	if (!new_rule)
@@ -3274,6 +3287,9 @@ static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
 		.eb.bitmask = EBT_NOPROTO,
 	};
 	struct nftnl_udata_buf *udata;
+	struct nft_rule_ctx ctx = {
+		.command	= NFT_COMPAT_RULE_APPEND,
+	};
 	struct nft_handle *h = data;
 	struct nftnl_rule *r;
 	const char *pname;
@@ -3301,7 +3317,7 @@ static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
 
 	command_jump(&cs, pname);
 
-	r = nft_rule_new(h, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME),
+	r = nft_rule_new(h, &ctx, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME),
 			 nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), &cs);
 	ebt_cs_clean(&cs);
 
diff --git a/iptables/nft.h b/iptables/nft.h
index 1d18982dc8cf..5acbbf82e2c2 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -168,9 +168,11 @@ struct nftnl_set *nft_set_batch_lookup_byid(struct nft_handle *h,
 /*
  * Operations with rule-set.
  */
-struct nftnl_rule;
+struct nft_rule_ctx {
+	int			command;
+};
 
-struct nftnl_rule *nft_rule_new(struct nft_handle *h, const char *chain, const char *table, struct iptables_command_state *cs);
+struct nftnl_rule *nft_rule_new(struct nft_handle *h, struct nft_rule_ctx *rule, const char *chain, const char *table, struct iptables_command_state *cs);
 int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, struct nftnl_rule *ref, bool verbose);
 int nft_rule_insert(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, int rulenum, bool verbose);
 int nft_rule_check(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, bool verbose);
@@ -188,7 +190,8 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *
  */
 int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes);
 int add_verdict(struct nftnl_rule *r, int verdict);
-int add_match(struct nft_handle *h, struct nftnl_rule *r, struct xt_entry_match *m);
+int add_match(struct nft_handle *h, struct nft_rule_ctx *ctx,
+	      struct nftnl_rule *r, struct xt_entry_match *m);
 int add_target(struct nftnl_rule *r, struct xt_entry_target *t);
 int add_jumpto(struct nftnl_rule *r, const char *name, int verdict);
 int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-12  9:59 [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support Pablo Neira Ayuso
@ 2023-07-12 11:05 ` Igor Raits
  2023-07-12 14:01   ` Pablo Neira Ayuso
  2023-07-12 17:13 ` Pablo Neira Ayuso
  2023-07-13 11:50 ` Phil Sutter
  2 siblings, 1 reply; 7+ messages in thread
From: Igor Raits @ 2023-07-12 11:05 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, fw, phil

Hi Pablo,

Thanks for the patch!

On Wed, Jul 12, 2023 at 11:59 AM Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>
> Add context structure to improve bridge among support which creates an
> anonymous set. This context structure specifies the command and it
> allows to optionally store a anonymous set.
>
> Use this context to generate native bytecode only if this is an
> add/insert/replace command.
>
> This fixes a dangling anonymous set that is created on rule removal.
>
> Fixes: 26753888720d ("nft: bridge: Rudimental among extension support")
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Reported-and-tested-by: Igor Raits <igor@gooddata.com>

> ---
> This test passes tests/py and tests/shell.
>
>  iptables/nft-arp.c    |  4 ++--
>  iptables/nft-bridge.c |  9 ++++----
>  iptables/nft-cmd.c    |  6 ++++-
>  iptables/nft-ipv4.c   |  6 ++---
>  iptables/nft-ipv6.c   |  6 ++---
>  iptables/nft-shared.h |  5 ++--
>  iptables/nft.c        | 54 ++++++++++++++++++++++++++++---------------
>  iptables/nft.h        |  9 +++++---
>  8 files changed, 62 insertions(+), 37 deletions(-)
>
> diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
> index 265de5f88cea..9868966a0368 100644
> --- a/iptables/nft-arp.c
> +++ b/iptables/nft-arp.c
> @@ -40,8 +40,8 @@ static bool need_devaddr(struct arpt_devaddr_info *info)
>         return false;
>  }
>
> -static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r,
> -                      struct iptables_command_state *cs)
> +static int nft_arp_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +                      struct nftnl_rule *r, struct iptables_command_state *cs)
>  {
>         struct arpt_entry *fw = &cs->arp;
>         uint32_t op;
> diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
> index 6e50950774e6..391a8ab723c1 100644
> --- a/iptables/nft-bridge.c
> +++ b/iptables/nft-bridge.c
> @@ -138,7 +138,8 @@ static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
>
>  static int
>  nft_bridge_add_match(struct nft_handle *h, const struct ebt_entry *fw,
> -                    struct nftnl_rule *r, struct xt_entry_match *m)
> +                    struct nft_rule_ctx *ctx, struct nftnl_rule *r,
> +                    struct xt_entry_match *m)
>  {
>         if (!strcmp(m->u.user.name, "802_3") && !(fw->bitmask & EBT_802_3))
>                 xtables_error(PARAMETER_PROBLEM,
> @@ -152,10 +153,10 @@ nft_bridge_add_match(struct nft_handle *h, const struct ebt_entry *fw,
>                 xtables_error(PARAMETER_PROBLEM,
>                               "For IPv6 filtering the protocol must be specified as IPv6.");
>
> -       return add_match(h, r, m);
> +       return add_match(h, ctx, r, m);
>  }
>
> -static int nft_bridge_add(struct nft_handle *h,
> +static int nft_bridge_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
>                           struct nftnl_rule *r,
>                           struct iptables_command_state *cs)
>  {
> @@ -217,7 +218,7 @@ static int nft_bridge_add(struct nft_handle *h,
>
>         for (iter = cs->match_list; iter; iter = iter->next) {
>                 if (iter->ismatch) {
> -                       if (nft_bridge_add_match(h, fw, r, iter->u.match->m))
> +                       if (nft_bridge_add_match(h, fw, ctx, r, iter->u.match->m))
>                                 break;
>                 } else {
>                         if (add_target(r, iter->u.watcher->t))
> diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
> index 7b2fc3a59578..8a824586ad8c 100644
> --- a/iptables/nft-cmd.c
> +++ b/iptables/nft-cmd.c
> @@ -14,12 +14,16 @@
>  #include <xtables.h>
>  #include "nft.h"
>  #include "nft-cmd.h"
> +#include <libnftnl/set.h>
>
>  struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
>                             const char *table, const char *chain,
>                             struct iptables_command_state *state,
>                             int rulenum, bool verbose)
>  {
> +       struct nft_rule_ctx ctx = {
> +               .command = command,
> +       };
>         struct nftnl_rule *rule;
>         struct nft_cmd *cmd;
>
> @@ -33,7 +37,7 @@ struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
>         cmd->verbose = verbose;
>
>         if (state) {
> -               rule = nft_rule_new(h, chain, table, state);
> +               rule = nft_rule_new(h, &ctx, chain, table, state);
>                 if (!rule) {
>                         nft_cmd_free(cmd);
>                         return NULL;
> diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
> index 2a5d25d8694e..2f10220edd50 100644
> --- a/iptables/nft-ipv4.c
> +++ b/iptables/nft-ipv4.c
> @@ -26,8 +26,8 @@
>  #include "nft.h"
>  #include "nft-shared.h"
>
> -static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
> -                       struct iptables_command_state *cs)
> +static int nft_ipv4_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +                       struct nftnl_rule *r, struct iptables_command_state *cs)
>  {
>         struct xtables_rule_match *matchp;
>         uint32_t op;
> @@ -84,7 +84,7 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
>         add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO);
>
>         for (matchp = cs->matches; matchp; matchp = matchp->next) {
> -               ret = add_match(h, r, matchp->match->m);
> +               ret = add_match(h, ctx, r, matchp->match->m);
>                 if (ret < 0)
>                         return ret;
>         }
> diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
> index 658a4f201895..d53f87c1d26e 100644
> --- a/iptables/nft-ipv6.c
> +++ b/iptables/nft-ipv6.c
> @@ -25,8 +25,8 @@
>  #include "nft.h"
>  #include "nft-shared.h"
>
> -static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
> -                       struct iptables_command_state *cs)
> +static int nft_ipv6_add(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +                       struct nftnl_rule *r, struct iptables_command_state *cs)
>  {
>         struct xtables_rule_match *matchp;
>         uint32_t op;
> @@ -70,7 +70,7 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
>         add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
>
>         for (matchp = cs->matches; matchp; matchp = matchp->next) {
> -               ret = add_match(h, r, matchp->match->m);
> +               ret = add_match(h, ctx, r, matchp->match->m);
>                 if (ret < 0)
>                         return ret;
>         }
> diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
> index a06b263d77c1..4f47058d2ec5 100644
> --- a/iptables/nft-shared.h
> +++ b/iptables/nft-shared.h
> @@ -35,13 +35,14 @@
>                         | FMT_NUMERIC | FMT_NOTABLE)
>  #define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
>
> +struct nft_rule_ctx;
>  struct xtables_args;
>  struct nft_handle;
>  struct xt_xlate;
>
>  struct nft_family_ops {
> -       int (*add)(struct nft_handle *h, struct nftnl_rule *r,
> -                  struct iptables_command_state *cs);
> +       int (*add)(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +                  struct nftnl_rule *r, struct iptables_command_state *cs);
>         bool (*is_same)(const struct iptables_command_state *cs_a,
>                         const struct iptables_command_state *cs_b);
>         void (*print_payload)(struct nftnl_expr *e,
> diff --git a/iptables/nft.c b/iptables/nft.c
> index 1cb104e75ccc..59e3fa7079c4 100644
> --- a/iptables/nft.c
> +++ b/iptables/nft.c
> @@ -1154,7 +1154,8 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
>  #define NFT_DATATYPE_ETHERADDR 9
>
>  static int __add_nft_among(struct nft_handle *h, const char *table,
> -                          struct nftnl_rule *r, struct nft_among_pair *pairs,
> +                          struct nft_rule_ctx *ctx, struct nftnl_rule *r,
> +                          struct nft_among_pair *pairs,
>                            int cnt, bool dst, bool inv, bool ip)
>  {
>         uint32_t set_id, type = NFT_DATATYPE_ETHERADDR, len = ETH_ALEN;
> @@ -1235,7 +1236,7 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
>         return 0;
>  }
>
> -static int add_nft_among(struct nft_handle *h,
> +static int add_nft_among(struct nft_handle *h, struct nft_rule_ctx *ctx,
>                          struct nftnl_rule *r, struct xt_entry_match *m)
>  {
>         struct nft_among_data *data = (struct nft_among_data *)m->data;
> @@ -1251,10 +1252,10 @@ static int add_nft_among(struct nft_handle *h,
>         }
>
>         if (data->src.cnt)
> -               __add_nft_among(h, table, r, data->pairs, data->src.cnt,
> +               __add_nft_among(h, table, ctx, r, data->pairs, data->src.cnt,
>                                 false, data->src.inv, data->src.ip);
>         if (data->dst.cnt)
> -               __add_nft_among(h, table, r, data->pairs + data->src.cnt,
> +               __add_nft_among(h, table, ctx, r, data->pairs + data->src.cnt,
>                                 data->dst.cnt, true, data->dst.inv,
>                                 data->dst.ip);
>         return 0;
> @@ -1462,22 +1463,30 @@ static int add_nft_mark(struct nft_handle *h, struct nftnl_rule *r,
>         return 0;
>  }
>
> -int add_match(struct nft_handle *h,
> +int add_match(struct nft_handle *h, struct nft_rule_ctx *ctx,
>               struct nftnl_rule *r, struct xt_entry_match *m)
>  {
>         struct nftnl_expr *expr;
>         int ret;
>
> -       if (!strcmp(m->u.user.name, "limit"))
> -               return add_nft_limit(r, m);
> -       else if (!strcmp(m->u.user.name, "among"))
> -               return add_nft_among(h, r, m);
> -       else if (!strcmp(m->u.user.name, "udp"))
> -               return add_nft_udp(h, r, m);
> -       else if (!strcmp(m->u.user.name, "tcp"))
> -               return add_nft_tcp(h, r, m);
> -       else if (!strcmp(m->u.user.name, "mark"))
> -               return add_nft_mark(h, r, m);
> +       switch (ctx->command) {
> +       case NFT_COMPAT_RULE_APPEND:
> +       case NFT_COMPAT_RULE_INSERT:
> +       case NFT_COMPAT_RULE_REPLACE:
> +               if (!strcmp(m->u.user.name, "limit"))
> +                       return add_nft_limit(r, m);
> +               else if (!strcmp(m->u.user.name, "among"))
> +                       return add_nft_among(h, ctx, r, m);
> +               else if (!strcmp(m->u.user.name, "udp"))
> +                       return add_nft_udp(h, r, m);
> +               else if (!strcmp(m->u.user.name, "tcp"))
> +                       return add_nft_tcp(h, r, m);
> +               else if (!strcmp(m->u.user.name, "mark"))
> +                       return add_nft_mark(h, r, m);
> +               break;
> +       default:
> +               break;
> +       }
>
>         expr = nftnl_expr_alloc("match");
>         if (expr == NULL)
> @@ -1705,7 +1714,8 @@ void add_compat(struct nftnl_rule *r, uint32_t proto, bool inv)
>  }
>
>  struct nftnl_rule *
> -nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
> +nft_rule_new(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +            const char *chain, const char *table,
>              struct iptables_command_state *cs)
>  {
>         struct nftnl_rule *r;
> @@ -1718,7 +1728,7 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
>         nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
>         nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
>
> -       if (h->ops->add(h, r, cs) < 0)
> +       if (h->ops->add(h, ctx, r, cs) < 0)
>                 goto err;
>
>         return r;
> @@ -2878,6 +2888,9 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
>  {
>         struct iptables_command_state cs = {};
>         struct nftnl_rule *r, *new_rule;
> +       struct nft_rule_ctx ctx = {
> +               .command = NFT_COMPAT_RULE_ZERO,
> +       };
>         struct nft_chain *c;
>         int ret = 0;
>
> @@ -2896,7 +2909,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
>
>         h->ops->rule_to_cs(h, r, &cs);
>         cs.counters.pcnt = cs.counters.bcnt = 0;
> -       new_rule = nft_rule_new(h, chain, table, &cs);
> +       new_rule = nft_rule_new(h, &ctx, chain, table, &cs);
>         h->ops->clear_cs(&cs);
>
>         if (!new_rule)
> @@ -3274,6 +3287,9 @@ static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
>                 .eb.bitmask = EBT_NOPROTO,
>         };
>         struct nftnl_udata_buf *udata;
> +       struct nft_rule_ctx ctx = {
> +               .command        = NFT_COMPAT_RULE_APPEND,
> +       };
>         struct nft_handle *h = data;
>         struct nftnl_rule *r;
>         const char *pname;
> @@ -3301,7 +3317,7 @@ static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
>
>         command_jump(&cs, pname);
>
> -       r = nft_rule_new(h, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME),
> +       r = nft_rule_new(h, &ctx, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME),
>                          nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), &cs);
>         ebt_cs_clean(&cs);
>
> diff --git a/iptables/nft.h b/iptables/nft.h
> index 1d18982dc8cf..5acbbf82e2c2 100644
> --- a/iptables/nft.h
> +++ b/iptables/nft.h
> @@ -168,9 +168,11 @@ struct nftnl_set *nft_set_batch_lookup_byid(struct nft_handle *h,
>  /*
>   * Operations with rule-set.
>   */
> -struct nftnl_rule;
> +struct nft_rule_ctx {
> +       int                     command;
> +};
>
> -struct nftnl_rule *nft_rule_new(struct nft_handle *h, const char *chain, const char *table, struct iptables_command_state *cs);
> +struct nftnl_rule *nft_rule_new(struct nft_handle *h, struct nft_rule_ctx *rule, const char *chain, const char *table, struct iptables_command_state *cs);
>  int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, struct nftnl_rule *ref, bool verbose);
>  int nft_rule_insert(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, int rulenum, bool verbose);
>  int nft_rule_check(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule *r, bool verbose);
> @@ -188,7 +190,8 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *
>   */
>  int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes);
>  int add_verdict(struct nftnl_rule *r, int verdict);
> -int add_match(struct nft_handle *h, struct nftnl_rule *r, struct xt_entry_match *m);
> +int add_match(struct nft_handle *h, struct nft_rule_ctx *ctx,
> +             struct nftnl_rule *r, struct xt_entry_match *m);
>  int add_target(struct nftnl_rule *r, struct xt_entry_target *t);
>  int add_jumpto(struct nftnl_rule *r, const char *name, int verdict);
>  int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set);
> --
> 2.30.2
>


-- 

Igor Raits | Sr. Principal SW Engineer

igor@gooddata.com

+420 775 117 817


Moravske namesti 1007/14

602 00 Brno-Veveri, Czech Republic

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-12 11:05 ` Igor Raits
@ 2023-07-12 14:01   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 7+ messages in thread
From: Pablo Neira Ayuso @ 2023-07-12 14:01 UTC (permalink / raw)
  To: Igor Raits; +Cc: netfilter-devel, fw, phil

On Wed, Jul 12, 2023 at 01:05:10PM +0200, Igor Raits wrote:
> Hi Pablo,
> 
> Thanks for the patch!
> 
> On Wed, Jul 12, 2023 at 11:59 AM Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> >
> > Add context structure to improve bridge among support which creates an
> > anonymous set. This context structure specifies the command and it
> > allows to optionally store a anonymous set.
> >
> > Use this context to generate native bytecode only if this is an
> > add/insert/replace command.
> >
> > This fixes a dangling anonymous set that is created on rule removal.
> >
> > Fixes: 26753888720d ("nft: bridge: Rudimental among extension support")
> > Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> 
> Reported-and-tested-by: Igor Raits <igor@gooddata.com>

I have just pushed it out, thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-12  9:59 [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support Pablo Neira Ayuso
  2023-07-12 11:05 ` Igor Raits
@ 2023-07-12 17:13 ` Pablo Neira Ayuso
  2023-07-13 11:07   ` Phil Sutter
  2023-07-13 11:50 ` Phil Sutter
  2 siblings, 1 reply; 7+ messages in thread
From: Pablo Neira Ayuso @ 2023-07-12 17:13 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw, igor, phil

On Wed, Jul 12, 2023 at 11:59:12AM +0200, Pablo Neira Ayuso wrote:
> diff --git a/iptables/nft.c b/iptables/nft.c
> index 1cb104e75ccc..59e3fa7079c4 100644
> --- a/iptables/nft.c
> +++ b/iptables/nft.c
[...]
> @@ -2878,6 +2888,9 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
>  {
>  	struct iptables_command_state cs = {};
>  	struct nftnl_rule *r, *new_rule;
> +	struct nft_rule_ctx ctx = {
> +		.command = NFT_COMPAT_RULE_ZERO,

BTW. I changed this to:

                .command = NFT_COMPAT_RULE_APPEND,

before pushing it out, for the record.

> +	};
>  	struct nft_chain *c;
>  	int ret = 0;
>  

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-12 17:13 ` Pablo Neira Ayuso
@ 2023-07-13 11:07   ` Phil Sutter
  2023-07-13 11:34     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 7+ messages in thread
From: Phil Sutter @ 2023-07-13 11:07 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, fw, igor

On Wed, Jul 12, 2023 at 07:13:50PM +0200, Pablo Neira Ayuso wrote:
> On Wed, Jul 12, 2023 at 11:59:12AM +0200, Pablo Neira Ayuso wrote:
> > diff --git a/iptables/nft.c b/iptables/nft.c
> > index 1cb104e75ccc..59e3fa7079c4 100644
> > --- a/iptables/nft.c
> > +++ b/iptables/nft.c
> [...]
> > @@ -2878,6 +2888,9 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
> >  {
> >  	struct iptables_command_state cs = {};
> >  	struct nftnl_rule *r, *new_rule;
> > +	struct nft_rule_ctx ctx = {
> > +		.command = NFT_COMPAT_RULE_ZERO,
> 
> BTW. I changed this to:
> 
>                 .command = NFT_COMPAT_RULE_APPEND,
> 
> before pushing it out, for the record.

Hmm. :)

I'm curious how to trigger the problem. Could you please provide a
test-case?

Thanks, Phil

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-13 11:07   ` Phil Sutter
@ 2023-07-13 11:34     ` Pablo Neira Ayuso
  0 siblings, 0 replies; 7+ messages in thread
From: Pablo Neira Ayuso @ 2023-07-13 11:34 UTC (permalink / raw)
  To: Phil Sutter, netfilter-devel, fw, igor

On Thu, Jul 13, 2023 at 01:07:36PM +0200, Phil Sutter wrote:
> On Wed, Jul 12, 2023 at 07:13:50PM +0200, Pablo Neira Ayuso wrote:
> > On Wed, Jul 12, 2023 at 11:59:12AM +0200, Pablo Neira Ayuso wrote:
> > > diff --git a/iptables/nft.c b/iptables/nft.c
> > > index 1cb104e75ccc..59e3fa7079c4 100644
> > > --- a/iptables/nft.c
> > > +++ b/iptables/nft.c
> > [...]
> > > @@ -2878,6 +2888,9 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
> > >  {
> > >  	struct iptables_command_state cs = {};
> > >  	struct nftnl_rule *r, *new_rule;
> > > +	struct nft_rule_ctx ctx = {
> > > +		.command = NFT_COMPAT_RULE_ZERO,
> > 
> > BTW. I changed this to:
> > 
> >                 .command = NFT_COMPAT_RULE_APPEND,
> > 
> > before pushing it out, for the record.
> 
> Hmm. :)
> 
> I'm curious how to trigger the problem. Could you please provide a
> test-case?

I suspect a problem might occur if the rule that is zeroed generates a
native expression.

nft_rule_zero_counters() calls _append() in practise, to readd the
rule after deleting it to zero the counters.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support
  2023-07-12  9:59 [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support Pablo Neira Ayuso
  2023-07-12 11:05 ` Igor Raits
  2023-07-12 17:13 ` Pablo Neira Ayuso
@ 2023-07-13 11:50 ` Phil Sutter
  2 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-07-13 11:50 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, fw, igor

On Wed, Jul 12, 2023 at 11:59:12AM +0200, Pablo Neira Ayuso wrote:
[...]
> diff --git a/iptables/nft.c b/iptables/nft.c
> index 1cb104e75ccc..59e3fa7079c4 100644
> --- a/iptables/nft.c
> +++ b/iptables/nft.c
> @@ -1154,7 +1154,8 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
>  #define NFT_DATATYPE_ETHERADDR	9
>  
>  static int __add_nft_among(struct nft_handle *h, const char *table,
> -			   struct nftnl_rule *r, struct nft_among_pair *pairs,
> +			   struct nft_rule_ctx *ctx, struct nftnl_rule *r,
> +			   struct nft_among_pair *pairs,
>  			   int cnt, bool dst, bool inv, bool ip)
>  {
>  	uint32_t set_id, type = NFT_DATATYPE_ETHERADDR, len = ETH_ALEN;

Is there something missing here? Neither add_nft_among() nor
__add_nft_among() use the new parameter. Or is this left over from a
previous version of the fix?

Cheers, Phil

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-07-13 11:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-12  9:59 [PATCH iptables] nft-bridge: pass context structure to ops->add() to improve anonymous set support Pablo Neira Ayuso
2023-07-12 11:05 ` Igor Raits
2023-07-12 14:01   ` Pablo Neira Ayuso
2023-07-12 17:13 ` Pablo Neira Ayuso
2023-07-13 11:07   ` Phil Sutter
2023-07-13 11:34     ` Pablo Neira Ayuso
2023-07-13 11:50 ` Phil Sutter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).