Blame SOURCES/0055-json-tcp-add-raw-tcp-option-match-support.patch

4e0227
From ad566e27398e81ed803c4225179bb8df4718a2e9 Mon Sep 17 00:00:00 2001
4e0227
From: Phil Sutter <psutter@redhat.com>
4e0227
Date: Mon, 12 Jul 2021 17:44:08 +0200
4e0227
Subject: [PATCH] json: tcp: add raw tcp option match support
4e0227
4e0227
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
4e0227
Upstream Status: nftables commit cb21869649208
4e0227
4e0227
commit cb21869649208118ed61354e2674858e4ff6c23c
4e0227
Author: Florian Westphal <fw@strlen.de>
4e0227
Date:   Tue Nov 3 12:04:20 2020 +0100
4e0227
4e0227
    json: tcp: add raw tcp option match support
4e0227
4e0227
    To similar change as in previous one, this time for the
4e0227
    jason (de)serialization.
4e0227
4e0227
    Re-uses the raw payload match syntax, i.e. base,offset,length.
4e0227
4e0227
    Signed-off-by: Florian Westphal <fw@strlen.de>
4e0227
---
4e0227
 src/json.c                 | 22 ++++++++--------
4e0227
 src/parser_json.c          | 52 ++++++++++++++++++++++++++------------
4e0227
 tests/py/any/tcpopt.t.json | 34 +++++++++++++++++++++++++
4e0227
 3 files changed, 82 insertions(+), 26 deletions(-)
4e0227
4e0227
diff --git a/src/json.c b/src/json.c
4e0227
index 1906e7d..b77c6d2 100644
4e0227
--- a/src/json.c
4e0227
+++ b/src/json.c
4e0227
@@ -656,30 +656,32 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
4e0227
 json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
