* Wed Aug 14 2024 Phil Sutter <psutter@redhat.com> [1.0.4-5.el8] - xt: Fix fallback printing for extensions matching keywords (Phil Sutter) [RHEL-5806] - xt: Fall back to generic printing from translation (Phil Sutter) [RHEL-5806] - xt: Rewrite unsupported compat expression dumping (Phil Sutter) [RHEL-5806] - xt: Purify enum nft_xt_type (Phil Sutter) [RHEL-5806] - xt: Delay libxtables access until translation (Phil Sutter) [RHEL-5806] - Warn for tables with compat expressions in rules (Phil Sutter) [RHEL-5806] Resolves: RHEL-5806
		
			
				
	
	
		
			284 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 5b2f626cb8770f485c20ae4f815763deac89a632 Mon Sep 17 00:00:00 2001
 | 
						|
From: Phil Sutter <psutter@redhat.com>
 | 
						|
Date: Wed, 14 Aug 2024 16:20:37 +0200
 | 
						|
Subject: [PATCH] xt: Rewrite unsupported compat expression dumping
 | 
						|
 | 
						|
JIRA: https://issues.redhat.com/browse/RHEL-5806
 | 
						|
Upstream Status: nftables commit 79195a8cc9e9d9cf2d17165bf07ac4cc9d55539f
 | 
						|
Conflicts:
 | 
						|
* One chunk manually applied, upstream moved stmt_print_json() in commit
 | 
						|
  e66f3187d891a ("json: add table map statement support").
 | 
						|
 | 
						|
commit 79195a8cc9e9d9cf2d17165bf07ac4cc9d55539f
 | 
						|
Author: Phil Sutter <phil@nwl.cc>
 | 
						|
Date:   Thu Nov 24 14:17:17 2022 +0100
 | 
						|
 | 
						|
    xt: Rewrite unsupported compat expression dumping
 | 
						|
 | 
						|
    Choose a format which provides more information and is easily parseable.
 | 
						|
    Then teach parsers about it and make it explicitly reject the ruleset
 | 
						|
    giving a meaningful explanation. Also update the man pages with some
 | 
						|
    more details.
 | 
						|
 | 
						|
    Signed-off-by: Phil Sutter <phil@nwl.cc>
 | 
						|
 | 
						|
Signed-off-by: Phil Sutter <psutter@redhat.com>
 | 
						|
---
 | 
						|
 doc/libnftables-json.adoc | 18 +++++++++++++++---
 | 
						|
 doc/statements.txt        | 17 +++++++++++++++++
 | 
						|
 include/json.h            |  2 ++
 | 
						|
 include/parser.h          |  1 +
 | 
						|
 src/json.c                | 19 +++++++++++++------
 | 
						|
 src/parser_bison.y        | 18 ++++++++++++++++++
 | 
						|
 src/parser_json.c         |  5 +++++
 | 
						|
 src/scanner.l             |  3 +++
 | 
						|
 src/statement.c           |  1 +
 | 
						|
 src/xt.c                  |  8 +++++++-
 | 
						|
 10 files changed, 82 insertions(+), 10 deletions(-)
 | 
						|
 | 
						|
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
 | 
						|
index 9cc17ff..284ffab 100644
 | 
						|
--- a/doc/libnftables-json.adoc
 | 
						|
+++ b/doc/libnftables-json.adoc
 | 
						|
@@ -1059,10 +1059,22 @@ Assign connection tracking expectation.
 | 
						|
 
 | 
						|
 === XT
 | 
						|
 [verse]
 | 
						|
-*{ "xt": null }*
 | 
						|
+____
 | 
						|
+*{ "xt": {
 | 
						|
+	"type":* 'TYPENAME'*,
 | 
						|
+	"name":* 'STRING'
 | 
						|
+*}}*
 | 
						|
+
 | 
						|
+'TYPENAME' := *match* | *target* | *watcher*
 | 
						|
+____
 | 
						|
+
 | 
						|
+This represents an xt statement from xtables compat interface. It is a
 | 
						|
