All of lore.kernel.org
 help / color / mirror / Atom feed
* [iptables PATCH 00/11] Share do_parse() between nft and legacy
@ 2021-12-24 17:17 Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 01/11] xtables: Drop xtables' family on demand feature Phil Sutter
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Patch 1 removes remains of an unused (and otherwise dropped) feature,
yet the change is necessary for the following ones. Patches 2-6 prepare
for patch 7 which moves do_parse() to xshared.c. Patches 8 and 9 prepare
for use of do_parse() from legacy code, Patches 10 and 11 finally drop
legacy ip(6)tables' rule parsing code.

Merry Xmas!

Phil Sutter (11):
  xtables: Drop xtables' family on demand feature
  xtables: Pull table validity check out of do_parse()
  xtables: Move struct nft_xt_cmd_parse to xshared.h
  xtables: Pass xtables_args to check_empty_interface()
  xtables: Pass xtables_args to check_inverse()
  xtables: Do not pass nft_handle to do_parse()
  xshared: Move do_parse to shared space
  xshared: Store parsed wait and wait_interval in xtables_args
  nft: Move proto_parse and post_parse callbacks to xshared
  iptables: Use xtables' do_parse() function
  ip6tables: Use the shared do_parse, too

 iptables/ip6tables.c            | 499 ++---------------------
 iptables/iptables.c             | 484 ++--------------------
 iptables/nft-ipv4.c             |  59 +--
 iptables/nft-ipv6.c             |  76 +---
 iptables/nft-shared.h           |  49 ---
 iptables/xshared.c              | 684 ++++++++++++++++++++++++++++++++
 iptables/xshared.h              |  66 +++
 iptables/xtables-eb-translate.c |   4 +-
 iptables/xtables-translate.c    |  13 +-
 iptables/xtables.c              | 573 +-------------------------
 10 files changed, 839 insertions(+), 1668 deletions(-)

-- 
2.34.1


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

* [iptables PATCH 01/11] xtables: Drop xtables' family on demand feature
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 02/11] xtables: Pull table validity check out of do_parse() Phil Sutter
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