4e0227
 {
4e0227
 	const char *desc = expr->exthdr.desc ?
4e0227
-			   expr->exthdr.desc->name :
4e0227
-			   "unknown-exthdr";
4e0227
+			   expr->exthdr.desc->name : NULL;
4e0227
 	const char *field = expr->exthdr.tmpl->token;
4e0227
 	json_t *root;
4e0227
 	bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT;
4e0227
 
4e0227
 	if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
4e0227
+		static const char *offstrs[] = { "", "1", "2", "3" };
4e0227
 		unsigned int offset = expr->exthdr.offset / 64;
4e0227
+		const char *offstr = "";
4e0227
 
4e0227
-		if (offset) {
4e0227
-			const char *offstrs[] = { "0", "1", "2", "3" };
4e0227
-			const char *offstr = "";
4e0227
-
4e0227
+		if (desc) {
4e0227
 			if (offset < 4)
4e0227
 				offstr = offstrs[offset];
4e0227
 
4e0227
 			root = json_pack("{s:s+}", "name", desc, offstr);
4e0227
+
4e0227
+			if (!is_exists)
4e0227
+				json_object_set_new(root, "field", json_string(field));
4e0227
 		} else {
4e0227
-			root = json_pack("{s:s}", "name", desc);
4e0227
+			root = json_pack("{s:i, s:i, s:i}",
4e0227
+					 "base", expr->exthdr.raw_type,
4e0227
+					 "offset", expr->exthdr.offset,
4e0227
+					 "len", expr->len);
4e0227
+			is_exists = false;
4e0227
 		}
4e0227
 
4e0227
-		if (!is_exists)
4e0227
-			json_object_set_new(root, "field", json_string(field));
4e0227
-
4e0227
 		return json_pack("{s:o}", "tcp option", root);
4e0227
 	}
4e0227
 	if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
4e0227
diff --git a/src/parser_json.c b/src/parser_json.c
4e0227
index ab2375f..fbf7db5 100644
4e0227
--- a/src/parser_json.c
4e0227
+++ b/src/parser_json.c
4e0227
@@ -500,6 +500,8 @@ static int json_parse_tcp_option_field(int type, const char *name, int *val)
4e0227
 		return 1;
4e0227
 
4e0227
 	desc = tcpopt_protocols[type];
4e0227
+	if (!desc)
4e0227
+		return 1;
4e0227
 
4e0227
 	for (i = 0; i < array_size(desc->templates); i++) {
4e0227
 		if (desc->templates[i].token &&
4e0227
@@ -599,30 +601,48 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx,
4e0227
 static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
4e0227
 					       const char *type, json_t *root)
4e0227
 {
4e0227
+	int fieldval, kind, offset, len;
4e0227
 	const char *desc, *field;
4e0227
-	int descval, fieldval;
4e0227
 	struct expr *expr;
4e0227
 
4e0227
-	if (json_unpack_err(ctx, root, "{s:s}", "name", &desc))
4e0227
-		return NULL;
4e0227
-
4e0227
-	if (json_parse_tcp_option_type(desc, &descval)) {
4e0227
-		json_error(ctx, "Unknown tcp option name '%s'.", desc);
4e0227
-		return NULL;
4e0227
-	}
4e0227
+	if (!json_unpack(root, "{s:i, s:i, s:i}",
4e0227
+			"base", &kind, "offset", &offset, "len", &len)) {
4e0227
+		uint32_t flag = 0;
4e0227
 
4e0227
-	if (json_unpack(root, "{s:s}", "field", &field)) {
4e0227
-		expr = tcpopt_expr_alloc(int_loc, descval,
4e0227
+		expr = tcpopt_expr_alloc(int_loc, kind,
4e0227
 					 TCPOPT_COMMON_KIND);
4e0227
-		expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
4e0227
 
4e0227
+		if (kind < 0 || kind > 255)
4e0227
+			return NULL;
4e0227
+
4e0227
+		if (offset == TCPOPT_COMMON_KIND && len == 8)
4e0227
+			flag = NFT_EXTHDR_F_PRESENT;
4e0227
+
4e0227
+		tcpopt_init_raw(expr, kind, offset, len, flag);
4e0227
 		return expr;
4e0227
+	} else if (!json_unpack(root, "{s:s}", "name", &desc)) {
4e0227
+		if (json_parse_tcp_option_type(desc, &kind)) {
4e0227
+			json_error(ctx, "Unknown tcp option name '%s'.", desc);
4e0227
+			return NULL;
4e0227
+		}
4e0227
+
4e0227
+		if (json_unpack(root, "{s:s}", "field", &field)) {
4e0227
+			expr = tcpopt_expr_alloc(int_loc, kind,
4e0227
+						 TCPOPT_COMMON_KIND);
4e0227
+			expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
4e0227
+			return expr;
4e0227
+		}
4e0227
+
4e0227
+		if (json_parse_tcp_option_field(kind, field, &fieldval)) {
4e0227
+			json_error(ctx, "Unknown tcp option field '%s'.", field);
4e0227
+			return NULL;
4e0227
+		}
4e0227
+
4e0227
+		return tcpopt_expr_alloc(int_loc, kind, fieldval);
4e0227
 	}
4e0227
-	if (json_parse_tcp_option_field(descval, field, &fieldval)) {
4e0227
-		json_error(ctx, "Unknown tcp option field '%s'.", field);
4e0227
-		return NULL;
4e0227
-	}
4e0227
-	return tcpopt_expr_alloc(int_loc, descval, fieldval);
4e0227
+
4e0227
+	json_error(ctx, "Invalid tcp option expression properties.");
4e0227
+	return NULL;
4e0227
 }
4e0227
 
4e0227
 static int json_parse_ip_option_type(const char *name, int *val)
4e0227
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
4e0227
index b15e36e..139e97d 100644
4e0227
--- a/tests/py/any/tcpopt.t.json
4e0227
+++ b/tests/py/any/tcpopt.t.json
4e0227
@@ -414,6 +414,40 @@
4e0227
     }
4e0227
 ]
4e0227
 
4e0227
+# tcp option 255 missing
4e0227
+[
4e0227
+    {
4e0227
+        "match": {
4e0227
+            "left": {
4e0227
+                "tcp option": {
4e0227
+                    "base": 255,
4e0227
+                    "len": 8,
4e0227
+                    "offset": 0
4e0227
+                }
4e0227
+            },
4e0227
+            "op": "==",
4e0227
+            "right": false
4e0227
+        }
4e0227
+    }
4e0227
+]
4e0227
+
4e0227
+# tcp option @255,8,8 255
4e0227
+[
4e0227
+    {
4e0227
+        "match": {
4e0227
+            "left": {
4e0227
+                "tcp option": {
4e0227
+                    "base": 255,
4e0227
+                    "len": 8,
4e0227
+                    "offset": 8
4e0227
+                }
4e0227
+            },
4e0227
+            "op": "==",
4e0227
+            "right": 255
4e0227
+        }
4e0227
+    }
4e0227
+]
4e0227
+
4e0227
 # tcp option window exists
4e0227
 [
4e0227
     {
4e0227
-- 
4e0227
2.31.1
4e0227