+fallback if translation is not available or not complete.
 | 
						|
+
 | 
						|
+Seeing this means the ruleset (or parts of it) were created by *iptables-nft*
 | 
						|
+and one should use that to manage it.
 | 
						|
 
 | 
						|
-This represents an xt statement from xtables compat interface. Sadly, at this
 | 
						|
-point, it is not possible to provide any further information about its content.
 | 
						|
+*BEWARE:* nftables won't restore these statements.
 | 
						|
 
 | 
						|
 == EXPRESSIONS
 | 
						|
 Expressions are the building blocks of (most) statements. In their most basic
 | 
						|
diff --git a/doc/statements.txt b/doc/statements.txt
 | 
						|
index 6aaf806..a00bd5d 100644
 | 
						|
--- a/doc/statements.txt
 | 
						|
+++ b/doc/statements.txt
 | 
						|
@@ -778,3 +778,20 @@ ____
 | 
						|
 # jump to different chains depending on layer 4 protocol type:
 | 
						|
 nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }
 | 
						|
 ------------------------
 | 
						|
+
 | 
						|
+XT STATEMENT
 | 
						|
+~~~~~~~~~~~~
 | 
						|
+This represents an xt statement from xtables compat interface. It is a
 | 
						|
+fallback if translation is not available or not complete.
 | 
						|
+
 | 
						|
+[verse]
 | 
						|
+____
 | 
						|
+*xt* 'TYPE' 'NAME'
 | 
						|
+
 | 
						|
+'TYPE' := *match* | *target* | *watcher*
 | 
						|
+____
 | 
						|
+
 | 
						|
+Seeing this means the ruleset (or parts of it) were created by *iptables-nft*
 | 
						|
+and one should use that to manage it.
 | 
						|
+
 | 
						|
+*BEWARE:* nftables won't restore these statements.
 | 
						|
diff --git a/include/json.h b/include/json.h
 | 
						|
index b0d78eb..f691678 100644
 | 
						|
--- a/include/json.h
 | 
						|
+++ b/include/json.h
 | 
						|
@@ -92,6 +92,7 @@ json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
 | 
						|
 json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
 | 
						|
 json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
 | 
						|
 json_t *optstrip_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
 | 
						|
+json_t *xt_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
 | 
						|
 
 | 
						|
 int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd);
 | 
						|
 
 | 
						|
@@ -194,6 +195,7 @@ STMT_PRINT_STUB(connlimit)
 | 
						|
 STMT_PRINT_STUB(tproxy)
 | 
						|
 STMT_PRINT_STUB(synproxy)
 | 
						|
 STMT_PRINT_STUB(optstrip)
 | 
						|
+STMT_PRINT_STUB(xt)
 | 
						|
 
 | 
						|
 #undef STMT_PRINT_STUB
 | 
						|
 #undef EXPR_PRINT_STUB
 | 
						|
diff --git a/include/parser.h b/include/parser.h
 | 
						|
index 5e5ad28..bd61b8f 100644
 | 
						|
--- a/include/parser.h
 | 
						|
+++ b/include/parser.h
 | 
						|
@@ -50,6 +50,7 @@ enum startcond_type {
 | 
						|
 	PARSER_SC_TCP,
 | 
						|
 	PARSER_SC_TYPE,
 | 
						|
 	PARSER_SC_VLAN,
 | 
						|
+	PARSER_SC_XT,
 | 
						|
 	PARSER_SC_CMD_EXPORT,
 | 
						|
 	PARSER_SC_CMD_IMPORT,
 | 
						|
 	PARSER_SC_CMD_LIST,
 | 
						|
diff --git a/src/json.c b/src/json.c
 | 
						|
index a525fd1..622fe08 100644
 | 
						|
--- a/src/json.c
 | 
						|
+++ b/src/json.c
 | 
						|
@@ -173,12 +173,6 @@ static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx)
 | 
						|
 	char buf[1024];
 | 
						|
 	FILE *fp;
 | 
						|
 
 | 
						|