This conditional h->family assignment was added by commit 3f7877e6be987
("xtables-restore: add -4 and -6 support") with the intention to support
something like 'xtables-restore -6 <ip6tables.dump', i.e. having
family-agnostic commands which accept flags to set the family. Yet
commit be70918eab26e ("xtables: rename xt-multi binaries to -nft,
-legacy") removed support for such command names back in 2018 and nobody
has complained so far. Therefore drop this leftover as it makes
do_parse() more generic.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/xtables.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/iptables/xtables.c b/iptables/xtables.c
index 57bec76c31fb3..5c48bd94644f3 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -657,10 +657,6 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 		xtables_error(PARAMETER_PROBLEM,
 			   "nothing appropriate following !");
 
-	/* Set only if required, needed by xtables-restore */
-	if (h->family == AF_UNSPEC)
-		h->family = args->family;
-
 	h->ops->post_parse(p->command, cs, args);
 
 	if (p->command == CMD_REPLACE &&
-- 
2.34.1


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

* [iptables PATCH 02/11] xtables: Pull table validity check out of do_parse()
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 01/11] xtables: Drop xtables' family on demand feature Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 03/11] xtables: Move struct nft_xt_cmd_parse to xshared.h Phil Sutter
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Makes do_parse() more generic, error codes don't change so this should
be safe.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/xtables.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/iptables/xtables.c b/iptables/xtables.c
index 5c48bd94644f3..ac864eb24a35e 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -514,10 +514,6 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 				xtables_error(PARAMETER_PROBLEM,
 					      "The -t option cannot be used in %s.\n",
 					      xt_params->program_name);
-			if (!nft_table_builtin_find(h, optarg))
-				xtables_error(VERSION_PROBLEM,
-					      "table '%s' does not exist",
-					      optarg);
 			p->table = optarg;
 			table_set = true;
 			break;
@@ -720,6 +716,10 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 
 	do_parse(h, argc, argv, &p, &cs, &args);
 
+	if (!nft_table_builtin_find(h, p.table))
+		xtables_error(VERSION_PROBLEM,
+			      "table '%s' does not exist",
+			      p.table);
 	switch (p.command) {
 	case CMD_APPEND:
 		ret = h->ops->add_entry(h, p.chain, p.table, &cs, &args,
-- 
2.34.1


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

* [iptables PATCH 03/11] xtables: Move struct nft_xt_cmd_parse to xshared.h
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 01/11] xtables: Drop xtables' family on demand feature Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 02/11] xtables: Pull table validity check out of do_parse() Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 04/11] xtables: Pass xtables_args to check_empty_interface() Phil Sutter
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Preparing for shared use with legacy variants, move it to "neutral
ground" and give it a more generic name.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-shared.h           | 14 +-------------
 iptables/xshared.h              | 12 ++++++++++++
 iptables/xtables-eb-translate.c |  4 ++--
 iptables/xtables-translate.c    |  8 ++++----
 iptables/xtables.c              |  4 ++--
 5 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index bcf8486eb44c4..4948aef761d10 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -210,20 +210,8 @@ struct xtables_args {
 	unsigned long long pcnt_cnt, bcnt_cnt;
 };
 
-struct nft_xt_cmd_parse {
-	unsigned int			command;
-	unsigned int			rulenum;
-	char				*table;
-	const char			*chain;
-	const char			*newname;
-	const char			*policy;
-	bool				restore;
-	int				verbose;
-	bool				xlate;
-};
-
 void do_parse(struct nft_handle *h, int argc, char *argv[],
-	      struct nft_xt_cmd_parse *p, struct iptables_command_state *cs,
+	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
 	      struct xtables_args *args);
 
 struct nftnl_chain_list;
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 2c05b0d7c4ace..dde94b7335f6a 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -262,4 +262,16 @@ int print_match_save(const struct xt_entry_match *e, const void *ip);
 void xtables_printhelp(const struct xtables_rule_match *matches);
 void exit_tryhelp(int status, int line) __attribute__((noreturn));
 
+struct xt_cmd_parse {
+	unsigned int			command;
+	unsigned int			rulenum;
+	char				*table;
+	const char			*chain;
+	const char			*newname;
+	const char			*policy;
+	bool				restore;
+	int				verbose;
+	bool				xlate;
+};
+
 #endif /* IPTABLES_XSHARED_H */
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
index a6c86b6531e3f..86177024ec703 100644
--- a/iptables/xtables-eb-translate.c
+++ b/iptables/xtables-eb-translate.c
@@ -152,7 +152,7 @@ static void print_ebt_cmd(int argc, char *argv[])
 	printf("\n");
 }
 
-static int nft_rule_eb_xlate_add(struct nft_handle *h, const struct nft_xt_cmd_parse *p,
+static int nft_rule_eb_xlate_add(struct nft_handle *h, const struct xt_cmd_parse *p,
 				 const struct iptables_command_state *cs, bool append)
 {
 	struct xt_xlate *xl = xt_xlate_alloc(10240);
@@ -191,7 +191,7 @@ static int do_commandeb_xlate(struct nft_handle *h, int argc, char *argv[], char
 	int selected_chain = -1;
 	struct xtables_rule_match *xtrm_i;
 	struct ebt_match *match;
-	struct nft_xt_cmd_parse p = {
+	struct xt_cmd_parse p = {
 		.table          = *table,
         };
 
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index e2948c5009dd6..9d312b244657e 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -150,7 +150,7 @@ const char *family2str[] = {
 };
 
 static int nft_rule_xlate_add(struct nft_handle *h,
-			      const struct nft_xt_cmd_parse *p,
+			      const struct xt_cmd_parse *p,
 			      const struct iptables_command_state *cs,
 			      bool append)
 {
@@ -186,11 +186,11 @@ err_out:
 	return ret;
 }
 
-static int xlate(struct nft_handle *h, struct nft_xt_cmd_parse *p,
+static int xlate(struct nft_handle *h, struct xt_cmd_parse *p,
 		 struct iptables_command_state *cs,
 		 struct xtables_args *args, bool append,
 		 int (*cb)(struct nft_handle *h,
-			   const struct nft_xt_cmd_parse *p,
+			   const struct xt_cmd_parse *p,
 			   const struct iptables_command_state *cs,
 			   bool append))
 {
@@ -248,7 +248,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
 			    char **table, bool restore)
 {
 	int ret = 0;
-	struct nft_xt_cmd_parse p = {
+	struct xt_cmd_parse p = {
 		.table		= *table,
 		.restore	= restore,
 		.xlate		= true,
diff --git a/iptables/xtables.c b/iptables/xtables.c
index ac864eb24a35e..837b399aba5b3 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -187,7 +187,7 @@ static void check_inverse(struct nft_handle *h, const char option[],
 }
 
 void do_parse(struct nft_handle *h, int argc, char *argv[],
-	      struct nft_xt_cmd_parse *p, struct iptables_command_state *cs,
+	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
 	      struct xtables_args *args)
 {
 	struct xtables_match *m;
@@ -699,7 +699,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 		bool restore)
 {
 	int ret = 1;
-	struct nft_xt_cmd_parse p = {
+	struct xt_cmd_parse p = {
 		.table		= *table,
 		.restore	= restore,
 	};
-- 
2.34.1


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

* [iptables PATCH 04/11] xtables: Pass xtables_args to check_empty_interface()
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (2 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 03/11] xtables: Move struct nft_xt_cmd_parse to xshared.h Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 05/11] xtables: Pass xtables_args to check_inverse() Phil Sutter
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

It holds the accessed family field as well and is more generic than
nft_handle.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/xtables.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/iptables/xtables.c b/iptables/xtables.c
index 837b399aba5b3..db0cec2461741 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -145,14 +145,14 @@ list_rules(struct nft_handle *h, const char *chain, const char *table,
 	return nft_cmd_rule_list_save(h, chain, table, rulenum, counters);
 }
 
-static void check_empty_interface(struct nft_handle *h, const char *arg)
+static void check_empty_interface(struct xtables_args *args, const char *arg)
 {
 	const char *msg = "Empty interface is likely to be undesired";
 
 	if (*arg != '\0')
 		return;
 
-	if (h->family != NFPROTO_ARP)
+	if (args->family != NFPROTO_ARP)
 		xtables_error(PARAMETER_PROBLEM, msg);
 
 	fprintf(stderr, "%s", msg);
@@ -460,7 +460,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 			break;
 
 		case 'i':
-			check_empty_interface(h, optarg);
+			check_empty_interface(args, optarg);
 			check_inverse(h, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_VIANAMEIN,
 				   &args->invflags, invert);
@@ -470,7 +470,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 			break;
 
 		case 'o':
-			check_empty_interface(h, optarg);
+			check_empty_interface(args, optarg);
 			check_inverse(h, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_VIANAMEOUT,
 				   &args->invflags, invert);
-- 
2.34.1


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

* [iptables PATCH 05/11] xtables: Pass xtables_args to check_inverse()
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (3 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 04/11] xtables: Pass xtables_args to check_empty_interface() Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse() Phil Sutter
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

It holds the accessed family field as well and is more generic than
nft_handle.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/xtables.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/iptables/xtables.c b/iptables/xtables.c
index db0cec2461741..5e8c027b8471e 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -158,10 +158,10 @@ static void check_empty_interface(struct xtables_args *args, const char *arg)
 	fprintf(stderr, "%s", msg);
 }
 
-static void check_inverse(struct nft_handle *h, const char option[],
+static void check_inverse(struct xtables_args *args, const char option[],
 			  bool *invert, int *optidx, int argc)
 {
-	switch (h->family) {
+	switch (args->family) {
 	case NFPROTO_ARP:
 		break;
 	default:
@@ -364,7 +364,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 			 * Option selection
 			 */
 		case 'p':
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_PROTOCOL,
 				   &args->invflags, invert);
 
@@ -387,14 +387,14 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 			break;
 
 		case 's':
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_SOURCE,
 				   &args->invflags, invert);
 			args->shostnetworkmask = argv[optind - 1];
 			break;
 
 		case 'd':
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_DESTINATION,
 				   &args->invflags, invert);
 			args->dhostnetworkmask = argv[optind - 1];
@@ -410,21 +410,21 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 #endif
 
 		case 2:/* src-mac */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_S_MAC, &args->invflags,
 				   invert);
 			args->src_mac = argv[optind - 1];
 			break;
 
 		case 3:/* dst-mac */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_D_MAC, &args->invflags,
 				   invert);
 			args->dst_mac = argv[optind - 1];
 			break;
 
 		case 'l':/* hardware length */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
 				   invert);
 			args->arp_hlen = argv[optind - 1];
@@ -433,21 +433,21 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 		case 8: /* was never supported, not even in arptables-legacy */
 			xtables_error(PARAMETER_PROBLEM, "not supported");
 		case 4:/* opcode */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_OPCODE, &args->invflags,
 				   invert);
 			args->arp_opcode = argv[optind - 1];
 			break;
 
 		case 5:/* h-type */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_H_TYPE, &args->invflags,
 				   invert);
 			args->arp_htype = argv[optind - 1];
 			break;
 
 		case 6:/* proto-type */
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_P_TYPE, &args->invflags,
 				   invert);
 			args->arp_ptype = argv[optind - 1];
@@ -461,7 +461,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 
 		case 'i':
 			check_empty_interface(args, optarg);
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_VIANAMEIN,
 				   &args->invflags, invert);
 			xtables_parse_interface(argv[optind - 1],
@@ -471,7 +471,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 
 		case 'o':
 			check_empty_interface(args, optarg);
-			check_inverse(h, optarg, &invert, &optind, argc);
+			check_inverse(args, optarg, &invert, &optind, argc);
 			set_option(&cs->options, OPT_VIANAMEOUT,
 				   &args->invflags, invert);
 			xtables_parse_interface(argv[optind - 1],
-- 
2.34.1


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

* [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse()
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (4 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 05/11] xtables: Pass xtables_args to check_inverse() Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2022-01-10 21:29   ` Pablo Neira Ayuso
  2021-12-24 17:17 ` [iptables PATCH 07/11] xshared: Move do_parse to shared space Phil Sutter
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Make it fit for sharing with legacy iptables, drop nft-specific
parameter. This requires to mirror proto_parse and post_parse callbacks
from family_ops somewhere reachable - use xt_cmd_parse, it holds other
"parser setup data" as well.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-shared.h        | 35 +--------------------------------
 iptables/xshared.h           | 38 ++++++++++++++++++++++++++++++++++++
 iptables/xtables-translate.c |  4 +++-
 iptables/xtables.c           | 13 +++++++-----
 4 files changed, 50 insertions(+), 40 deletions(-)

diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 4948aef761d10..7396fa991439f 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -177,40 +177,7 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data);
 bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2);
 bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2);
 
-struct addr_mask {
-	union {
-		struct in_addr	*v4;
-		struct in6_addr *v6;
-		void *ptr;
-	} addr;
-
-	unsigned int naddrs;
-
-	union {
-		struct in_addr	*v4;
-		struct in6_addr *v6;
-		void *ptr;
-	} mask;
-};
-
-struct xtables_args {
-	int		family;
-	uint16_t	proto;
-	uint8_t		flags;
-	uint16_t	invflags;
-	char		iniface[IFNAMSIZ], outiface[IFNAMSIZ];
-	unsigned char	iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
-	bool		goto_set;
-	const char	*shostnetworkmask, *dhostnetworkmask;
-	const char	*pcnt, *bcnt;
-	struct addr_mask s, d;
-	const char	*src_mac, *dst_mac;
-	const char	*arp_hlen, *arp_opcode;
-	const char	*arp_htype, *arp_ptype;
-	unsigned long long pcnt_cnt, bcnt_cnt;
-};
-
-void do_parse(struct nft_handle *h, int argc, char *argv[],
+void do_parse(int argc, char *argv[],
 	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
 	      struct xtables_args *args);
 
diff --git a/iptables/xshared.h b/iptables/xshared.h
index dde94b7335f6a..1954168f64058 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -262,6 +262,39 @@ int print_match_save(const struct xt_entry_match *e, const void *ip);
 void xtables_printhelp(const struct xtables_rule_match *matches);
 void exit_tryhelp(int status, int line) __attribute__((noreturn));
 
+struct addr_mask {
+	union {
+		struct in_addr	*v4;
+		struct in6_addr *v6;
+		void *ptr;
+	} addr;
+
+	unsigned int naddrs;
+
+	union {
+		struct in_addr	*v4;
+		struct in6_addr *v6;
+		void *ptr;
+	} mask;
+};
+
+struct xtables_args {
+	int		family;
+	uint16_t	proto;
+	uint8_t		flags;
+	uint16_t	invflags;
+	char		iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+	unsigned char	iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+	bool		goto_set;
+	const char	*shostnetworkmask, *dhostnetworkmask;
+	const char	*pcnt, *bcnt;
+	struct addr_mask s, d;
+	const char	*src_mac, *dst_mac;
+	const char	*arp_hlen, *arp_opcode;
+	const char	*arp_htype, *arp_ptype;
+	unsigned long long pcnt_cnt, bcnt_cnt;
+};
+
 struct xt_cmd_parse {
 	unsigned int			command;
 	unsigned int			rulenum;
@@ -272,6 +305,11 @@ struct xt_cmd_parse {
 	bool				restore;
 	int				verbose;
 	bool				xlate;
+	void		(*proto_parse)(struct iptables_command_state *cs,
+				       struct xtables_args *args);
+	void		(*post_parse)(int command,
+				      struct iptables_command_state *cs,
+				      struct xtables_args *args);
 };
 
 #endif /* IPTABLES_XSHARED_H */
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index 9d312b244657e..b0b27695cbb8c 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -252,6 +252,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
 		.table		= *table,
 		.restore	= restore,
 		.xlate		= true,
+		.proto_parse	= h->ops->proto_parse,
+		.post_parse	= h->ops->post_parse,
 	};
 	struct iptables_command_state cs = {
 		.jumpto = "",
@@ -265,7 +267,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
 	if (h->ops->init_cs)
 		h->ops->init_cs(&cs);
 
-	do_parse(h, argc, argv, &p, &cs, &args);
+	do_parse(argc, argv, &p, &cs, &args);
 
 	cs.restore = restore;
 
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 5e8c027b8471e..d7e22285e089e 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -186,7 +186,7 @@ static void check_inverse(struct xtables_args *args, const char option[],
 	}
 }
 
-void do_parse(struct nft_handle *h, int argc, char *argv[],
+void do_parse(int argc, char *argv[],
 	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
 	      struct xtables_args *args)
 {
@@ -382,8 +382,8 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 					   "rule would never match protocol");
 
 			/* This needs to happen here to parse extensions */
-			if (h->ops->proto_parse)
-				h->ops->proto_parse(cs, args);
+			if (p->proto_parse)
+				p->proto_parse(cs, args);
 			break;
 
 		case 's':
@@ -653,7 +653,8 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
 		xtables_error(PARAMETER_PROBLEM,
 			   "nothing appropriate following !");
 
-	h->ops->post_parse(p->command, cs, args);
+	if (p->post_parse)
+		p->post_parse(p->command, cs, args);
 
 	if (p->command == CMD_REPLACE &&
 	    (args->s.naddrs != 1 || args->d.naddrs != 1))
@@ -702,6 +703,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 	struct xt_cmd_parse p = {
 		.table		= *table,
 		.restore	= restore,
+		.proto_parse	= h->ops->proto_parse,
+		.post_parse	= h->ops->post_parse,
 	};
 	struct iptables_command_state cs = {
 		.jumpto = "",
@@ -714,7 +717,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 	if (h->ops->init_cs)
 		h->ops->init_cs(&cs);
 
-	do_parse(h, argc, argv, &p, &cs, &args);
+	do_parse(argc, argv, &p, &cs, &args);
 
 	if (!nft_table_builtin_find(h, p.table))
 		xtables_error(VERSION_PROBLEM,
-- 
2.34.1


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

* [iptables PATCH 07/11] xshared: Move do_parse to shared space
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (5 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse() Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 08/11] xshared: Store parsed wait and wait_interval in xtables_args Phil Sutter
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Small adjustments were needed:

- Pass line variable via xt_cmd_parse, xshared.c does not have it in
  namespace.
- Replace opts, prog_name and prog_vers defines by the respective
  xt_params field reference.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-shared.h        |   4 -
 iptables/xshared.c           | 553 ++++++++++++++++++++++++++++++++++
 iptables/xshared.h           |   5 +
 iptables/xtables-translate.c |   1 +
 iptables/xtables.c           | 556 +----------------------------------
 5 files changed, 560 insertions(+), 559 deletions(-)

diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 7396fa991439f..a253dd70c335f 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -177,10 +177,6 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data);
 bool compare_matches(struct xtables_rule_match *mt1, struct xtables_rule_match *mt2);
 bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2);
 
-void do_parse(int argc, char *argv[],
-	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
-	      struct xtables_args *args);
-
 struct nftnl_chain_list;
 
 struct nft_xt_restore_cb {
diff --git a/iptables/xshared.c b/iptables/xshared.c
index efee7a30b39fd..7702d899a3586 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1262,3 +1262,556 @@ void exit_tryhelp(int status, int line)
 	xtables_free_opts(1);
 	exit(status);
 }
+
+static void check_empty_interface(struct xtables_args *args, const char *arg)
+{
+	const char *msg = "Empty interface is likely to be undesired";
+
+	if (*arg != '\0')
+		return;
+
+	if (args->family != NFPROTO_ARP)
+		xtables_error(PARAMETER_PROBLEM, msg);
+
+	fprintf(stderr, "%s", msg);
+}
+
+static void check_inverse(struct xtables_args *args, const char option[],
+			  bool *invert, int *optidx, int argc)
+{
+	switch (args->family) {
+	case NFPROTO_ARP:
+		break;
+	default:
+		return;
+	}
+
+	if (!option || strcmp(option, "!"))
+		return;
+
+	fprintf(stderr, "Using intrapositioned negation (`--option ! this`) "
+		"is deprecated in favor of extrapositioned (`! --option this`).\n");
+
+	if (*invert)
+		xtables_error(PARAMETER_PROBLEM,
+			      "Multiple `!' flags not allowed");
+	*invert = true;
+	if (optidx) {
+		*optidx = *optidx + 1;
+		if (argc && *optidx > argc)
+			xtables_error(PARAMETER_PROBLEM,
+				      "no argument following `!'");
+	}
+}
+
+void do_parse(int argc, char *argv[],
+	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
+	      struct xtables_args *args)
+{
+	struct xtables_match *m;
+	struct xtables_rule_match *matchp;
+	bool wait_interval_set = false;
+	struct timeval wait_interval;
+	struct xtables_target *t;
+	bool table_set = false;
+	bool invert = false;
+	int wait = 0;
+
+	/* re-set optind to 0 in case do_command4 gets called
+	 * a second time */
+	optind = 0;
+
+	/* clear mflags in case do_command4 gets called a second time
+	 * (we clear the global list of all matches for security)*/
+	for (m = xtables_matches; m; m = m->next)
+		m->mflags = 0;
+
+	for (t = xtables_targets; t; t = t->next) {
+		t->tflags = 0;
+		t->used = 0;
+	}
+
+	/* Suppress error messages: we may add new options if we
+	   demand-load a protocol. */
+	opterr = 0;
+
+	xt_params->opts = xt_params->orig_opts;
+	while ((cs->c = getopt_long(argc, argv, xt_params->optstring,
+				    xt_params->opts, NULL)) != -1) {
+		switch (cs->c) {
+			/*
+			 * Command selection
+			 */
+		case 'A':
+			add_command(&p->command, CMD_APPEND, CMD_NONE, invert);
+			p->chain = optarg;
+			break;
+
+		case 'C':
+			add_command(&p->command, CMD_CHECK, CMD_NONE, invert);
+			p->chain = optarg;
+			break;
+
+		case 'D':
+			add_command(&p->command, CMD_DELETE, CMD_NONE, invert);
+			p->chain = optarg;
+			if (xs_has_arg(argc, argv)) {
+				p->rulenum = parse_rulenumber(argv[optind++]);
+				p->command = CMD_DELETE_NUM;
+			}
+			break;
+
+		case 'R':
+			add_command(&p->command, CMD_REPLACE, CMD_NONE, invert);
+			p->chain = optarg;
+			if (xs_has_arg(argc, argv))
+				p->rulenum = parse_rulenumber(argv[optind++]);
+			else
+				xtables_error(PARAMETER_PROBLEM,
+					   "-%c requires a rule number",
+					   cmd2char(CMD_REPLACE));
+			break;
+
+		case 'I':
+			add_command(&p->command, CMD_INSERT, CMD_NONE, invert);
+			p->chain = optarg;
+			if (xs_has_arg(argc, argv))
+				p->rulenum = parse_rulenumber(argv[optind++]);
+			else
+				p->rulenum = 1;
+			break;
+
+		case 'L':
+			add_command(&p->command, CMD_LIST,
+				    CMD_ZERO | CMD_ZERO_NUM, invert);
+			if (optarg)
+				p->chain = optarg;
+			else if (xs_has_arg(argc, argv))
+				p->chain = argv[optind++];
+			if (xs_has_arg(argc, argv))
+				p->rulenum = parse_rulenumber(argv[optind++]);
+			break;
+
+		case 'S':
+			add_command(&p->command, CMD_LIST_RULES,
+				    CMD_ZERO|CMD_ZERO_NUM, invert);
+			if (optarg)
+				p->chain = optarg;
+			else if (xs_has_arg(argc, argv))
+				p->chain = argv[optind++];
+			if (xs_has_arg(argc, argv))
+				p->rulenum = parse_rulenumber(argv[optind++]);
+			break;
+
+		case 'F':
+			add_command(&p->command, CMD_FLUSH, CMD_NONE, invert);
+			if (optarg)
+				p->chain = optarg;
+			else if (xs_has_arg(argc, argv))
+				p->chain = argv[optind++];
+			break;
+
+		case 'Z':
+			add_command(&p->command, CMD_ZERO,
+				    CMD_LIST|CMD_LIST_RULES, invert);
+			if (optarg)
+				p->chain = optarg;
+			else if (xs_has_arg(argc, argv))
+				p->chain = argv[optind++];
+			if (xs_has_arg(argc, argv)) {
+				p->rulenum = parse_rulenumber(argv[optind++]);
+				p->command = CMD_ZERO_NUM;
+			}
+			break;
+
+		case 'N':
+			parse_chain(optarg);
+			add_command(&p->command, CMD_NEW_CHAIN, CMD_NONE,
+				    invert);
+			p->chain = optarg;
+			break;
+
+		case 'X':
+			add_command(&p->command, CMD_DELETE_CHAIN, CMD_NONE,
+				    invert);
+			if (optarg)
+				p->chain = optarg;
+			else if (xs_has_arg(argc, argv))
+				p->chain = argv[optind++];
+			break;
+
+		case 'E':
+			add_command(&p->command, CMD_RENAME_CHAIN, CMD_NONE,
+				    invert);
+			p->chain = optarg;
+			if (xs_has_arg(argc, argv))
+				p->newname = argv[optind++];
+			else
+				xtables_error(PARAMETER_PROBLEM,
+					   "-%c requires old-chain-name and "
+					   "new-chain-name",
+					    cmd2char(CMD_RENAME_CHAIN));
+			break;
+
+		case 'P':
+			add_command(&p->command, CMD_SET_POLICY, CMD_NONE,
+				    invert);
+			p->chain = optarg;
+			if (xs_has_arg(argc, argv))
+				p->policy = argv[optind++];
+			else
+				xtables_error(PARAMETER_PROBLEM,
+					   "-%c requires a chain and a policy",
+					   cmd2char(CMD_SET_POLICY));
+			break;
+
+		case 'h':
+			if (!optarg)
+				optarg = argv[optind];
+
+			/* iptables -p icmp -h */
+			if (!cs->matches && cs->protocol)
+				xtables_find_match(cs->protocol,
+					XTF_TRY_LOAD, &cs->matches);
+
+			xt_params->print_help(cs->matches);
+			p->command = CMD_NONE;
+			return;
+
+			/*
+			 * Option selection
+			 */
+		case 'p':
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_PROTOCOL,
+				   &args->invflags, invert);
+
+			/* Canonicalize into lower case */
+			for (cs->protocol = argv[optind - 1];
+			     *cs->protocol; cs->protocol++)
+				*cs->protocol = tolower(*cs->protocol);
+
+			cs->protocol = argv[optind - 1];
+			args->proto = xtables_parse_protocol(cs->protocol);
+
+			if (args->proto == 0 &&
+			    (args->invflags & XT_INV_PROTO))
+				xtables_error(PARAMETER_PROBLEM,
+					   "rule would never match protocol");
+
+			/* This needs to happen here to parse extensions */
+			if (p->proto_parse)
+				p->proto_parse(cs, args);
+			break;
+
+		case 's':
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_SOURCE,
+				   &args->invflags, invert);
+			args->shostnetworkmask = argv[optind - 1];
+			break;
+
+		case 'd':
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_DESTINATION,
+				   &args->invflags, invert);
+			args->dhostnetworkmask = argv[optind - 1];
+			break;
+
+#ifdef IPT_F_GOTO
+		case 'g':
+			set_option(&cs->options, OPT_JUMP, &args->invflags,
+				   invert);
+			args->goto_set = true;
+			cs->jumpto = xt_parse_target(optarg);
+			break;
+#endif
+
+		case 2:/* src-mac */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_S_MAC, &args->invflags,
+				   invert);
+			args->src_mac = argv[optind - 1];
+			break;
+
+		case 3:/* dst-mac */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_D_MAC, &args->invflags,
+				   invert);
+			args->dst_mac = argv[optind - 1];
+			break;
+
+		case 'l':/* hardware length */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
+				   invert);
+			args->arp_hlen = argv[optind - 1];
+			break;
+
+		case 8: /* was never supported, not even in arptables-legacy */
+			xtables_error(PARAMETER_PROBLEM, "not supported");
+		case 4:/* opcode */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_OPCODE, &args->invflags,
+				   invert);
+			args->arp_opcode = argv[optind - 1];
+			break;
+
+		case 5:/* h-type */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_H_TYPE, &args->invflags,
+				   invert);
+			args->arp_htype = argv[optind - 1];
+			break;
+
+		case 6:/* proto-type */
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_P_TYPE, &args->invflags,
+				   invert);
+			args->arp_ptype = argv[optind - 1];
+			break;
+
+		case 'j':
+			set_option(&cs->options, OPT_JUMP, &args->invflags,
+				   invert);
+			command_jump(cs, argv[optind - 1]);
+			break;
+
+		case 'i':
+			check_empty_interface(args, optarg);
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_VIANAMEIN,
+				   &args->invflags, invert);
+			xtables_parse_interface(argv[optind - 1],
+						args->iniface,
+						args->iniface_mask);
+			break;
+
+		case 'o':
+			check_empty_interface(args, optarg);
+			check_inverse(args, optarg, &invert, &optind, argc);
+			set_option(&cs->options, OPT_VIANAMEOUT,
+				   &args->invflags, invert);
+			xtables_parse_interface(argv[optind - 1],
+						args->outiface,
+						args->outiface_mask);
+			break;
+
+		case 'f':
+			if (args->family == AF_INET6) {
+				xtables_error(PARAMETER_PROBLEM,
+					"`-f' is not supported in IPv6, "
+					"use -m frag instead");
+			}
+			set_option(&cs->options, OPT_FRAGMENT, &args->invflags,
+				   invert);
+			args->flags |= IPT_F_FRAG;
+			break;
+
+		case 'v':
+			if (!p->verbose)
+				set_option(&cs->options, OPT_VERBOSE,
+					   &args->invflags, invert);
+			p->verbose++;
+			break;
+
+		case 'm':
+			command_match(cs, invert);
+			break;
+
+		case 'n':
+			set_option(&cs->options, OPT_NUMERIC, &args->invflags,
+				   invert);
+			break;
+
+		case 't':
+			if (invert)
+				xtables_error(PARAMETER_PROBLEM,
+					   "unexpected ! flag before --table");
+			if (p->restore && table_set)
+				xtables_error(PARAMETER_PROBLEM,
+					      "The -t option cannot be used in %s.\n",
+					      xt_params->program_name);
+			p->table = optarg;
+			table_set = true;
+			break;
+
+		case 'x':
+			set_option(&cs->options, OPT_EXPANDED, &args->invflags,
+				   invert);
+			break;
+
+		case 'V':
+			if (invert)
+				printf("Not %s ;-)\n",
+				       xt_params->program_version);
+			else
+				printf("%s v%s\n",
+				       xt_params->program_name,
+				       xt_params->program_version);
+			exit(0);
+
+		case 'w':
+			if (p->restore) {
+				xtables_error(PARAMETER_PROBLEM,
+					      "You cannot use `-w' from "
+					      "iptables-restore");
+			}
+
+			wait = parse_wait_time(argc, argv);
+			break;
+
+		case 'W':
+			if (p->restore) {
+				xtables_error(PARAMETER_PROBLEM,
+					      "You cannot use `-W' from "
+					      "iptables-restore");
+			}
+
+			parse_wait_interval(argc, argv, &wait_interval);
+			wait_interval_set = true;
+			break;
+
+		case '0':
+			set_option(&cs->options, OPT_LINENUMBERS,
+				   &args->invflags, invert);
+			break;
+
+		case 'M':
+			xtables_modprobe_program = optarg;
+			break;
+
+		case 'c':
+			set_option(&cs->options, OPT_COUNTERS, &args->invflags,
+				   invert);
+			args->pcnt = optarg;
+			args->bcnt = strchr(args->pcnt + 1, ',');
+			if (args->bcnt)
+			    args->bcnt++;
+			if (!args->bcnt && xs_has_arg(argc, argv))
+				args->bcnt = argv[optind++];
+			if (!args->bcnt)
+				xtables_error(PARAMETER_PROBLEM,
+					"-%c requires packet and byte counter",
+					opt2char(OPT_COUNTERS));
+
+			if (sscanf(args->pcnt, "%llu", &args->pcnt_cnt) != 1)
+				xtables_error(PARAMETER_PROBLEM,
+					"-%c packet counter not numeric",
+					opt2char(OPT_COUNTERS));
+
+			if (sscanf(args->bcnt, "%llu", &args->bcnt_cnt) != 1)
+				xtables_error(PARAMETER_PROBLEM,
+					"-%c byte counter not numeric",
+					opt2char(OPT_COUNTERS));
+			break;
+
+		case '4':
+			if (args->family == AF_INET)
+				break;
+
+			if (p->restore && args->family == AF_INET6)
+				return;
+
+			exit_tryhelp(2, p->line);
+
+		case '6':
+			if (args->family == AF_INET6)
+				break;
+
+			if (p->restore && args->family == AF_INET)
+				return;
+
+			exit_tryhelp(2, p->line);
+
+		case 1: /* non option */
+			if (optarg[0] == '!' && optarg[1] == '\0') {
+				if (invert)
+					xtables_error(PARAMETER_PROBLEM,
+						   "multiple consecutive ! not"
+						   " allowed");
+				invert = true;
+				optarg[0] = '\0';
+				continue;
+			}
+			fprintf(stderr, "Bad argument `%s'\n", optarg);
+			exit_tryhelp(2, p->line);
+
+		default:
+			if (command_default(cs, xt_params, invert))
+				/* cf. ip6tables.c */
+				continue;
+			break;
+		}
+		invert = false;
+	}
+
+	if (strcmp(p->table, "nat") == 0 &&
+	    ((p->policy != NULL && strcmp(p->policy, "DROP") == 0) ||
+	    (cs->jumpto != NULL && strcmp(cs->jumpto, "DROP") == 0)))
+		xtables_error(PARAMETER_PROBLEM,
+			"\nThe \"nat\" table is not intended for filtering, "
+			"the use of DROP is therefore inhibited.\n\n");
+
+	if (!wait && wait_interval_set)
+		xtables_error(PARAMETER_PROBLEM,
+			      "--wait-interval only makes sense with --wait\n");
+
+	for (matchp = cs->matches; matchp; matchp = matchp->next)
+		xtables_option_mfcall(matchp->match);
+	if (cs->target != NULL)
+		xtables_option_tfcall(cs->target);
+
+	/* Fix me: must put inverse options checking here --MN */
+
+	if (optind < argc)
+		xtables_error(PARAMETER_PROBLEM,
+			   "unknown arguments found on commandline");
+	if (!p->command)
+		xtables_error(PARAMETER_PROBLEM, "no command specified");
+	if (invert)
+		xtables_error(PARAMETER_PROBLEM,
+			   "nothing appropriate following !");
+
+	if (p->post_parse)
+		p->post_parse(p->command, cs, args);
+
+	if (p->command == CMD_REPLACE &&
+	    (args->s.naddrs != 1 || args->d.naddrs != 1))
+		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
+			   "specify a unique address");
+
+	generic_opt_check(p->command, cs->options);
+
+	if (p->chain != NULL && strlen(p->chain) >= XT_EXTENSION_MAXNAMELEN)
+		xtables_error(PARAMETER_PROBLEM,
+			   "chain name `%s' too long (must be under %u chars)",
+			   p->chain, XT_EXTENSION_MAXNAMELEN);
+
+	if (p->command == CMD_APPEND ||
+	    p->command == CMD_DELETE ||
+	    p->command == CMD_DELETE_NUM ||
+	    p->command == CMD_CHECK ||
+	    p->command == CMD_INSERT ||
+	    p->command == CMD_REPLACE) {
+		if (strcmp(p->chain, "PREROUTING") == 0
+		    || strcmp(p->chain, "INPUT") == 0) {
+			/* -o not valid with incoming packets. */
+			if (cs->options & OPT_VIANAMEOUT)
+				xtables_error(PARAMETER_PROBLEM,
+					   "Can't use -%c with %s\n",
+					   opt2char(OPT_VIANAMEOUT),
+					   p->chain);
+		}
+
+		if (strcmp(p->chain, "POSTROUTING") == 0
+		    || strcmp(p->chain, "OUTPUT") == 0) {
+			/* -i not valid with outgoing packets */
+			if (cs->options & OPT_VIANAMEIN)
+				xtables_error(PARAMETER_PROBLEM,
+					   "Can't use -%c with %s\n",
+					   opt2char(OPT_VIANAMEIN),
+					   p->chain);
+		}
+	}
+}
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 1954168f64058..2737ba4b11c25 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -303,6 +303,7 @@ struct xt_cmd_parse {
 	const char			*newname;
 	const char			*policy;
 	bool				restore;
+	int				line;
 	int				verbose;
 	bool				xlate;
 	void		(*proto_parse)(struct iptables_command_state *cs,
@@ -312,4 +313,8 @@ struct xt_cmd_parse {
 				      struct xtables_args *args);
 };
 
+void do_parse(int argc, char *argv[],
+	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
+	      struct xtables_args *args);
+
 #endif /* IPTABLES_XSHARED_H */
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index b0b27695cbb8c..076b7249329bc 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -251,6 +251,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
 	struct xt_cmd_parse p = {
 		.table		= *table,
 		.restore	= restore,
+		.line		= line,
 		.xlate		= true,
 		.proto_parse	= h->ops->proto_parse,
 		.post_parse	= h->ops->post_parse,
diff --git a/iptables/xtables.c b/iptables/xtables.c
index d7e22285e089e..6d79215755b3e 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -95,10 +95,6 @@ struct xtables_globals xtables_globals = {
 	.print_help = xtables_printhelp,
 };
 
-#define opts xt_params->opts
-#define prog_name xt_params->program_name
-#define prog_vers xt_params->program_version
-
 /*
  *	All functions starting with "parse" should succeed, otherwise
  *	the program fails.
@@ -145,557 +141,6 @@ list_rules(struct nft_handle *h, const char *chain, const char *table,
 	return nft_cmd_rule_list_save(h, chain, table, rulenum, counters);
 }
 
-static void check_empty_interface(struct xtables_args *args, const char *arg)
-{
-	const char *msg = "Empty interface is likely to be undesired";
-
-	if (*arg != '\0')
-		return;
-
-	if (args->family != NFPROTO_ARP)
-		xtables_error(PARAMETER_PROBLEM, msg);
-
-	fprintf(stderr, "%s", msg);
-}
-
-static void check_inverse(struct xtables_args *args, const char option[],
-			  bool *invert, int *optidx, int argc)
-{
-	switch (args->family) {
-	case NFPROTO_ARP:
-		break;
-	default:
-		return;
-	}
-
-	if (!option || strcmp(option, "!"))
-		return;
-
-	fprintf(stderr, "Using intrapositioned negation (`--option ! this`) "
-		"is deprecated in favor of extrapositioned (`! --option this`).\n");
-
-	if (*invert)
-		xtables_error(PARAMETER_PROBLEM,
-			      "Multiple `!' flags not allowed");
-	*invert = true;
-	if (optidx) {
-		*optidx = *optidx + 1;
-		if (argc && *optidx > argc)
-			xtables_error(PARAMETER_PROBLEM,
-				      "no argument following `!'");
-	}
-}
-
-void do_parse(int argc, char *argv[],
-	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
-	      struct xtables_args *args)
-{
-	struct xtables_match *m;
-	struct xtables_rule_match *matchp;
-	bool wait_interval_set = false;
-	struct timeval wait_interval;
-	struct xtables_target *t;
-	bool table_set = false;
-	bool invert = false;
-	int wait = 0;
-
-	/* re-set optind to 0 in case do_command4 gets called
-	 * a second time */
-	optind = 0;
-
-	/* clear mflags in case do_command4 gets called a second time
-	 * (we clear the global list of all matches for security)*/
-	for (m = xtables_matches; m; m = m->next)
-		m->mflags = 0;
-
-	for (t = xtables_targets; t; t = t->next) {
-		t->tflags = 0;
-		t->used = 0;
-	}
-
-	/* Suppress error messages: we may add new options if we
-	   demand-load a protocol. */
-	opterr = 0;
-
-	opts = xt_params->orig_opts;
-	while ((cs->c = getopt_long(argc, argv, xt_params->optstring,
-					   opts, NULL)) != -1) {
-		switch (cs->c) {
-			/*
-			 * Command selection
-			 */
-		case 'A':
-			add_command(&p->command, CMD_APPEND, CMD_NONE, invert);
-			p->chain = optarg;
-			break;
-
-		case 'C':
-			add_command(&p->command, CMD_CHECK, CMD_NONE, invert);
-			p->chain = optarg;
-			break;
-
-		case 'D':
-			add_command(&p->command, CMD_DELETE, CMD_NONE, invert);
-			p->chain = optarg;
-			if (xs_has_arg(argc, argv)) {
-				p->rulenum = parse_rulenumber(argv[optind++]);
-				p->command = CMD_DELETE_NUM;
-			}
-			break;
-
-		case 'R':
-			add_command(&p->command, CMD_REPLACE, CMD_NONE, invert);
-			p->chain = optarg;
-			if (xs_has_arg(argc, argv))
-				p->rulenum = parse_rulenumber(argv[optind++]);
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a rule number",
-					   cmd2char(CMD_REPLACE));
-			break;
-
-		case 'I':
-			add_command(&p->command, CMD_INSERT, CMD_NONE, invert);
-			p->chain = optarg;
-			if (xs_has_arg(argc, argv))
-				p->rulenum = parse_rulenumber(argv[optind++]);
-			else
-				p->rulenum = 1;
-			break;
-
-		case 'L':
-			add_command(&p->command, CMD_LIST,
-				    CMD_ZERO | CMD_ZERO_NUM, invert);
-			if (optarg)
-				p->chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				p->chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				p->rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'S':
-			add_command(&p->command, CMD_LIST_RULES,
-				    CMD_ZERO|CMD_ZERO_NUM, invert);
-			if (optarg)
-				p->chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				p->chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				p->rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'F':
-			add_command(&p->command, CMD_FLUSH, CMD_NONE, invert);
-			if (optarg)
-				p->chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				p->chain = argv[optind++];
-			break;
-
-		case 'Z':
-			add_command(&p->command, CMD_ZERO,
-				    CMD_LIST|CMD_LIST_RULES, invert);
-			if (optarg)
-				p->chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				p->chain = argv[optind++];
-			if (xs_has_arg(argc, argv)) {
-				p->rulenum = parse_rulenumber(argv[optind++]);
-				p->command = CMD_ZERO_NUM;
-			}
-			break;
-
-		case 'N':
-			parse_chain(optarg);
-			add_command(&p->command, CMD_NEW_CHAIN, CMD_NONE,
-				    invert);
-			p->chain = optarg;
-			break;
-
-		case 'X':
-			add_command(&p->command, CMD_DELETE_CHAIN, CMD_NONE,
-				    invert);
-			if (optarg)
-				p->chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				p->chain = argv[optind++];
-			break;
-
-		case 'E':
-			add_command(&p->command, CMD_RENAME_CHAIN, CMD_NONE,
-				    invert);
-			p->chain = optarg;
-			if (xs_has_arg(argc, argv))
-				p->newname = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires old-chain-name and "
-					   "new-chain-name",
-					    cmd2char(CMD_RENAME_CHAIN));
-			break;
-
-		case 'P':
-			add_command(&p->command, CMD_SET_POLICY, CMD_NONE,
-				    invert);
-			p->chain = optarg;
-			if (xs_has_arg(argc, argv))
-				p->policy = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a chain and a policy",
-					   cmd2char(CMD_SET_POLICY));
-			break;
-
-		case 'h':
-			if (!optarg)
-				optarg = argv[optind];
-
-			/* iptables -p icmp -h */
-			if (!cs->matches && cs->protocol)
-				xtables_find_match(cs->protocol,
-					XTF_TRY_LOAD, &cs->matches);
-
-			xt_params->print_help(cs->matches);
-			p->command = CMD_NONE;
-			return;
-
-			/*
-			 * Option selection
-			 */
-		case 'p':
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_PROTOCOL,
-				   &args->invflags, invert);
-
-			/* Canonicalize into lower case */
-			for (cs->protocol = argv[optind - 1];
-			     *cs->protocol; cs->protocol++)
-				*cs->protocol = tolower(*cs->protocol);
-
-			cs->protocol = argv[optind - 1];
-			args->proto = xtables_parse_protocol(cs->protocol);
-
-			if (args->proto == 0 &&
-			    (args->invflags & XT_INV_PROTO))
-				xtables_error(PARAMETER_PROBLEM,
-					   "rule would never match protocol");
-
-			/* This needs to happen here to parse extensions */
-			if (p->proto_parse)
-				p->proto_parse(cs, args);
-			break;
-
-		case 's':
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_SOURCE,
-				   &args->invflags, invert);
-			args->shostnetworkmask = argv[optind - 1];
-			break;
-
-		case 'd':
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_DESTINATION,
-				   &args->invflags, invert);
-			args->dhostnetworkmask = argv[optind - 1];
-			break;
-
-#ifdef IPT_F_GOTO
-		case 'g':
-			set_option(&cs->options, OPT_JUMP, &args->invflags,
-				   invert);
-			args->goto_set = true;
-			cs->jumpto = xt_parse_target(optarg);
-			break;
-#endif
-
-		case 2:/* src-mac */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_S_MAC, &args->invflags,
-				   invert);
-			args->src_mac = argv[optind - 1];
-			break;
-
-		case 3:/* dst-mac */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_D_MAC, &args->invflags,
-				   invert);
-			args->dst_mac = argv[optind - 1];
-			break;
-
-		case 'l':/* hardware length */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
-				   invert);
-			args->arp_hlen = argv[optind - 1];
-			break;
-
-		case 8: /* was never supported, not even in arptables-legacy */
-			xtables_error(PARAMETER_PROBLEM, "not supported");
-		case 4:/* opcode */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_OPCODE, &args->invflags,
-				   invert);
-			args->arp_opcode = argv[optind - 1];
-			break;
-
-		case 5:/* h-type */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_H_TYPE, &args->invflags,
-				   invert);
-			args->arp_htype = argv[optind - 1];
-			break;
-
-		case 6:/* proto-type */
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_P_TYPE, &args->invflags,
-				   invert);
-			args->arp_ptype = argv[optind - 1];
-			break;
-
-		case 'j':
-			set_option(&cs->options, OPT_JUMP, &args->invflags,
-				   invert);
-			command_jump(cs, argv[optind - 1]);
-			break;
-
-		case 'i':
-			check_empty_interface(args, optarg);
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_VIANAMEIN,
-				   &args->invflags, invert);
-			xtables_parse_interface(argv[optind - 1],
-						args->iniface,
-						args->iniface_mask);
-			break;
-
-		case 'o':
-			check_empty_interface(args, optarg);
-			check_inverse(args, optarg, &invert, &optind, argc);
-			set_option(&cs->options, OPT_VIANAMEOUT,
-				   &args->invflags, invert);
-			xtables_parse_interface(argv[optind - 1],
-						args->outiface,
-						args->outiface_mask);
-			break;
-
-		case 'f':
-			if (args->family == AF_INET6) {
-				xtables_error(PARAMETER_PROBLEM,
-					"`-f' is not supported in IPv6, "
-					"use -m frag instead");
-			}
-			set_option(&cs->options, OPT_FRAGMENT, &args->invflags,
-				   invert);
-			args->flags |= IPT_F_FRAG;
-			break;
-
-		case 'v':
-			if (!p->verbose)
-				set_option(&cs->options, OPT_VERBOSE,
-					   &args->invflags, invert);
-			p->verbose++;
-			break;
-
-		case 'm':
-			command_match(cs, invert);
-			break;
-
-		case 'n':
-			set_option(&cs->options, OPT_NUMERIC, &args->invflags,
-				   invert);
-			break;
-
-		case 't':
-			if (invert)
-				xtables_error(PARAMETER_PROBLEM,
-					   "unexpected ! flag before --table");
-			if (p->restore && table_set)
-				xtables_error(PARAMETER_PROBLEM,
-					      "The -t option cannot be used in %s.\n",
-					      xt_params->program_name);
-			p->table = optarg;
-			table_set = true;
-			break;
-
-		case 'x':
-			set_option(&cs->options, OPT_EXPANDED, &args->invflags,
-				   invert);
-			break;
-
-		case 'V':
-			if (invert)
-				printf("Not %s ;-)\n", prog_vers);
-			else
-				printf("%s v%s\n",
-				       prog_name, prog_vers);
-			exit(0);
-
-		case 'w':
-			if (p->restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-w' from "
-					      "iptables-restore");
-			}
-
-			wait = parse_wait_time(argc, argv);
-			break;
-
-		case 'W':
-			if (p->restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-W' from "
-					      "iptables-restore");
-			}
-
-			parse_wait_interval(argc, argv, &wait_interval);
-			wait_interval_set = true;
-			break;
-
-		case '0':
-			set_option(&cs->options, OPT_LINENUMBERS,
-				   &args->invflags, invert);
-			break;
-
-		case 'M':
-			xtables_modprobe_program = optarg;
-			break;
-
-		case 'c':
-			set_option(&cs->options, OPT_COUNTERS, &args->invflags,
-				   invert);
-			args->pcnt = optarg;
-			args->bcnt = strchr(args->pcnt + 1, ',');
-			if (args->bcnt)
-			    args->bcnt++;
-			if (!args->bcnt && xs_has_arg(argc, argv))
-				args->bcnt = argv[optind++];
-			if (!args->bcnt)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c requires packet and byte counter",
-					opt2char(OPT_COUNTERS));
-
-			if (sscanf(args->pcnt, "%llu", &args->pcnt_cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c packet counter not numeric",
-					opt2char(OPT_COUNTERS));
-
-			if (sscanf(args->bcnt, "%llu", &args->bcnt_cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c byte counter not numeric",
-					opt2char(OPT_COUNTERS));
-			break;
-
-		case '4':
-			if (args->family == AF_INET)
-				break;
-
-			if (p->restore && args->family == AF_INET6)
-				return;
-
-			exit_tryhelp(2, line);
-
-		case '6':
-			if (args->family == AF_INET6)
-				break;
-
-			if (p->restore && args->family == AF_INET)
-				return;
-
-			exit_tryhelp(2, line);
-
-		case 1: /* non option */
-			if (optarg[0] == '!' && optarg[1] == '\0') {
-				if (invert)
-					xtables_error(PARAMETER_PROBLEM,
-						   "multiple consecutive ! not"
-						   " allowed");
-				invert = true;
-				optarg[0] = '\0';
-				continue;
-			}
-			fprintf(stderr, "Bad argument `%s'\n", optarg);
-			exit_tryhelp(2, line);
-
-		default:
-			if (command_default(cs, xt_params, invert))
-				/* cf. ip6tables.c */
-				continue;
-			break;
-		}
-		invert = false;
-	}
-
-	if (strcmp(p->table, "nat") == 0 &&
-	    ((p->policy != NULL && strcmp(p->policy, "DROP") == 0) ||
-	    (cs->jumpto != NULL && strcmp(cs->jumpto, "DROP") == 0)))
-		xtables_error(PARAMETER_PROBLEM,
-			"\nThe \"nat\" table is not intended for filtering, "
-			"the use of DROP is therefore inhibited.\n\n");
-
-	if (!wait && wait_interval_set)
-		xtables_error(PARAMETER_PROBLEM,
-			      "--wait-interval only makes sense with --wait\n");
-
-	for (matchp = cs->matches; matchp; matchp = matchp->next)
-		xtables_option_mfcall(matchp->match);
-	if (cs->target != NULL)
-		xtables_option_tfcall(cs->target);
-
-	/* Fix me: must put inverse options checking here --MN */
-
-	if (optind < argc)
-		xtables_error(PARAMETER_PROBLEM,
-			   "unknown arguments found on commandline");
-	if (!p->command)
-		xtables_error(PARAMETER_PROBLEM, "no command specified");
-	if (invert)
-		xtables_error(PARAMETER_PROBLEM,
-			   "nothing appropriate following !");
-
-	if (p->post_parse)
-		p->post_parse(p->command, cs, args);
-
-	if (p->command == CMD_REPLACE &&
-	    (args->s.naddrs != 1 || args->d.naddrs != 1))
-		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
-			   "specify a unique address");
-
-	generic_opt_check(p->command, cs->options);
-
-	if (p->chain != NULL && strlen(p->chain) >= XT_EXTENSION_MAXNAMELEN)
-		xtables_error(PARAMETER_PROBLEM,
-			   "chain name `%s' too long (must be under %u chars)",
-			   p->chain, XT_EXTENSION_MAXNAMELEN);
-
-	if (p->command == CMD_APPEND ||
-	    p->command == CMD_DELETE ||
-	    p->command == CMD_DELETE_NUM ||
-	    p->command == CMD_CHECK ||
-	    p->command == CMD_INSERT ||
-	    p->command == CMD_REPLACE) {
-		if (strcmp(p->chain, "PREROUTING") == 0
-		    || strcmp(p->chain, "INPUT") == 0) {
-			/* -o not valid with incoming packets. */
-			if (cs->options & OPT_VIANAMEOUT)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEOUT),
-					   p->chain);
-		}
-
-		if (strcmp(p->chain, "POSTROUTING") == 0
-		    || strcmp(p->chain, "OUTPUT") == 0) {
-			/* -i not valid with outgoing packets */
-			if (cs->options & OPT_VIANAMEIN)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEIN),
-					   p->chain);
-		}
-	}
-}
-
 int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 		bool restore)
 {
@@ -703,6 +148,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 	struct xt_cmd_parse p = {
 		.table		= *table,
 		.restore	= restore,
+		.line		= line,
 		.proto_parse	= h->ops->proto_parse,
 		.post_parse	= h->ops->post_parse,
 	};
-- 
2.34.1


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

* [iptables PATCH 08/11] xshared: Store parsed wait and wait_interval in xtables_args
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (6 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 07/11] xshared: Move do_parse to shared space Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 09/11] nft: Move proto_parse and post_parse callbacks to xshared Phil Sutter
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

