All of lore.kernel.org
 help / color / mirror / Atom feed
From: Phil Sutter <phil@nwl.cc>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: netfilter-devel@vger.kernel.org
Subject: [iptables PATCH v3 05/13] nft: Add family ops callbacks wrapping different nft_cmd_* functions
Date: Fri, 15 Oct 2021 14:26:00 +0200	[thread overview]
Message-ID: <20211015122608.12474-6-phil@nwl.cc> (raw)
In-Reply-To: <20211015122608.12474-1-phil@nwl.cc>

Commands supporting multiple source/destination addresses need to
iterate over them and call the respective nft_cmd_* function multiple
times. These loops are family-specific though as each family uses a
different data structure within struct iptables_command_state to store
the addresses.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-ipv4.c   |  93 +++++++++++++++++++++
 iptables/nft-ipv6.c   | 104 +++++++++++++++++++++++
 iptables/nft-shared.h |  18 ++++
 iptables/xtables.c    | 190 +++---------------------------------------
 4 files changed, 228 insertions(+), 177 deletions(-)

diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 34f94bd8cc24a..febd7673af4f8 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -468,6 +468,95 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
 	return ret;
 }
 
+static int
+nft_ipv4_add_entry(struct nft_handle *h,
+		   const char *chain, const char *table,
+		   struct iptables_command_state *cs,
+		   struct xtables_args *args, bool verbose,
+		   bool append, int rulenum)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr;
+		cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr;
+		for (j = 0; j < args->d.naddrs; j++) {
+			cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr;
+			cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr;
+
+			if (append) {
+				ret = nft_cmd_rule_append(h, chain, table,
+						      cs, NULL, verbose);
+			} else {
+				ret = nft_cmd_rule_insert(h, chain, table,
+						      cs, rulenum, verbose);
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv4_delete_entry(struct nft_handle *h,
+		      const char *chain, const char *table,
+		      struct iptables_command_state *cs,
+		      struct xtables_args *args, bool verbose)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr;
+		cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr;
+		for (j = 0; j < args->d.naddrs; j++) {
+			cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr;
+			cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr;
+			ret = nft_cmd_rule_delete(h, chain, table, cs, verbose);
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv4_check_entry(struct nft_handle *h,
+		     const char *chain, const char *table,
+		     struct iptables_command_state *cs,
+		     struct xtables_args *args, bool verbose)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr;
+		cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr;
+		for (j = 0; j < args->d.naddrs; j++) {
+			cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr;
+			cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr;
+			ret = nft_cmd_rule_check(h, chain, table, cs, verbose);
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv4_replace_entry(struct nft_handle *h,
+		       const char *chain, const char *table,
+		       struct iptables_command_state *cs,
+		       struct xtables_args *args, bool verbose,
+		       int rulenum)
+{
+	cs->fw.ip.src.s_addr = args->s.addr.v4->s_addr;
+	cs->fw.ip.dst.s_addr = args->d.addr.v4->s_addr;
+	cs->fw.ip.smsk.s_addr = args->s.mask.v4->s_addr;
+	cs->fw.ip.dmsk.s_addr = args->d.mask.v4->s_addr;
+
+	return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose);
+}
+
 struct nft_family_ops nft_family_ops_ipv4 = {
 	.add			= nft_ipv4_add,
 	.is_same		= nft_ipv4_is_same,
@@ -484,4 +573,8 @@ struct nft_family_ops nft_family_ops_ipv4 = {
 	.rule_to_cs		= nft_rule_to_iptables_command_state,
 	.clear_cs		= nft_clear_iptables_command_state,
 	.xlate			= nft_ipv4_xlate,
+	.add_entry		= nft_ipv4_add_entry,
+	.delete_entry		= nft_ipv4_delete_entry,
+	.check_entry		= nft_ipv4_check_entry,
+	.replace_entry		= nft_ipv4_replace_entry,
 };
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index d9c9400ad7dc3..f0e64bbd4ab23 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -410,6 +410,106 @@ static int nft_ipv6_xlate(const void *data, struct xt_xlate *xl)
 	return ret;
 }
 
+static int
+nft_ipv6_add_entry(struct nft_handle *h,
+		   const char *chain, const char *table,
+		   struct iptables_command_state *cs,
+		   struct xtables_args *args, bool verbose,
+		   bool append, int rulenum)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		memcpy(&cs->fw6.ipv6.src,
+		       &args->s.addr.v6[i], sizeof(struct in6_addr));
+		memcpy(&cs->fw6.ipv6.smsk,
+		       &args->s.mask.v6[i], sizeof(struct in6_addr));
+		for (j = 0; j < args->d.naddrs; j++) {
+			memcpy(&cs->fw6.ipv6.dst,
+			       &args->d.addr.v6[j], sizeof(struct in6_addr));
+			memcpy(&cs->fw6.ipv6.dmsk,
+			       &args->d.mask.v6[j], sizeof(struct in6_addr));
+			if (append) {
+				ret = nft_cmd_rule_append(h, chain, table,
+						      cs, NULL, verbose);
+			} else {
+				ret = nft_cmd_rule_insert(h, chain, table,
+						      cs, rulenum, verbose);
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv6_delete_entry(struct nft_handle *h,
+		      const char *chain, const char *table,
+		      struct iptables_command_state *cs,
+		      struct xtables_args *args, bool verbose)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		memcpy(&cs->fw6.ipv6.src,
+		       &args->s.addr.v6[i], sizeof(struct in6_addr));
+		memcpy(&cs->fw6.ipv6.smsk,
+		       &args->s.mask.v6[i], sizeof(struct in6_addr));
+		for (j = 0; j < args->d.naddrs; j++) {
+			memcpy(&cs->fw6.ipv6.dst,
+			       &args->d.addr.v6[j], sizeof(struct in6_addr));
+			memcpy(&cs->fw6.ipv6.dmsk,
+			       &args->d.mask.v6[j], sizeof(struct in6_addr));
+			ret = nft_cmd_rule_delete(h, chain, table, cs, verbose);
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv6_check_entry(struct nft_handle *h,
+		     const char *chain, const char *table,
+		     struct iptables_command_state *cs,
+		     struct xtables_args *args, bool verbose)
+{
+	unsigned int i, j;
+	int ret = 1;
+
+	for (i = 0; i < args->s.naddrs; i++) {
+		memcpy(&cs->fw6.ipv6.src,
+		       &args->s.addr.v6[i], sizeof(struct in6_addr));
+		memcpy(&cs->fw6.ipv6.smsk,
+		       &args->s.mask.v6[i], sizeof(struct in6_addr));
+		for (j = 0; j < args->d.naddrs; j++) {
+			memcpy(&cs->fw6.ipv6.dst,
+			       &args->d.addr.v6[j], sizeof(struct in6_addr));
+			memcpy(&cs->fw6.ipv6.dmsk,
+			       &args->d.mask.v6[j], sizeof(struct in6_addr));
+			ret = nft_cmd_rule_check(h, chain, table, cs, verbose);
+		}
+	}
+
+	return ret;
+}
+
+static int
+nft_ipv6_replace_entry(struct nft_handle *h,
+		       const char *chain, const char *table,
+		       struct iptables_command_state *cs,
+		       struct xtables_args *args, bool verbose,
+		       int rulenum)
+{
+	memcpy(&cs->fw6.ipv6.src, args->s.addr.v6, sizeof(struct in6_addr));
+	memcpy(&cs->fw6.ipv6.dst, args->d.addr.v6, sizeof(struct in6_addr));
+	memcpy(&cs->fw6.ipv6.smsk, args->s.mask.v6, sizeof(struct in6_addr));
+	memcpy(&cs->fw6.ipv6.dmsk, args->d.mask.v6, sizeof(struct in6_addr));
+
+	return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose);
+}
+
 struct nft_family_ops nft_family_ops_ipv6 = {
 	.add			= nft_ipv6_add,
 	.is_same		= nft_ipv6_is_same,
@@ -426,4 +526,8 @@ struct nft_family_ops nft_family_ops_ipv6 = {
 	.rule_to_cs		= nft_rule_to_iptables_command_state,
 	.clear_cs		= nft_clear_iptables_command_state,
 	.xlate			= nft_ipv6_xlate,
+	.add_entry		= nft_ipv6_add_entry,
+	.delete_entry		= nft_ipv6_delete_entry,
+	.check_entry		= nft_ipv6_check_entry,
+	.replace_entry		= nft_ipv6_replace_entry,
 };
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 44ad0811f4081..cb1c3fffe63b4 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -111,6 +111,24 @@ struct nft_family_ops {
 			   struct iptables_command_state *cs);
 	void (*clear_cs)(struct iptables_command_state *cs);
 	int (*xlate)(const void *data, struct xt_xlate *xl);
+	int (*add_entry)(struct nft_handle *h,
+			 const char *chain, const char *table,
+			 struct iptables_command_state *cs,
+			 struct xtables_args *args, bool verbose,
+			 bool append, int rulenum);
+	int (*delete_entry)(struct nft_handle *h,
+			    const char *chain, const char *table,
+			    struct iptables_command_state *cs,
+			    struct xtables_args *args, bool verbose);
+	int (*check_entry)(struct nft_handle *h,
+			   const char *chain, const char *table,
+			   struct iptables_command_state *cs,
+			   struct xtables_args *args, bool verbose);
+	int (*replace_entry)(struct nft_handle *h,
+			     const char *chain, const char *table,
+			     struct iptables_command_state *cs,
+			     struct xtables_args *args, bool verbose,
+			     int rulenum);
 };
 
 void add_meta(struct nftnl_rule *r, uint32_t key);
diff --git a/iptables/xtables.c b/iptables/xtables.c
index f45e36086dcb8..9abfc8f8d7f32 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -223,168 +223,6 @@ xtables_exit_error(enum xtables_exittype status, const char *msg, ...)
 
 /* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
 
-static int
-add_entry(const char *chain,
-	  const char *table,
-	  struct iptables_command_state *cs,
-	  int rulenum, int family,
-	  const struct addr_mask s,
-	  const struct addr_mask d,
-	  bool verbose, struct nft_handle *h, bool append)
-{
-	unsigned int i, j;
-	int ret = 1;
-
-	for (i = 0; i < s.naddrs; i++) {
-		if (family == AF_INET) {
-			cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
-			cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
-			for (j = 0; j < d.naddrs; j++) {
-				cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
-				cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
-
-				if (append) {
-					ret = nft_cmd_rule_append(h, chain, table,
-							      cs, NULL,
-							      verbose);
-				} else {
-					ret = nft_cmd_rule_insert(h, chain, table,
-							      cs, rulenum,
-							      verbose);
-				}
-			}
-		} else if (family == AF_INET6) {
-			memcpy(&cs->fw6.ipv6.src,
-			       &s.addr.v6[i], sizeof(struct in6_addr));
-			memcpy(&cs->fw6.ipv6.smsk,
-			       &s.mask.v6[i], sizeof(struct in6_addr));
-			for (j = 0; j < d.naddrs; j++) {
-				memcpy(&cs->fw6.ipv6.dst,
-				       &d.addr.v6[j], sizeof(struct in6_addr));
-				memcpy(&cs->fw6.ipv6.dmsk,
-				       &d.mask.v6[j], sizeof(struct in6_addr));
-				if (append) {
-					ret = nft_cmd_rule_append(h, chain, table,
-							      cs, NULL,
-							      verbose);
-				} else {
-					ret = nft_cmd_rule_insert(h, chain, table,
-							      cs, rulenum,
-							      verbose);
-				}
-			}
-		}
-	}
-
-	return ret;
-}
-
-static int
-replace_entry(const char *chain, const char *table,
-	      struct iptables_command_state *cs,
-	      unsigned int rulenum,
-	      int family,
-	      const struct addr_mask s,
-	      const struct addr_mask d,
-	      bool verbose, struct nft_handle *h)
-{
-	if (family == AF_INET) {
-		cs->fw.ip.src.s_addr = s.addr.v4->s_addr;
-		cs->fw.ip.dst.s_addr = d.addr.v4->s_addr;
-		cs->fw.ip.smsk.s_addr = s.mask.v4->s_addr;
-		cs->fw.ip.dmsk.s_addr = d.mask.v4->s_addr;
-	} else if (family == AF_INET6) {
-		memcpy(&cs->fw6.ipv6.src, s.addr.v6, sizeof(struct in6_addr));
-		memcpy(&cs->fw6.ipv6.dst, d.addr.v6, sizeof(struct in6_addr));
-		memcpy(&cs->fw6.ipv6.smsk, s.mask.v6, sizeof(struct in6_addr));
-		memcpy(&cs->fw6.ipv6.dmsk, d.mask.v6, sizeof(struct in6_addr));
-	} else
-		return 1;
-
-	return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose);
-}
-
-static int
-delete_entry(const char *chain, const char *table,
-	     struct iptables_command_state *cs,
-	     int family,
-	     const struct addr_mask s,
-	     const struct addr_mask d,
-	     bool verbose,
-	     struct nft_handle *h)
-{
-	unsigned int i, j;
-	int ret = 1;
-
-	for (i = 0; i < s.naddrs; i++) {
-		if (family == AF_INET) {
-			cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
-			cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
-			for (j = 0; j < d.naddrs; j++) {
-				cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
-				cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
-				ret = nft_cmd_rule_delete(h, chain,
-						      table, cs, verbose);
-			}
-		} else if (family == AF_INET6) {
-			memcpy(&cs->fw6.ipv6.src,
-			       &s.addr.v6[i], sizeof(struct in6_addr));
-			memcpy(&cs->fw6.ipv6.smsk,
-			       &s.mask.v6[i], sizeof(struct in6_addr));
-			for (j = 0; j < d.naddrs; j++) {
-				memcpy(&cs->fw6.ipv6.dst,
-				       &d.addr.v6[j], sizeof(struct in6_addr));
-				memcpy(&cs->fw6.ipv6.dmsk,
-				       &d.mask.v6[j], sizeof(struct in6_addr));
-				ret = nft_cmd_rule_delete(h, chain,
-						      table, cs, verbose);
-			}
-		}
-	}
-
-	return ret;
-}
-
-static int
-check_entry(const char *chain, const char *table,
-	    struct iptables_command_state *cs,
-	    int family,
-	    const struct addr_mask s,
-	    const struct addr_mask d,
-	    bool verbose, struct nft_handle *h)
-{
-	unsigned int i, j;
-	int ret = 1;
-
-	for (i = 0; i < s.naddrs; i++) {
-		if (family == AF_INET) {
-			cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
-			cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
-			for (j = 0; j < d.naddrs; j++) {
-				cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
-				cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
-				ret = nft_cmd_rule_check(h, chain,
-						     table, cs, verbose);
-			}
-		} else if (family == AF_INET6) {
-			memcpy(&cs->fw6.ipv6.src,
-			       &s.addr.v6[i], sizeof(struct in6_addr));
-			memcpy(&cs->fw6.ipv6.smsk,
-			       &s.mask.v6[i], sizeof(struct in6_addr));
-			for (j = 0; j < d.naddrs; j++) {
-				memcpy(&cs->fw6.ipv6.dst,
-				       &d.addr.v6[j], sizeof(struct in6_addr));
-				memcpy(&cs->fw6.ipv6.dmsk,
-				       &d.mask.v6[j], sizeof(struct in6_addr));
-				ret = nft_cmd_rule_check(h, chain,
-						     table, cs, verbose);
-			}
-		}
-	}
-
-	return ret;
-}
-
 static int
 list_entries(struct nft_handle *h, const char *chain, const char *table,
 	     int rulenum, int verbose, int numeric, int expanded,
@@ -923,33 +761,31 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 
 	switch (p.command) {
 	case CMD_APPEND:
-		ret = add_entry(p.chain, p.table, &cs, 0, h->family,
-				args.s, args.d,
-				cs.options & OPT_VERBOSE, h, true);
+		ret = h->ops->add_entry(h, p.chain, p.table, &cs, &args,
+					cs.options & OPT_VERBOSE, true,
+					p.rulenum - 1);
 		break;
 	case CMD_DELETE:
-		ret = delete_entry(p.chain, p.table, &cs, h->family,
-				   args.s, args.d,
-				   cs.options & OPT_VERBOSE, h);
+		ret = h->ops->delete_entry(h, p.chain, p.table, &cs, &args,
+					   cs.options & OPT_VERBOSE);
 		break;
 	case CMD_DELETE_NUM:
 		ret = nft_cmd_rule_delete_num(h, p.chain, p.table,
 					      p.rulenum - 1, p.verbose);
 		break;
 	case CMD_CHECK:
-		ret = check_entry(p.chain, p.table, &cs, h->family,
-				  args.s, args.d,
-				  cs.options & OPT_VERBOSE, h);
+		ret = h->ops->check_entry(h, p.chain, p.table, &cs, &args,
+					  cs.options & OPT_VERBOSE);
 		break;
 	case CMD_REPLACE:
-		ret = replace_entry(p.chain, p.table, &cs, p.rulenum - 1,
-				    h->family, args.s, args.d,
-				    cs.options & OPT_VERBOSE, h);
+		ret = h->ops->replace_entry(h, p.chain, p.table, &cs, &args,
+					    cs.options & OPT_VERBOSE,
+					    p.rulenum - 1);
 		break;
 	case CMD_INSERT:
-		ret = add_entry(p.chain, p.table, &cs, p.rulenum - 1,
-				h->family, args.s, args.d,
-				cs.options&OPT_VERBOSE, h, false);
+		ret = h->ops->add_entry(h, p.chain, p.table, &cs, &args,
+					cs.options & OPT_VERBOSE, false,
+					p.rulenum - 1);
 		break;
 	case CMD_FLUSH:
 		ret = nft_cmd_rule_flush(h, p.chain, p.table,
-- 
2.33.0


  parent reply	other threads:[~2021-10-15 12:26 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-15 12:25 [iptables PATCH v3 00/13] Eliminate dedicated arptables-nft parser Phil Sutter
2021-10-15 12:25 ` [iptables PATCH v3 01/13] nft: Introduce builtin_tables_lookup() Phil Sutter
2021-10-15 12:25 ` [iptables PATCH v3 02/13] xshared: Store optstring in xtables_globals Phil Sutter
2021-10-15 12:25 ` [iptables PATCH v3 03/13] nft-shared: Introduce init_cs family ops callback Phil Sutter
2021-10-15 12:25 ` [iptables PATCH v3 04/13] xtables: Simplify addr_mask freeing Phil Sutter
2021-10-15 12:26 ` Phil Sutter [this message]
2021-10-15 12:26 ` [iptables PATCH v3 06/13] xtables-standalone: Drop version number from init errors Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 07/13] libxtables: Introduce xtables_globals print_help callback Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 08/13] arptables: Use standard data structures when parsing Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 09/13] nft-arp: Introduce post_parse callback Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 10/13] nft-shared: Make nft_check_xt_legacy() family agnostic Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 11/13] xtables: Derive xtables_globals from family Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 12/13] xtables: arptables accepts empty interface names Phil Sutter
2021-10-15 12:26 ` [iptables PATCH v3 13/13] nft: Merge xtables-arp-standalone.c into xtables-standalone.c Phil Sutter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211015122608.12474-6-phil@nwl.cc \
    --to=phil@nwl.cc \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.