-	/* XXX: Can't be supported at this point:
 | 
						|
-	 * xt_stmt_xlate() ignores output_fp.
 | 
						|
-	 */
 | 
						|
-	if (stmt->ops->type == STMT_XT)
 | 
						|
-		return json_pack("{s:n}", "xt");
 | 
						|
-
 | 
						|
 	if (stmt->ops->json)
 | 
						|
 		return stmt->ops->json(stmt, octx);
 | 
						|
 
 | 
						|
@@ -1584,6 +1578,19 @@ json_t *optstrip_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
 | 
						|
 			 expr_print_json(stmt->optstrip.expr, octx));
 | 
						|
 }
 | 
						|
 
 | 
						|
+json_t *xt_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
 | 
						|
+{
 | 
						|
+	static const char *xt_typename[NFT_XT_MAX] = {
 | 
						|
+		[NFT_XT_MATCH]          = "match",
 | 
						|
+		[NFT_XT_TARGET]         = "target",
 | 
						|
+		[NFT_XT_WATCHER]        = "watcher",
 | 
						|
+	};
 | 
						|
+
 | 
						|
+	return json_pack("{s:{s:s, s:s}}", "xt",
 | 
						|
+			 "type", xt_typename[stmt->xt.type],
 | 
						|
+			 "name", stmt->xt.name);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static json_t *table_print_json_full(struct netlink_ctx *ctx,
 | 
						|
 				     struct table *table)
 | 
						|
 {
 | 
						|
diff --git a/src/parser_bison.y b/src/parser_bison.y
 | 
						|
index b882f3b..a9d16f8 100644
 | 
						|
--- a/src/parser_bison.y
 | 
						|
+++ b/src/parser_bison.y
 | 
						|
@@ -615,6 +615,8 @@ int nft_lex(void *, void *, void *);
 | 
						|
 %token IN			"in"
 | 
						|
 %token OUT			"out"
 | 
						|
 
 | 
						|
+%token XT		"xt"
 | 
						|
+
 | 
						|
 %type <limit_rate>		limit_rate_pkts
 | 
						|
 %type <limit_rate>		limit_rate_bytes
 | 
						|
 
 | 
						|
@@ -889,6 +891,9 @@ int nft_lex(void *, void *, void *);
 | 
						|
 %type <stmt>			optstrip_stmt
 | 
						|
 %destructor { stmt_free($$); }	optstrip_stmt
 | 
						|
 
 | 
						|
+%type <stmt>			xt_stmt
 | 
						|
+%destructor { stmt_free($$); }	xt_stmt
 | 
						|
+
 | 
						|
 %type <expr>			boolean_expr
 | 
						|
 %destructor { expr_free($$); }	boolean_expr
 | 
						|
 %type <val8>			boolean_keys
 | 
						|
@@ -981,6 +986,7 @@ close_scope_udplite	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_UDPL
 | 
						|
 
 | 
						|
 close_scope_log		: { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_LOG); }
 | 
						|
 close_scope_synproxy	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_SYNPROXY); }
 | 
						|