While nft-variants don't care, legacy ones do.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/xshared.c | 8 +++-----
 iptables/xshared.h | 2 ++
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/iptables/xshared.c b/iptables/xshared.c
index 7702d899a3586..021402ea6165e 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1311,11 +1311,9 @@ void do_parse(int argc, char *argv[],
 	struct xtables_match *m;
 	struct xtables_rule_match *matchp;
 	bool wait_interval_set = false;
-	struct timeval wait_interval;
 	struct xtables_target *t;
 	bool table_set = false;
 	bool invert = false;
-	int wait = 0;
 
 	/* re-set optind to 0 in case do_command4 gets called
 	 * a second time */
@@ -1658,7 +1656,7 @@ void do_parse(int argc, char *argv[],
 					      "iptables-restore");
 			}
 
-			wait = parse_wait_time(argc, argv);
+			args->wait = parse_wait_time(argc, argv);
 			break;
 
 		case 'W':
@@ -1668,7 +1666,7 @@ void do_parse(int argc, char *argv[],
 					      "iptables-restore");
 			}
 
-			parse_wait_interval(argc, argv, &wait_interval);
+			parse_wait_interval(argc, argv, &args->wait_interval);
 			wait_interval_set = true;
 			break;
 
@@ -1753,7 +1751,7 @@ void do_parse(int argc, char *argv[],
 			"\nThe \"nat\" table is not intended for filtering, "
 			"the use of DROP is therefore inhibited.\n\n");
 
