netfilter-devel.vger.kernel.org archive mirror
 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 v2 05/17] nft: Add family ops callbacks wrapping different nft_cmd_* functions
Date: Thu, 30 Sep 2021 16:04:07 +0200	[thread overview]
Message-ID: <20210930140419.6170-6-phil@nwl.cc> (raw)
In-Reply-To: <20210930140419.6170-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-09-30 14:05 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-30 14:04 [iptables PATCH v2 00/17] Eliminate dedicated arptables-nft parser Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 01/17] nft: Introduce builtin_tables_lookup() Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 02/17] xshared: Store optstring in xtables_globals Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 03/17] nft-shared: Introduce init_cs family ops callback Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 04/17] xtables: Simplify addr_mask freeing Phil Sutter
2021-09-30 14:04 ` Phil Sutter [this message]
2021-09-30 14:04 ` [iptables PATCH v2 06/17] xtables-standalone: Drop version number from init errors Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 07/17] libxtables: Introduce xtables_globals print_help callback Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 08/17] arptables: Use standard data structures when parsing Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 09/17] nft-arp: Introduce post_parse callback Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 10/17] nft-shared: Make nft_check_xt_legacy() family agnostic Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 11/17] xtables: Derive xtables_globals from family Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 12/17] nft: Merge xtables-arp-standalone.c into xtables-standalone.c Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 13/17] xtables: arptables doesn't warn about empty interface Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 14/17] xtables: arptables accepts but ignores '-m' Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 15/17] xtables: arptables ignores wrong -t values Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 16/17] xtables: Support '!' betwen option and argument Phil Sutter
2021-09-30 14:04 ` [iptables PATCH v2 17/17] nft: Store maximum allowed chain name length in family ops Phil Sutter
2021-10-14 20:56 ` [iptables PATCH v2 00/17] Eliminate dedicated arptables-nft parser Pablo Neira Ayuso
2021-10-15 11:01   ` Phil Sutter
2021-10-15 11:25     ` Pablo Neira Ayuso

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=20210930140419.6170-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 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).