+close_scope_xt		: { scanner_pop_start_cond(nft->scanner, PARSER_SC_XT); }
 | 
						|
 
 | 
						|
 common_block		:	INCLUDE		QUOTED_STRING	stmt_separator
 | 
						|
 			{
 | 
						|
@@ -2861,6 +2867,18 @@ stmt			:	verdict_stmt
 | 
						|
 			|	synproxy_stmt	close_scope_synproxy
 | 
						|
 			|	chain_stmt
 | 
						|
 			|	optstrip_stmt
 | 
						|
+			|	xt_stmt		close_scope_xt
 | 
						|
+			;
 | 
						|
+
 | 
						|
+xt_stmt			:	XT	STRING	STRING
 | 
						|
+			{
 | 
						|
+				$$ = NULL;
 | 
						|
+				xfree($2);
 | 
						|
+				xfree($3);
 | 
						|
+				erec_queue(error(&@$, "unsupported xtables compat expression, use iptables-nft with this ruleset"),
 | 
						|
+					   state->msgs);
 | 
						|
+				YYERROR;
 | 
						|
+			}
 | 
						|
 			;
 | 
						|
 
 | 
						|
 chain_stmt_type		:	JUMP	{ $$ = NFT_JUMP; }
 | 
						|
diff --git a/src/parser_json.c b/src/parser_json.c
 | 
						|
index fb40100..1699a44 100644
 | 
						|
--- a/src/parser_json.c
 | 
						|
+++ b/src/parser_json.c
 | 
						|
@@ -2716,6 +2716,11 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root)
 | 
						|
 		return verdict_stmt_alloc(int_loc, expr);
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	if (!strcmp(type, "xt")) {
 | 
						|
+		json_error(ctx, "unsupported xtables compat expression, use iptables-nft with this ruleset");
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	for (i = 0; i < array_size(stmt_parser_tbl); i++) {
 | 
						|
 		if (!strcmp(type, stmt_parser_tbl[i].key))
 | 
						|
 			return stmt_parser_tbl[i].cb(ctx, stmt_parser_tbl[i].key, tmp);
 | 
						|
diff --git a/src/scanner.l b/src/scanner.l
 | 
						|
index ed7256b..64d21df 100644
 | 
						|
--- a/src/scanner.l
 | 
						|
+++ b/src/scanner.l
 | 
						|
@@ -215,6 +215,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 | 
						|
 %s SCANSTATE_TCP
 | 
						|
 %s SCANSTATE_TYPE
 | 
						|
 %s SCANSTATE_VLAN
 | 
						|
+%s SCANSTATE_XT
 | 
						|
 %s SCANSTATE_CMD_EXPORT
 | 
						|
 %s SCANSTATE_CMD_IMPORT
 | 
						|
 %s SCANSTATE_CMD_LIST
 | 
						|
@@ -803,6 +804,8 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 | 
						|
 
 | 
						|
 "secmark"		{ scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; }
 | 
						|
 
 | 
						|
+"xt"			{ scanner_push_start_cond(yyscanner, SCANSTATE_XT); return XT; }
 | 
						|
+
 | 
						|
 {addrstring}		{
 | 
						|
 				yylval->string = xstrdup(yytext);
 | 
						|
 				return STRING;
 | 
						|
diff --git a/src/statement.c b/src/statement.c
 | 
						|
index 30caf9c..0448c85 100644
 | 
						|
--- a/src/statement.c
 | 
						|
+++ b/src/statement.c
 | 
						|
@@ -997,6 +997,7 @@ static const struct stmt_ops xt_stmt_ops = {
 | 
						|
 	.name		= "xt",
 | 
						|
 	.print		= xt_stmt_print,
 | 
						|
 	.destroy	= xt_stmt_destroy,
 | 
						|
+	.json		= xt_stmt_json,
 | 
						|
 };
 | 
						|
 
 | 
						|
 struct stmt *xt_stmt_alloc(const struct location *loc)
 | 
						|
diff --git a/src/xt.c b/src/xt.c
 | 
						|
index 300416a..12b52aa 100644
 | 
						|
--- a/src/xt.c
 | 
						|
+++ b/src/xt.c
 | 
						|
@@ -115,7 +115,13 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx)
 | 
						|
 	xt_xlate_free(xl);
 | 
						|
 	xfree(entry);
 | 
						|
 #else
 | 
						|
-	nft_print(octx, "# xt_%s", stmt->xt.name);
 | 
						|
+	static const char *typename[NFT_XT_MAX] = {
 | 
						|
+		[NFT_XT_MATCH]		= "match",
 | 
						|
+		[NFT_XT_TARGET]		= "target",
 | 
						|
+		[NFT_XT_WATCHER]	= "watcher",
 | 
						|
+	};
 | 
						|
+
 | 
						|
+	nft_print(octx, "xt %s %s", typename[stmt->xt.type], stmt->xt.name);
 | 
						|
 #endif
 | 
						|
 }
 | 
						|
 
 | 
						|
-- 
 | 
						|
2.45.0
 | 
						|
 |