-	if (!wait && wait_interval_set)
+	if (!args->wait && wait_interval_set)
 		xtables_error(PARAMETER_PROBLEM,
 			      "--wait-interval only makes sense with --wait\n");
 
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 2737ba4b11c25..6ac1330537731 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -293,6 +293,8 @@ struct xtables_args {
 	const char	*arp_hlen, *arp_opcode;
 	const char	*arp_htype, *arp_ptype;
 	unsigned long long pcnt_cnt, bcnt_cnt;
+	int		wait;
+	struct timeval	wait_interval;
 };
 
 struct xt_cmd_parse {
-- 
2.34.1


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

* [iptables PATCH 09/11] nft: Move proto_parse and post_parse callbacks to xshared
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (7 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 08/11] xshared: Store parsed wait and wait_interval in xtables_args Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 10/11] iptables: Use xtables' do_parse() function Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 11/11] ip6tables: Use the shared do_parse, too Phil Sutter
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

They are not nft-variant-specific and may therefore be shared with
legacy.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-ipv4.c |  59 +--------------------
 iptables/nft-ipv6.c |  76 +-------------------------
 iptables/xshared.c  | 126 ++++++++++++++++++++++++++++++++++++++++++++
 iptables/xshared.h  |   9 ++++
 4 files changed, 139 insertions(+), 131 deletions(-)

diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index f36260980e829..2588babd395a5 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -274,61 +274,6 @@ static void nft_ipv4_save_rule(const void *data, unsigned int format)
 				&cs->fw, format);
 }
 
-static void nft_ipv4_proto_parse(struct iptables_command_state *cs,
-				 struct xtables_args *args)
-{
-	cs->fw.ip.proto = args->proto;
-	cs->fw.ip.invflags = args->invflags;
-}
-
-static void nft_ipv4_post_parse(int command,
-				struct iptables_command_state *cs,
-				struct xtables_args *args)
-{
-	cs->fw.ip.flags = args->flags;
-	/* We already set invflags in proto_parse, but we need to refresh it
-	 * to include new parsed options.
-	 */
-	cs->fw.ip.invflags = args->invflags;
-
-	memcpy(cs->fw.ip.iniface, args->iniface, IFNAMSIZ);
-	memcpy(cs->fw.ip.iniface_mask,
-	       args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
-
-	memcpy(cs->fw.ip.outiface, args->outiface, IFNAMSIZ);
-	memcpy(cs->fw.ip.outiface_mask,
-	       args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
-
-	if (args->goto_set)
-		cs->fw.ip.flags |= IPT_F_GOTO;
-
-	cs->counters.pcnt = args->pcnt_cnt;
-	cs->counters.bcnt = args->bcnt_cnt;
-
-	if (command & (CMD_REPLACE | CMD_INSERT |
-			CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-		if (!(cs->options & OPT_DESTINATION))
-			args->dhostnetworkmask = "0.0.0.0/0";
-		if (!(cs->options & OPT_SOURCE))
-			args->shostnetworkmask = "0.0.0.0/0";
-	}
-
-	if (args->shostnetworkmask)
-		xtables_ipparse_multiple(args->shostnetworkmask,
-					 &args->s.addr.v4, &args->s.mask.v4,
-					 &args->s.naddrs);
-	if (args->dhostnetworkmask)
-		xtables_ipparse_multiple(args->dhostnetworkmask,
-					 &args->d.addr.v4, &args->d.mask.v4,
-					 &args->d.naddrs);
-
-	if ((args->s.naddrs > 1 || args->d.naddrs > 1) &&
-	    (cs->fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
-		xtables_error(PARAMETER_PROBLEM,
-			      "! not allowed with multiple"
-			      " source or destination IP addresses");
-}
-
 static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr,
 			    const struct in_addr *mask,
 			    bool inv, struct xt_xlate *xl)
@@ -510,8 +455,8 @@ struct nft_family_ops nft_family_ops_ipv4 = {
 	.print_rule		= nft_ipv4_print_rule,
 	.save_rule		= nft_ipv4_save_rule,
 	.save_chain		= nft_ipv46_save_chain,
-	.proto_parse		= nft_ipv4_proto_parse,
-	.post_parse		= nft_ipv4_post_parse,
+	.proto_parse		= ipv4_proto_parse,
+	.post_parse		= ipv4_post_parse,
 	.parse_target		= nft_ipv46_parse_target,
 	.rule_to_cs		= nft_rule_to_iptables_command_state,
 	.clear_cs		= nft_clear_iptables_command_state,
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 132130880a43a..6d288112abbfa 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -236,78 +236,6 @@ static void nft_ipv6_save_rule(const void *data, unsigned int format)
 				&cs->fw6, format);
 }
 
-/* These are invalid numbers as upper layer protocol */
-static int is_exthdr(uint16_t proto)
-{
-	return (proto == IPPROTO_ROUTING ||
-		proto == IPPROTO_FRAGMENT ||
-		proto == IPPROTO_AH ||
-		proto == IPPROTO_DSTOPTS);
-}
-
-static void nft_ipv6_proto_parse(struct iptables_command_state *cs,
-				 struct xtables_args *args)
-{
-	cs->fw6.ipv6.proto = args->proto;
-	cs->fw6.ipv6.invflags = args->invflags;
-
-	if (is_exthdr(cs->fw6.ipv6.proto)
-	    && (cs->fw6.ipv6.invflags & XT_INV_PROTO) == 0)
-		fprintf(stderr,
-			"Warning: never matched protocol: %s. "
-			"use extension match instead.\n",
-			cs->protocol);
-}
-
-static void nft_ipv6_post_parse(int command, struct iptables_command_state *cs,
-				struct xtables_args *args)
-{
-	cs->fw6.ipv6.flags = args->flags;
-	/* We already set invflags in proto_parse, but we need to refresh it
-	 * to include new parsed options.
-	 */
-	cs->fw6.ipv6.invflags = args->invflags;
-
-	memcpy(cs->fw6.ipv6.iniface, args->iniface, IFNAMSIZ);
-	memcpy(cs->fw6.ipv6.iniface_mask,
-	       args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
-
-	memcpy(cs->fw6.ipv6.outiface, args->outiface, IFNAMSIZ);
-	memcpy(cs->fw6.ipv6.outiface_mask,
-	       args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
-
-	if (args->goto_set)
-		cs->fw6.ipv6.flags |= IP6T_F_GOTO;
-
-	cs->fw6.counters.pcnt = args->pcnt_cnt;
-	cs->fw6.counters.bcnt = args->bcnt_cnt;
-
-	if (command & (CMD_REPLACE | CMD_INSERT |
-			CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-		if (!(cs->options & OPT_DESTINATION))
-			args->dhostnetworkmask = "::0/0";
-		if (!(cs->options & OPT_SOURCE))
-			args->shostnetworkmask = "::0/0";
-	}
-
-	if (args->shostnetworkmask)
-		xtables_ip6parse_multiple(args->shostnetworkmask,
-					  &args->s.addr.v6,
-					  &args->s.mask.v6,
-					  &args->s.naddrs);
-	if (args->dhostnetworkmask)
-		xtables_ip6parse_multiple(args->dhostnetworkmask,
-					  &args->d.addr.v6,
-					  &args->d.mask.v6,
-					  &args->d.naddrs);
-
-	if ((args->s.naddrs > 1 || args->d.naddrs > 1) &&
-	    (cs->fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
-		xtables_error(PARAMETER_PROBLEM,
-			      "! not allowed with multiple"
-			      " source or destination IP addresses");
-}
-
 static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr,
 			    const struct in6_addr *mask,
 			    int invert, struct xt_xlate *xl)
@@ -495,8 +423,8 @@ struct nft_family_ops nft_family_ops_ipv6 = {
 	.print_rule		= nft_ipv6_print_rule,
 	.save_rule		= nft_ipv6_save_rule,
 	.save_chain		= nft_ipv46_save_chain,
-	.proto_parse		= nft_ipv6_proto_parse,
-	.post_parse		= nft_ipv6_post_parse,
+	.proto_parse		= ipv6_proto_parse,
+	.post_parse		= ipv6_post_parse,
 	.parse_target		= nft_ipv46_parse_target,
 	.rule_to_cs		= nft_rule_to_iptables_command_state,
 	.clear_cs		= nft_clear_iptables_command_state,
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 021402ea6165e..1993c89541527 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1813,3 +1813,129 @@ void do_parse(int argc, char *argv[],
 		}
 	}
 }
+
+void ipv4_proto_parse(struct iptables_command_state *cs,
+		      struct xtables_args *args)
+{
+	cs->fw.ip.proto = args->proto;
+	cs->fw.ip.invflags = args->invflags;
+}
+
+/* These are invalid numbers as upper layer protocol */
+static int is_exthdr(uint16_t proto)
+{
+	return (proto == IPPROTO_ROUTING ||
+		proto == IPPROTO_FRAGMENT ||
+		proto == IPPROTO_AH ||
+		proto == IPPROTO_DSTOPTS);
+}
+
+void ipv6_proto_parse(struct iptables_command_state *cs,
+		      struct xtables_args *args)
+{
+	cs->fw6.ipv6.proto = args->proto;
+	cs->fw6.ipv6.invflags = args->invflags;
+
+	if (is_exthdr(cs->fw6.ipv6.proto)
+	    && (cs->fw6.ipv6.invflags & XT_INV_PROTO) == 0)
+		fprintf(stderr,
+			"Warning: never matched protocol: %s. "
+			"use extension match instead.\n",
+			cs->protocol);
+}
+
+void ipv4_post_parse(int command, struct iptables_command_state *cs,
+		     struct xtables_args *args)
+{
+	cs->fw.ip.flags = args->flags;
+	/* We already set invflags in proto_parse, but we need to refresh it
+	 * to include new parsed options.
+	 */
+	cs->fw.ip.invflags = args->invflags;
+
+	memcpy(cs->fw.ip.iniface, args->iniface, IFNAMSIZ);
+	memcpy(cs->fw.ip.iniface_mask,
+	       args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+	memcpy(cs->fw.ip.outiface, args->outiface, IFNAMSIZ);
+	memcpy(cs->fw.ip.outiface_mask,
+	       args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+	if (args->goto_set)
+		cs->fw.ip.flags |= IPT_F_GOTO;
+
+	cs->counters.pcnt = args->pcnt_cnt;
+	cs->counters.bcnt = args->bcnt_cnt;
+
+	if (command & (CMD_REPLACE | CMD_INSERT |
+			CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+		if (!(cs->options & OPT_DESTINATION))
+			args->dhostnetworkmask = "0.0.0.0/0";
+		if (!(cs->options & OPT_SOURCE))
+			args->shostnetworkmask = "0.0.0.0/0";
+	}
+
+	if (args->shostnetworkmask)
+		xtables_ipparse_multiple(args->shostnetworkmask,
+					 &args->s.addr.v4, &args->s.mask.v4,
+					 &args->s.naddrs);
+	if (args->dhostnetworkmask)
+		xtables_ipparse_multiple(args->dhostnetworkmask,
+					 &args->d.addr.v4, &args->d.mask.v4,
+					 &args->d.naddrs);
+
+	if ((args->s.naddrs > 1 || args->d.naddrs > 1) &&
+	    (cs->fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
+		xtables_error(PARAMETER_PROBLEM,
+			      "! not allowed with multiple"
+			      " source or destination IP addresses");
+}
+
+void ipv6_post_parse(int command, struct iptables_command_state *cs,
+		     struct xtables_args *args)
+{
+	cs->fw6.ipv6.flags = args->flags;
+	/* We already set invflags in proto_parse, but we need to refresh it
+	 * to include new parsed options.
+	 */
+	cs->fw6.ipv6.invflags = args->invflags;
+
+	memcpy(cs->fw6.ipv6.iniface, args->iniface, IFNAMSIZ);
+	memcpy(cs->fw6.ipv6.iniface_mask,
+	       args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+	memcpy(cs->fw6.ipv6.outiface, args->outiface, IFNAMSIZ);
+	memcpy(cs->fw6.ipv6.outiface_mask,
+	       args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+	if (args->goto_set)
+		cs->fw6.ipv6.flags |= IP6T_F_GOTO;
+
+	cs->fw6.counters.pcnt = args->pcnt_cnt;
+	cs->fw6.counters.bcnt = args->bcnt_cnt;
+
+	if (command & (CMD_REPLACE | CMD_INSERT |
+			CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+		if (!(cs->options & OPT_DESTINATION))
+			args->dhostnetworkmask = "::0/0";
+		if (!(cs->options & OPT_SOURCE))
+			args->shostnetworkmask = "::0/0";
+	}
+
+	if (args->shostnetworkmask)
+		xtables_ip6parse_multiple(args->shostnetworkmask,
+					  &args->s.addr.v6,
+					  &args->s.mask.v6,
+					  &args->s.naddrs);
+	if (args->dhostnetworkmask)
+		xtables_ip6parse_multiple(args->dhostnetworkmask,
+					  &args->d.addr.v6,
+					  &args->d.mask.v6,
+					  &args->d.naddrs);
+
+	if ((args->s.naddrs > 1 || args->d.naddrs > 1) &&
+	    (cs->fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
+		xtables_error(PARAMETER_PROBLEM,
+			      "! not allowed with multiple"
+			      " source or destination IP addresses");
+}
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 6ac1330537731..296b3510226f3 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -319,4 +319,13 @@ void do_parse(int argc, char *argv[],
 	      struct xt_cmd_parse *p, struct iptables_command_state *cs,
 	      struct xtables_args *args);
 
+void ipv4_proto_parse(struct iptables_command_state *cs,
+		      struct xtables_args *args);
+void ipv6_proto_parse(struct iptables_command_state *cs,
+		      struct xtables_args *args);
+void ipv4_post_parse(int command, struct iptables_command_state *cs,
+		     struct xtables_args *args);
+void ipv6_post_parse(int command, struct iptables_command_state *cs,
+		     struct xtables_args *args);
+
 #endif /* IPTABLES_XSHARED_H */
-- 
2.34.1


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

* [iptables PATCH 10/11] iptables: Use xtables' do_parse() function
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (8 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 09/11] nft: Move proto_parse and post_parse callbacks to xshared Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  2021-12-24 17:17 ` [iptables PATCH 11/11] ip6tables: Use the shared do_parse, too Phil Sutter
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

To do so, a few conversions are needed:

- Make use of xt_params->optstring
- Make use of xt_params->print_help callback
- Switch to using a proto_parse callback

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/iptables.c | 484 +++-----------------------------------------
 iptables/xshared.c  |   3 +
 2 files changed, 36 insertions(+), 451 deletions(-)

diff --git a/iptables/iptables.c b/iptables/iptables.c
index 7dc4cbc1c9c22..d1bc73f5a2021 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -87,21 +87,12 @@ static struct option original_opts[] = {
 struct xtables_globals iptables_globals = {
 	.option_offset = 0,
 	.program_version = PACKAGE_VERSION " (legacy)",
+	.optstring = OPTSTRING_COMMON "R:S::W::" "46bfg:h::m:nvw::x",
 	.orig_opts = original_opts,
 	.compat_rev = xtables_compatible_revision,
+	.print_help = xtables_printhelp,
 };
 
-#define opts iptables_globals.opts
-#define prog_name iptables_globals.program_name
-#define prog_vers iptables_globals.program_version
-
-static void
-exit_printhelp(const struct xtables_rule_match *matches)
-{
-	xtables_printhelp(matches);
-	exit(0);
-}
-
 /*
  *	All functions starting with "parse" should succeed, otherwise
  *	the program fails.
@@ -699,10 +690,21 @@ generate_entry(const struct ipt_entry *fw,
 int do_command4(int argc, char *argv[], char **table,
 		struct xtc_handle **handle, bool restore)
 {
+	struct xt_cmd_parse p = {
+		.table		= *table,
+		.restore	= restore,
+		.line		= line,
+		.proto_parse	= ipv4_proto_parse,
+		.post_parse	= ipv4_post_parse,
+	};
 	struct iptables_command_state cs = {
 		.jumpto	= "",
 		.argv	= argv,
 	};
+	struct xtables_args args = {
+		.family = AF_INET,
+		.wait_interval.tv_sec = 1,
+	};
 	struct ipt_entry *e = NULL;
 	unsigned int nsaddrs = 0, ndaddrs = 0;
 	struct in_addr *saddrs = NULL, *smasks = NULL;
@@ -710,433 +712,30 @@ int do_command4(int argc, char *argv[], char **table,
 	struct timeval wait_interval = {
 		.tv_sec = 1,
 	};
-	bool wait_interval_set = false;
 	int verbose = 0;
 	int wait = 0;
 	const char *chain = NULL;
-	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
 	const char *policy = NULL, *newname = NULL;
 	unsigned int rulenum = 0, command = 0;
-	const char *pcnt = NULL, *bcnt = NULL;
 	int ret = 1;
-	struct xtables_match *m;
-	struct xtables_rule_match *matchp;
-	struct xtables_target *t;
-	unsigned long long cnt;
-	bool table_set = false;
-	uint16_t invflags = 0;
-	bool invert = false;
-
-	/* re-set optind to 0 in case do_command4 gets called
-	 * a second time */
-	optind = 0;
-
-	/* clear mflags in case do_command4 gets called a second time
-	 * (we clear the global list of all matches for security)*/
-	for (m = xtables_matches; m; m = m->next)
-		m->mflags = 0;
-
-	for (t = xtables_targets; t; t = t->next) {
-		t->tflags = 0;
-		t->used = 0;
-	}
-
-	/* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-	opterr = 0;
-	opts = xt_params->orig_opts;
-	while ((cs.c = getopt_long(argc, argv,
-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::W::nt:m:xc:g:46",
-					   opts, NULL)) != -1) {
-		switch (cs.c) {
-			/*
-			 * Command selection
-			 */
-		case 'A':
-			add_command(&command, CMD_APPEND, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'C':
-			add_command(&command, CMD_CHECK, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'D':
-			add_command(&command, CMD_DELETE, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv)) {
-				rulenum = parse_rulenumber(argv[optind++]);
-				command = CMD_DELETE_NUM;
-			}
-			break;
-
-		case 'R':
-			add_command(&command, CMD_REPLACE, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a rule number",
-					   cmd2char(CMD_REPLACE));
-			break;
-
-		case 'I':
-			add_command(&command, CMD_INSERT, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			else rulenum = 1;
-			break;
-
-		case 'L':
-			add_command(&command, CMD_LIST,
-				    CMD_ZERO | CMD_ZERO_NUM, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'S':
-			add_command(&command, CMD_LIST_RULES,
-				    CMD_ZERO|CMD_ZERO_NUM, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'F':
-			add_command(&command, CMD_FLUSH, CMD_NONE, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			break;
-
-		case 'Z':
-			add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
-				    invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv)) {
-				rulenum = parse_rulenumber(argv[optind++]);
-				command = CMD_ZERO_NUM;
-			}
-			break;
-
-		case 'N':
-			parse_chain(optarg);
-			add_command(&command, CMD_NEW_CHAIN, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'X':
-			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-				    invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			break;
-
-		case 'E':
-			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-				    invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				newname = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires old-chain-name and "
-					   "new-chain-name",
-					    cmd2char(CMD_RENAME_CHAIN));
-			break;
-
-		case 'P':
-			add_command(&command, CMD_SET_POLICY, CMD_NONE,
-				    invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				policy = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a chain and a policy",
-					   cmd2char(CMD_SET_POLICY));
-			break;
-
-		case 'h':
-			if (!optarg)
-				optarg = argv[optind];
-
-			/* iptables -p icmp -h */
-			if (!cs.matches && cs.protocol)
-				xtables_find_match(cs.protocol,
-					XTF_TRY_LOAD, &cs.matches);
-
-			exit_printhelp(cs.matches);
-
-			/*
-			 * Option selection
-			 */
-		case 'p':
-			set_option(&cs.options, OPT_PROTOCOL, &invflags,
-				   invert);
-
-			/* Canonicalize into lower case */
-			for (cs.protocol = optarg; *cs.protocol; cs.protocol++)
-				*cs.protocol = tolower(*cs.protocol);
-
-			cs.protocol = optarg;
-			cs.fw.ip.proto = xtables_parse_protocol(cs.protocol);
-
-			if (cs.fw.ip.proto == 0 && (invflags & XT_INV_PROTO))
-				xtables_error(PARAMETER_PROBLEM,
-					   "rule would never match protocol");
-			break;
-
-		case 's':
-			set_option(&cs.options, OPT_SOURCE, &invflags, invert);
-			shostnetworkmask = optarg;
-			break;
-
-		case 'd':
-			set_option(&cs.options, OPT_DESTINATION, &invflags,
-				   invert);
-			dhostnetworkmask = optarg;
-			break;
-
-#ifdef IPT_F_GOTO
-		case 'g':
-			set_option(&cs.options, OPT_JUMP, &invflags, invert);
-			cs.fw.ip.flags |= IPT_F_GOTO;
-			cs.jumpto = xt_parse_target(optarg);
-			break;
-#endif
-
-		case 'j':
-			set_option(&cs.options, OPT_JUMP, &invflags, invert);
-			command_jump(&cs, optarg);
-			break;
-
-
-		case 'i':
-			if (*optarg == '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"Empty interface is likely to be "
-					"undesired");
-			set_option(&cs.options, OPT_VIANAMEIN, &invflags,
-				   invert);
-			xtables_parse_interface(optarg,
-					cs.fw.ip.iniface,
-					cs.fw.ip.iniface_mask);
-			break;
-
-		case 'o':
-			if (*optarg == '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"Empty interface is likely to be "
-					"undesired");
-			set_option(&cs.options, OPT_VIANAMEOUT, &invflags,
-				   invert);
-			xtables_parse_interface(optarg,
-					cs.fw.ip.outiface,
-					cs.fw.ip.outiface_mask);
-			break;
-
-		case 'f':
-			set_option(&cs.options, OPT_FRAGMENT, &invflags,
-				   invert);
-			cs.fw.ip.flags |= IPT_F_FRAG;
-			break;
-
-		case 'v':
-			if (!verbose)
-				set_option(&cs.options, OPT_VERBOSE,
-					   &invflags, invert);
-			verbose++;
-			break;
-
-		case 'w':
-			if (restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-w' from "
-					      "iptables-restore");
-			}
-			wait = parse_wait_time(argc, argv);
-			break;
 
-		case 'W':
-			if (restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-W' from "
-					      "iptables-restore");
-			}
-			parse_wait_interval(argc, argv, &wait_interval);
-			wait_interval_set = true;
-			break;
-
-		case 'm':
-			command_match(&cs, invert);
-			break;
-
-		case 'n':
-			set_option(&cs.options, OPT_NUMERIC, &invflags,
-				   invert);
-			break;
-
-		case 't':
-			if (invert)
-				xtables_error(PARAMETER_PROBLEM,
-					   "unexpected ! flag before --table");
-			if (restore && table_set)
-				xtables_error(PARAMETER_PROBLEM,
-					      "The -t option cannot be used in %s.\n",
-					      xt_params->program_name);
-			*table = optarg;
-			table_set = true;
-			break;
-
-		case 'x':
-			set_option(&cs.options, OPT_EXPANDED, &invflags,
-				   invert);
-			break;
-
-		case 'V':
-			if (invert)
-				printf("Not %s ;-)\n", prog_vers);
-			else
-				printf("%s v%s\n",
-				       prog_name, prog_vers);
-			exit(0);
-
-		case '0':
-			set_option(&cs.options, OPT_LINENUMBERS, &invflags,
-				   invert);
-			break;
-
-		case 'M':
-			xtables_modprobe_program = optarg;
-			break;
-
-		case 'c':
-
-			set_option(&cs.options, OPT_COUNTERS, &invflags,
-				   invert);
-			pcnt = optarg;
-			bcnt = strchr(pcnt + 1, ',');
-			if (bcnt)
-			    bcnt++;
-			if (!bcnt && xs_has_arg(argc, argv))
-				bcnt = argv[optind++];
-			if (!bcnt)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c requires packet and byte counter",
-					opt2char(OPT_COUNTERS));
-
-			if (sscanf(pcnt, "%llu", &cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c packet counter not numeric",
-					opt2char(OPT_COUNTERS));
-			cs.fw.counters.pcnt = cnt;
-
-			if (sscanf(bcnt, "%llu", &cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c byte counter not numeric",
-					opt2char(OPT_COUNTERS));
-			cs.fw.counters.bcnt = cnt;
-			break;
-
-		case '4':
-			/* This is indeed the IPv4 iptables */
-			break;
-
-		case '6':
-			/* This is not the IPv6 ip6tables */
-			if (line != -1)
-				return 1; /* success: line ignored */
-			fprintf(stderr, "This is the IPv4 version of iptables.\n");
-			exit_tryhelp(2, line);
-
-		case 1: /* non option */
-			if (optarg[0] == '!' && optarg[1] == '\0') {
-				if (invert)
-					xtables_error(PARAMETER_PROBLEM,
-						   "multiple consecutive ! not"
-						   " allowed");
-				invert = true;
-				optarg[0] = '\0';
-				continue;
-			}
-			fprintf(stderr, "Bad argument `%s'\n", optarg);
-			exit_tryhelp(2, line);
-
-		default:
-			if (command_default(&cs, &iptables_globals, invert))
-				/* cf. ip6tables.c */
-				continue;
-			break;
-		}
-		invert = false;
-	}
-
-	if (!wait && wait_interval_set)
-		xtables_error(PARAMETER_PROBLEM,
-			      "--wait-interval only makes sense with --wait\n");
-
-	if (strcmp(*table, "nat") == 0 &&
-	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
-	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
-		xtables_error(PARAMETER_PROBLEM,
-			"\nThe \"nat\" table is not intended for filtering, "
-		        "the use of DROP is therefore inhibited.\n\n");
-
-	for (matchp = cs.matches; matchp; matchp = matchp->next)
-		xtables_option_mfcall(matchp->match);
-	if (cs.target != NULL)
-		xtables_option_tfcall(cs.target);
-
-	/* Fix me: must put inverse options checking here --MN */
-
-	if (optind < argc)
-		xtables_error(PARAMETER_PROBLEM,
-			   "unknown arguments found on commandline");
-	if (!command)
-		xtables_error(PARAMETER_PROBLEM, "no command specified");
-	if (invert)
-		xtables_error(PARAMETER_PROBLEM,
-			   "nothing appropriate following !");
-
-	cs.fw.ip.invflags = invflags;
-
-	if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-		if (!(cs.options & OPT_DESTINATION))
-			dhostnetworkmask = "0.0.0.0/0";
-		if (!(cs.options & OPT_SOURCE))
-			shostnetworkmask = "0.0.0.0/0";
-	}
-
-	if (shostnetworkmask)
-		xtables_ipparse_multiple(shostnetworkmask, &saddrs,
-					 &smasks, &nsaddrs);
-
-	if (dhostnetworkmask)
-		xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
-					 &dmasks, &ndaddrs);
-
-	if ((nsaddrs > 1 || ndaddrs > 1) &&
-	    (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
-		xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-			   " source or destination IP addresses");
-
-	if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
-			   "specify a unique address");
-
-	generic_opt_check(command, cs.options);
+	do_parse(argc, argv, &p, &cs, &args);
+
+	command		= p.command;
+	chain		= p.chain;
+	*table		= p.table;
+	rulenum		= p.rulenum;
+	policy		= p.policy;
+	newname		= p.newname;
+	verbose		= p.verbose;
+	wait		= args.wait;
+	wait_interval	= args.wait_interval;
+	nsaddrs		= args.s.naddrs;
+	ndaddrs		= args.d.naddrs;
+	saddrs		= args.s.addr.v4;
+	daddrs		= args.d.addr.v4;
+	smasks		= args.s.mask.v4;
+	dmasks		= args.d.mask.v4;
 
 	/* Attempt to acquire the xtables lock */
 	if (!restore)
@@ -1160,26 +759,6 @@ int do_command4(int argc, char *argv[], char **table,
 	    || command == CMD_CHECK
 	    || command == CMD_INSERT
 	    || command == CMD_REPLACE) {
-		if (strcmp(chain, "PREROUTING") == 0
-		    || strcmp(chain, "INPUT") == 0) {
-			/* -o not valid with incoming packets. */
-			if (cs.options & OPT_VIANAMEOUT)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEOUT),
-					   chain);
-		}
-
-		if (strcmp(chain, "POSTROUTING") == 0
-		    || strcmp(chain, "OUTPUT") == 0) {
-			/* -i not valid with outgoing packets */
-			if (cs.options & OPT_VIANAMEIN)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEIN),
-					   chain);
-		}
-
 		if (cs.target && iptc_is_chain(cs.jumpto, *handle)) {
 			fprintf(stderr,
 				"Warning: using chain %s, not extension\n",
@@ -1317,6 +896,9 @@ int do_command4(int argc, char *argv[], char **table,
 	case CMD_SET_POLICY:
 		ret = iptc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw.counters : NULL, *handle);
 		break;
+	case CMD_NONE:
+	/* do_parse ignored the line (eg: -4 with ip6tables-restore) */
+		break;
 	default:
 		/* We should never reach this... */
 		exit_tryhelp(2, line);
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 1993c89541527..1bce6715c3a9a 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1864,8 +1864,11 @@ void ipv4_post_parse(int command, struct iptables_command_state *cs,
 	if (args->goto_set)
 		cs->fw.ip.flags |= IPT_F_GOTO;
 
+	/* nft-variants use cs->counters, legacy uses cs->fw.counters */
 	cs->counters.pcnt = args->pcnt_cnt;
 	cs->counters.bcnt = args->bcnt_cnt;
+	cs->fw.counters.pcnt = args->pcnt_cnt;
+	cs->fw.counters.bcnt = args->bcnt_cnt;
 
 	if (command & (CMD_REPLACE | CMD_INSERT |
 			CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-- 
2.34.1


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

* [iptables PATCH 11/11] ip6tables: Use the shared do_parse, too
  2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
                   ` (9 preceding siblings ...)
  2021-12-24 17:17 ` [iptables PATCH 10/11] iptables: Use xtables' do_parse() function Phil Sutter
@ 2021-12-24 17:17 ` Phil Sutter
  10 siblings, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2021-12-24 17:17 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Same change as with iptables, merely have to set IP6T_F_PROTO flag in
ipv6_proto_parse().

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/ip6tables.c | 499 +++----------------------------------------
 iptables/xshared.c   |   4 +
 2 files changed, 37 insertions(+), 466 deletions(-)

diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index b4604f83cf8a4..fa3e6c1506e71 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -90,21 +90,12 @@ static struct option original_opts[] = {
 struct xtables_globals ip6tables_globals = {
 	.option_offset = 0,
 	.program_version = PACKAGE_VERSION " (legacy)",
+	.optstring = OPTSTRING_COMMON "R:S::W::" "46bg:h::m:nvw::x",
 	.orig_opts = original_opts,
 	.compat_rev = xtables_compatible_revision,
+	.print_help = xtables_printhelp,
 };
 
-#define opts ip6tables_globals.opts
-#define prog_name ip6tables_globals.program_name
-#define prog_vers ip6tables_globals.program_version
-
-static void
-exit_printhelp(const struct xtables_rule_match *matches)
-{
-	xtables_printhelp(matches);
-	exit(0);
-}
-
 /*
  *	All functions starting with "parse" should succeed, otherwise
  *	the program fails.
@@ -114,15 +105,6 @@ exit_printhelp(const struct xtables_rule_match *matches)
  *	return global static data.
 */
 
-/* These are invalid numbers as upper layer protocol */
-static int is_exthdr(uint16_t proto)
-{
-	return (proto == IPPROTO_ROUTING ||
-		proto == IPPROTO_FRAGMENT ||
-		proto == IPPROTO_AH ||
-		proto == IPPROTO_DSTOPTS);
-}
-
 static int
 print_match(const struct xt_entry_match *m,
 	    const struct ip6t_ip6 *ip,
@@ -714,10 +696,21 @@ generate_entry(const struct ip6t_entry *fw,
 int do_command6(int argc, char *argv[], char **table,
 		struct xtc_handle **handle, bool restore)
 {
+	struct xt_cmd_parse p = {
+		.table		= *table,
+		.restore	= restore,
+		.line		= line,
+		.proto_parse	= ipv6_proto_parse,
+		.post_parse	= ipv6_post_parse,
+	};
 	struct iptables_command_state cs = {
 		.jumpto	= "",
 		.argv	= argv,
 	};
+	struct xtables_args args = {
+		.family = AF_INET6,
+		.wait_interval.tv_sec = 1,
+	};
 	struct ip6t_entry *e = NULL;
 	unsigned int nsaddrs = 0, ndaddrs = 0;
 	struct in6_addr *saddrs = NULL, *daddrs = NULL;
@@ -728,437 +721,28 @@ int do_command6(int argc, char *argv[], char **table,
 	struct timeval wait_interval = {
 		.tv_sec	= 1,
 	};
-	bool wait_interval_set = false;
 	const char *chain = NULL;
-	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
 	const char *policy = NULL, *newname = NULL;
 	unsigned int rulenum = 0, command = 0;
-	const char *pcnt = NULL, *bcnt = NULL;
 	int ret = 1;
-	struct xtables_match *m;
-	struct xtables_rule_match *matchp;
-	struct xtables_target *t;
-	unsigned long long cnt;
-	bool table_set = false;
-	uint16_t invflags = 0;
-	bool invert = false;
-
-	/* re-set optind to 0 in case do_command6 gets called
-	 * a second time */
-	optind = 0;
-
-	/* clear mflags in case do_command6 gets called a second time
-	 * (we clear the global list of all matches for security)*/
-	for (m = xtables_matches; m; m = m->next)
-		m->mflags = 0;
-
-	for (t = xtables_targets; t; t = t->next) {
-		t->tflags = 0;
-		t->used = 0;
-	}
-
-	/* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-	opterr = 0;
-
-	opts = xt_params->orig_opts;
-	while ((cs.c = getopt_long(argc, argv,
-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::W::nt:m:xc:g:46",
-					   opts, NULL)) != -1) {
-		switch (cs.c) {
-			/*
-			 * Command selection
-			 */
-		case 'A':
-			add_command(&command, CMD_APPEND, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'C':
-			add_command(&command, CMD_CHECK, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'D':
-			add_command(&command, CMD_DELETE, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv)) {
-				rulenum = parse_rulenumber(argv[optind++]);
-				command = CMD_DELETE_NUM;
-			}
-			break;
-
-		case 'R':
-			add_command(&command, CMD_REPLACE, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a rule number",
-					   cmd2char(CMD_REPLACE));
-			break;
-
-		case 'I':
-			add_command(&command, CMD_INSERT, CMD_NONE, invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			else rulenum = 1;
-			break;
-
-		case 'L':
-			add_command(&command, CMD_LIST,
-				    CMD_ZERO | CMD_ZERO_NUM, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'S':
-			add_command(&command, CMD_LIST_RULES,
-				    CMD_ZERO | CMD_ZERO_NUM, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv))
-				rulenum = parse_rulenumber(argv[optind++]);
-			break;
-
-		case 'F':
-			add_command(&command, CMD_FLUSH, CMD_NONE, invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			break;
-
-		case 'Z':
-			add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
-				    invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			if (xs_has_arg(argc, argv)) {
-				rulenum = parse_rulenumber(argv[optind++]);
-				command = CMD_ZERO_NUM;
-			}
-			break;
-
-		case 'N':
-			parse_chain(optarg);
-			add_command(&command, CMD_NEW_CHAIN, CMD_NONE, invert);
-			chain = optarg;
-			break;
-
-		case 'X':
-			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-				    invert);
-			if (optarg) chain = optarg;
-			else if (xs_has_arg(argc, argv))
-				chain = argv[optind++];
-			break;
-
-		case 'E':
-			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-				    invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				newname = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires old-chain-name and "
-					   "new-chain-name",
-					    cmd2char(CMD_RENAME_CHAIN));
-			break;
-
-		case 'P':
-			add_command(&command, CMD_SET_POLICY, CMD_NONE,
-				    invert);
-			chain = optarg;
-			if (xs_has_arg(argc, argv))
-				policy = argv[optind++];
-			else
-				xtables_error(PARAMETER_PROBLEM,
-					   "-%c requires a chain and a policy",
-					   cmd2char(CMD_SET_POLICY));
-			break;
-
-		case 'h':
-			if (!optarg)
-				optarg = argv[optind];
 
-			/* ip6tables -p icmp -h */
-			if (!cs.matches && cs.protocol)
-				xtables_find_match(cs.protocol, XTF_TRY_LOAD,
-					&cs.matches);
-
-			exit_printhelp(cs.matches);
-
-			/*
-			 * Option selection
-			 */
-		case 'p':
-			set_option(&cs.options, OPT_PROTOCOL, &invflags,
-				   invert);
-
-			/* Canonicalize into lower case */
-			for (cs.protocol = optarg; *cs.protocol; cs.protocol++)
-				*cs.protocol = tolower(*cs.protocol);
-
-			cs.protocol = optarg;
-			cs.fw6.ipv6.proto = xtables_parse_protocol(cs.protocol);
-			cs.fw6.ipv6.flags |= IP6T_F_PROTO;
-
-			if (cs.fw6.ipv6.proto == 0 && (invflags & XT_INV_PROTO))
-				xtables_error(PARAMETER_PROBLEM,
-					   "rule would never match protocol");
-
-			if (is_exthdr(cs.fw6.ipv6.proto)
-			    && (invflags & XT_INV_PROTO) == 0)
-				fprintf(stderr,
-					"Warning: never matched protocol: %s. "
-					"use extension match instead.\n",
-					cs.protocol);
-			break;
-
-		case 's':
-			set_option(&cs.options, OPT_SOURCE, &invflags, invert);
-			shostnetworkmask = optarg;
-			break;
-
-		case 'd':
-			set_option(&cs.options, OPT_DESTINATION, &invflags,
-				   invert);
-			dhostnetworkmask = optarg;
-			break;
-
-#ifdef IP6T_F_GOTO
-		case 'g':
-			set_option(&cs.options, OPT_JUMP, &invflags, invert);
-			cs.fw6.ipv6.flags |= IP6T_F_GOTO;
-			cs.jumpto = xt_parse_target(optarg);
-			break;
-#endif
-
-		case 'j':
-			set_option(&cs.options, OPT_JUMP, &invflags, invert);
-			command_jump(&cs, optarg);
-			break;
-
-
-		case 'i':
-			if (*optarg == '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"Empty interface is likely to be "
-					"undesired");
-			set_option(&cs.options, OPT_VIANAMEIN, &invflags,
-				   invert);
-			xtables_parse_interface(optarg,
-					cs.fw6.ipv6.iniface,
-					cs.fw6.ipv6.iniface_mask);
-			break;
-
-		case 'o':
-			if (*optarg == '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"Empty interface is likely to be "
-					"undesired");
-			set_option(&cs.options, OPT_VIANAMEOUT, &invflags,
-				   invert);
-			xtables_parse_interface(optarg,
-					cs.fw6.ipv6.outiface,
-					cs.fw6.ipv6.outiface_mask);
-			break;
-
-		case 'v':
-			if (!verbose)
-				set_option(&cs.options, OPT_VERBOSE,
-					   &invflags, invert);
-			verbose++;
-			break;
-
-		case 'w':
-			if (restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-w' from "
-					      "ip6tables-restore");
-			}
-			wait = parse_wait_time(argc, argv);
-			break;
-
-		case 'W':
-			if (restore) {
-				xtables_error(PARAMETER_PROBLEM,
-					      "You cannot use `-W' from "
-					      "ip6tables-restore");
-			}
-			parse_wait_interval(argc, argv, &wait_interval);
-			wait_interval_set = true;
-			break;
-
-		case 'm':
-			command_match(&cs, invert);
-			break;
-
-		case 'n':
-			set_option(&cs.options, OPT_NUMERIC, &invflags, invert);
-			break;
-
-		case 't':
-			if (invert)
-				xtables_error(PARAMETER_PROBLEM,
-					   "unexpected ! flag before --table");
-			if (restore && table_set)
-				xtables_error(PARAMETER_PROBLEM,
-					      "The -t option cannot be used in %s.\n",
-					      xt_params->program_name);
-			*table = optarg;
-			table_set = true;
-			break;
-
-		case 'x':
-			set_option(&cs.options, OPT_EXPANDED, &invflags,
-				   invert);
-			break;
-
-		case 'V':
-			if (invert)
-				printf("Not %s ;-)\n", prog_vers);
-			else
-				printf("%s v%s\n",
-				       prog_name, prog_vers);
-			exit(0);
-
-		case '0':
-			set_option(&cs.options, OPT_LINENUMBERS, &invflags,
-				   invert);
-			break;
-
-		case 'M':
-			xtables_modprobe_program = optarg;
-			break;
-
-		case 'c':
-
-			set_option(&cs.options, OPT_COUNTERS, &invflags,
-				   invert);
-			pcnt = optarg;
-			bcnt = strchr(pcnt + 1, ',');
-			if (bcnt)
-			    bcnt++;
-			if (!bcnt && xs_has_arg(argc, argv))
-				bcnt = argv[optind++];
-			if (!bcnt)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c requires packet and byte counter",
-					opt2char(OPT_COUNTERS));
-
-			if (sscanf(pcnt, "%llu", &cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c packet counter not numeric",
-					opt2char(OPT_COUNTERS));
-			cs.fw6.counters.pcnt = cnt;
-
-			if (sscanf(bcnt, "%llu", &cnt) != 1)
-				xtables_error(PARAMETER_PROBLEM,
-					"-%c byte counter not numeric",
-					opt2char(OPT_COUNTERS));
-			cs.fw6.counters.bcnt = cnt;
-			break;
-
-		case '4':
-			/* This is not the IPv4 iptables */
-			if (line != -1)
-				return 1; /* success: line ignored */
-			fprintf(stderr, "This is the IPv6 version of ip6tables.\n");
-			exit_tryhelp(2, line);
-
-		case '6':
-			/* This is indeed the IPv6 ip6tables */
-			break;
-
-		case 1: /* non option */
-			if (optarg[0] == '!' && optarg[1] == '\0') {
-				if (invert)
-					xtables_error(PARAMETER_PROBLEM,
-						   "multiple consecutive ! not"
-						   " allowed");
-				invert = true;
-				optarg[0] = '\0';
-				continue;
-			}
-			fprintf(stderr, "Bad argument `%s'\n", optarg);
-			exit_tryhelp(2, line);
-
-		default:
-			if (command_default(&cs, &ip6tables_globals, invert))
-				/*
-				 * If new options were loaded, we must retry
-				 * getopt immediately and not allow
-				 * invert=false to be executed.
-				 */
-				continue;
-			break;
-		}
-		invert = false;
-	}
-
-	if (!wait && wait_interval_set)
-		xtables_error(PARAMETER_PROBLEM,
-			      "--wait-interval only makes sense with --wait\n");
-
-	if (strcmp(*table, "nat") == 0 &&
-	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
-	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
-		xtables_error(PARAMETER_PROBLEM,
-			"\nThe \"nat\" table is not intended for filtering, "
-		        "the use of DROP is therefore inhibited.\n\n");
-
-	for (matchp = cs.matches; matchp; matchp = matchp->next)
-		xtables_option_mfcall(matchp->match);
-	if (cs.target != NULL)
-		xtables_option_tfcall(cs.target);
-
-	/* Fix me: must put inverse options checking here --MN */
-
-	if (optind < argc)
-		xtables_error(PARAMETER_PROBLEM,
-			   "unknown arguments found on commandline");
-	if (!command)
-		xtables_error(PARAMETER_PROBLEM, "no command specified");
-	if (invert)
-		xtables_error(PARAMETER_PROBLEM,
-			   "nothing appropriate following !");
-
-	cs.fw6.ipv6.invflags = invflags;
-
-	if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
-		if (!(cs.options & OPT_DESTINATION))
-			dhostnetworkmask = "::0/0";
-		if (!(cs.options & OPT_SOURCE))
-			shostnetworkmask = "::0/0";
-	}
-
-	if (shostnetworkmask)
-		xtables_ip6parse_multiple(shostnetworkmask, &saddrs,
-					  &smasks, &nsaddrs);
-
-	if (dhostnetworkmask)
-		xtables_ip6parse_multiple(dhostnetworkmask, &daddrs,
-					  &dmasks, &ndaddrs);
-
-	if ((nsaddrs > 1 || ndaddrs > 1) &&
-	    (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
-		xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-			   " source or destination IP addresses");
-
-	if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
-			   "specify a unique address");
-
-	generic_opt_check(command, cs.options);
+	do_parse(argc, argv, &p, &cs, &args);
+
+	command		= p.command;
+	chain		= p.chain;
+	*table		= p.table;
+	rulenum		= p.rulenum;
+	policy		= p.policy;
+	newname		= p.newname;
+	verbose		= p.verbose;
+	wait		= args.wait;
+	wait_interval	= args.wait_interval;
+	nsaddrs		= args.s.naddrs;
+	ndaddrs		= args.d.naddrs;
+	saddrs		= args.s.addr.v6;
+	daddrs		= args.d.addr.v6;
+	smasks		= args.s.mask.v6;
+	dmasks		= args.d.mask.v6;
 
 	/* Attempt to acquire the xtables lock */
 	if (!restore)
@@ -1182,26 +766,6 @@ int do_command6(int argc, char *argv[], char **table,
 	    || command == CMD_CHECK
 	    || command == CMD_INSERT
 	    || command == CMD_REPLACE) {
-		if (strcmp(chain, "PREROUTING") == 0
-		    || strcmp(chain, "INPUT") == 0) {
-			/* -o not valid with incoming packets. */
-			if (cs.options & OPT_VIANAMEOUT)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEOUT),
-					   chain);
-		}
-
-		if (strcmp(chain, "POSTROUTING") == 0
-		    || strcmp(chain, "OUTPUT") == 0) {
-			/* -i not valid with outgoing packets */
-			if (cs.options & OPT_VIANAMEIN)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Can't use -%c with %s\n",
-					   opt2char(OPT_VIANAMEIN),
-					   chain);
-		}
-
 		if (cs.target && ip6tc_is_chain(cs.jumpto, *handle)) {
 			fprintf(stderr,
 				"Warning: using chain %s, not extension\n",
@@ -1337,6 +901,9 @@ int do_command6(int argc, char *argv[], char **table,
 	case CMD_SET_POLICY:
 		ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw6.counters : NULL, *handle);
 		break;
+	case CMD_NONE:
+	/* do_parse ignored the line (eg: -4 with ip6tables-restore) */
+		break;
 	default:
 		/* We should never reach this... */
 		exit_tryhelp(2, line);
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 1bce6715c3a9a..3b363e72361e0 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1836,6 +1836,10 @@ void ipv6_proto_parse(struct iptables_command_state *cs,
 	cs->fw6.ipv6.proto = args->proto;
 	cs->fw6.ipv6.invflags = args->invflags;
 
+	/* this is needed for ip6tables-legacy only */
+	args->flags |= IP6T_F_PROTO;
+	cs->fw6.ipv6.flags |= IP6T_F_PROTO;
+
 	if (is_exthdr(cs->fw6.ipv6.proto)
 	    && (cs->fw6.ipv6.invflags & XT_INV_PROTO) == 0)
 		fprintf(stderr,
-- 
2.34.1


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

* Re: [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse()
  2021-12-24 17:17 ` [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse() Phil Sutter
@ 2022-01-10 21:29   ` Pablo Neira Ayuso
  2022-01-10 21:35     ` Pablo Neira Ayuso
  2022-01-11 10:34     ` Phil Sutter
  0 siblings, 2 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2022-01-10 21:29 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Fri, Dec 24, 2021 at 06:17:49PM +0100, Phil Sutter wrote:
[...]
> diff --git a/iptables/xshared.h b/iptables/xshared.h
> index dde94b7335f6a..1954168f64058 100644
> --- a/iptables/xshared.h
> +++ b/iptables/xshared.h
[...]
>  struct xt_cmd_parse {
>  	unsigned int			command;
>  	unsigned int			rulenum;
> @@ -272,6 +305,11 @@ struct xt_cmd_parse {
>  	bool				restore;
>  	int				verbose;
>  	bool				xlate;

Probably wrap these two common functions between legacy and nft in a
structure? Something like: struct nft_parse_ops...

> +	void		(*proto_parse)(struct iptables_command_state *cs,
> +				       struct xtables_args *args);
> +	void		(*post_parse)(int command,
> +				      struct iptables_command_state *cs,
> +				      struct xtables_args *args);
>  };
>  
>  #endif /* IPTABLES_XSHARED_H */
> diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
> index 9d312b244657e..b0b27695cbb8c 100644
> --- a/iptables/xtables-translate.c
> +++ b/iptables/xtables-translate.c
> @@ -252,6 +252,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
>  		.table		= *table,
>  		.restore	= restore,
>  		.xlate		= true,
> +		.proto_parse	= h->ops->proto_parse,
> +		.post_parse	= h->ops->post_parse,

so you could just do:

                .parse          = h->ops->parse,

and if you need to extend this structure in the future for whatever
revolutionary reason, you will need to update this part of the code to
do:

                .another_parse  = h->ops->another_parse,

Apart from this, anything else LGTM.

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

* Re: [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse()
  2022-01-10 21:29   ` Pablo Neira Ayuso
@ 2022-01-10 21:35     ` Pablo Neira Ayuso
  2022-01-11 10:34     ` Phil Sutter
  1 sibling, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2022-01-10 21:35 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Mon, Jan 10, 2022 at 10:29:37PM +0100, Pablo Neira Ayuso wrote:
> On Fri, Dec 24, 2021 at 06:17:49PM +0100, Phil Sutter wrote:
> [...]
> > diff --git a/iptables/xshared.h b/iptables/xshared.h
> > index dde94b7335f6a..1954168f64058 100644
> > --- a/iptables/xshared.h
> > +++ b/iptables/xshared.h
> [...]
> >  struct xt_cmd_parse {
> >  	unsigned int			command;
> >  	unsigned int			rulenum;
> > @@ -272,6 +305,11 @@ struct xt_cmd_parse {
> >  	bool				restore;
> >  	int				verbose;
> >  	bool				xlate;
> 
> Probably wrap these two common functions between legacy and nft in a
> structure? Something like: struct nft_parse_ops...

struct xt_parse_ops...

> > +	void		(*proto_parse)(struct iptables_command_state *cs,
> > +				       struct xtables_args *args);
> > +	void		(*post_parse)(int command,
> > +				      struct iptables_command_state *cs,
> > +				      struct xtables_args *args);
> >  };
> >  
> >  #endif /* IPTABLES_XSHARED_H */
> > diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
> > index 9d312b244657e..b0b27695cbb8c 100644
> > --- a/iptables/xtables-translate.c
> > +++ b/iptables/xtables-translate.c
> > @@ -252,6 +252,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
> >  		.table		= *table,
> >  		.restore	= restore,
> >  		.xlate		= true,
> > +		.proto_parse	= h->ops->proto_parse,
> > +		.post_parse	= h->ops->post_parse,
> 
> so you could just do:
> 
>                 .parse          = h->ops->parse,
> 
> and if you need to extend this structure in the future for whatever
> revolutionary reason, you will need to update this part of the code to
                        ^....
                        you will *not* need

> do:
> 
>                 .another_parse  = h->ops->another_parse,
> 
> Apart from this, anything else LGTM.

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

* Re: [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse()
  2022-01-10 21:29   ` Pablo Neira Ayuso
  2022-01-10 21:35     ` Pablo Neira Ayuso
@ 2022-01-11 10:34     ` Phil Sutter
  1 sibling, 0 replies; 15+ messages in thread
From: Phil Sutter @ 2022-01-11 10:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

On Mon, Jan 10, 2022 at 10:29:37PM +0100, Pablo Neira Ayuso wrote:
> On Fri, Dec 24, 2021 at 06:17:49PM +0100, Phil Sutter wrote:
> [...]
> > diff --git a/iptables/xshared.h b/iptables/xshared.h
> > index dde94b7335f6a..1954168f64058 100644
> > --- a/iptables/xshared.h
> > +++ b/iptables/xshared.h
> [...]
> >  struct xt_cmd_parse {
> >  	unsigned int			command;
> >  	unsigned int			rulenum;
> > @@ -272,6 +305,11 @@ struct xt_cmd_parse {
> >  	bool				restore;
> >  	int				verbose;
> >  	bool				xlate;
> 
> Probably wrap these two common functions between legacy and nft in a
> structure? Something like: struct nft_parse_ops...

Ah yes, thanks for suggesting. Wrapping the callbacks didn't come to
mind despite the need for two assignments everywhere.

I'll fix and resubmit.

Cheers, Phil

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

end of thread, other threads:[~2022-01-11 10:34 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-24 17:17 [iptables PATCH 00/11] Share do_parse() between nft and legacy Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 01/11] xtables: Drop xtables' family on demand feature Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 02/11] xtables: Pull table validity check out of do_parse() Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 03/11] xtables: Move struct nft_xt_cmd_parse to xshared.h Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 04/11] xtables: Pass xtables_args to check_empty_interface() Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 05/11] xtables: Pass xtables_args to check_inverse() Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 06/11] xtables: Do not pass nft_handle to do_parse() Phil Sutter
2022-01-10 21:29   ` Pablo Neira Ayuso
2022-01-10 21:35     ` Pablo Neira Ayuso
2022-01-11 10:34     ` Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 07/11] xshared: Move do_parse to shared space Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 08/11] xshared: Store parsed wait and wait_interval in xtables_args Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 09/11] nft: Move proto_parse and post_parse callbacks to xshared Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 10/11] iptables: Use xtables' do_parse() function Phil Sutter
2021-12-24 17:17 ` [iptables PATCH 11/11] ip6tables: Use the shared do_parse, too Phil Sutter

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.