netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH nft 7/7] json: tcp: add raw tcp option match support
Date: Thu,  5 Nov 2020 15:11:44 +0100	[thread overview]
Message-ID: <20201105141144.31430-8-fw@strlen.de> (raw)
In-Reply-To: <20201105141144.31430-1-fw@strlen.de>

To similar change as in previous one, this time for the
jason (de)serialization.

Re-uses the raw payload match syntax, i.e. base,offset,length.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/json.c                 | 22 ++++++++--------
 src/parser_json.c          | 52 ++++++++++++++++++++++++++------------
 tests/py/any/tcpopt.t.json | 34 +++++++++++++++++++++++++
 3 files changed, 82 insertions(+), 26 deletions(-)

diff --git a/src/json.c b/src/json.c
index 3c4654d6dada..ac3b1c833d86 100644
--- a/src/json.c
+++ b/src/json.c
@@ -665,30 +665,32 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
 json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
 {
 	const char *desc = expr->exthdr.desc ?
-			   expr->exthdr.desc->name :
-			   "unknown-exthdr";
+			   expr->exthdr.desc->name : NULL;
 	const char *field = expr->exthdr.tmpl->token;
 	json_t *root;
 	bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT;
 
 	if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
+		static const char *offstrs[] = { "", "1", "2", "3" };
 		unsigned int offset = expr->exthdr.offset / 64;
+		const char *offstr = "";
 
-		if (offset) {
-			const char *offstrs[] = { "0", "1", "2", "3" };
-			const char *offstr = "";
-
+		if (desc) {
 			if (offset < 4)
 				offstr = offstrs[offset];
 
 			root = json_pack("{s:s+}", "name", desc, offstr);
+
+			if (!is_exists)
+				json_object_set_new(root, "field", json_string(field));
 		} else {
-			root = json_pack("{s:s}", "name", desc);
+			root = json_pack("{s:i, s:i, s:i}",
+					 "base", expr->exthdr.raw_type,
+					 "offset", expr->exthdr.offset,
+					 "len", expr->len);
+			is_exists = false;
 		}
 
-		if (!is_exists)
-			json_object_set_new(root, "field", json_string(field));
-
 		return json_pack("{s:o}", "tcp option", root);
 	}
 	if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
diff --git a/src/parser_json.c b/src/parser_json.c
index 6e1333659f81..b1de56a4a0d2 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -502,6 +502,8 @@ static int json_parse_tcp_option_field(int type, const char *name, int *val)
 		return 1;
 
 	desc = tcpopt_protocols[type];
+	if (!desc)
+		return 1;
 
 	for (i = 0; i < array_size(desc->templates); i++) {
 		if (desc->templates[i].token &&
@@ -601,30 +603,48 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx,
 static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
 					       const char *type, json_t *root)
 {
+	int fieldval, kind, offset, len;
 	const char *desc, *field;
-	int descval, fieldval;
 	struct expr *expr;
 
-	if (json_unpack_err(ctx, root, "{s:s}", "name", &desc))
-		return NULL;
-
-	if (json_parse_tcp_option_type(desc, &descval)) {
-		json_error(ctx, "Unknown tcp option name '%s'.", desc);
-		return NULL;
-	}
+	if (!json_unpack(root, "{s:i, s:i, s:i}",
+			"base", &kind, "offset", &offset, "len", &len)) {
+		uint32_t flag = 0;
 
-	if (json_unpack(root, "{s:s}", "field", &field)) {
-		expr = tcpopt_expr_alloc(int_loc, descval,
+		expr = tcpopt_expr_alloc(int_loc, kind,
 					 TCPOPT_COMMON_KIND);
-		expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
 
+		if (kind < 0 || kind > 255)
+			return NULL;
+
+		if (offset == TCPOPT_COMMON_KIND && len == 8)
+			flag = NFT_EXTHDR_F_PRESENT;
+
+		tcpopt_init_raw(expr, kind, offset, len, flag);
 		return expr;
+	} else if (!json_unpack(root, "{s:s}", "name", &desc)) {
+		if (json_parse_tcp_option_type(desc, &kind)) {
+			json_error(ctx, "Unknown tcp option name '%s'.", desc);
+			return NULL;
+		}
+
+		if (json_unpack(root, "{s:s}", "field", &field)) {
+			expr = tcpopt_expr_alloc(int_loc, kind,
+						 TCPOPT_COMMON_KIND);
+			expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+			return expr;
+		}
+
+		if (json_parse_tcp_option_field(kind, field, &fieldval)) {
+			json_error(ctx, "Unknown tcp option field '%s'.", field);
+			return NULL;
+		}
+
+		return tcpopt_expr_alloc(int_loc, kind, fieldval);
 	}
-	if (json_parse_tcp_option_field(descval, field, &fieldval)) {
-		json_error(ctx, "Unknown tcp option field '%s'.", field);
-		return NULL;
-	}
-	return tcpopt_expr_alloc(int_loc, descval, fieldval);
+
+	json_error(ctx, "Invalid tcp option expression properties.");
+	return NULL;
 }
 
 static int json_parse_ip_option_type(const char *name, int *val)
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
index b15e36ee7f4c..139e97d8f043 100644
--- a/tests/py/any/tcpopt.t.json
+++ b/tests/py/any/tcpopt.t.json
@@ -414,6 +414,40 @@
     }
 ]
 
+# tcp option 255 missing
+[
+    {
+        "match": {
+            "left": {
+                "tcp option": {
+                    "base": 255,
+                    "len": 8,
+                    "offset": 0
+                }
+            },
+            "op": "==",
+            "right": false
+        }
+    }
+]
+
+# tcp option @255,8,8 255
+[
+    {
+        "match": {
+            "left": {
+                "tcp option": {
+                    "base": 255,
+                    "len": 8,
+                    "offset": 8
+                }
+            },
+            "op": "==",
+            "right": 255
+        }
+    }
+]
+
 # tcp option window exists
 [
     {
-- 
2.26.2


      parent reply	other threads:[~2020-11-05 14:12 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-05 14:11 [PATCH nft 0/7] rework tcp option handling Florian Westphal
2020-11-05 14:11 ` [PATCH nft 1/7] parser: merge sack-perm/sack-permitted and maxseg/mss Florian Westphal
2020-11-05 15:22   ` Jeremy Sowden
2020-11-05 15:45     ` Florian Westphal
2020-11-05 14:11 ` [PATCH nft 2/7] tcpopts: clean up parser -> tcpopt.c plumbing Florian Westphal
2020-11-05 14:11 ` [PATCH nft 3/7] tcpopt: rename noop to nop Florian Westphal
2020-11-05 14:11 ` [PATCH nft 4/7] tcpopt: split tcpopt_hdr_fields into per-option enum Florian Westphal
2020-11-05 14:11 ` [PATCH nft 5/7] tcpopt: allow to check for presence of any tcp option Florian Westphal
2020-11-05 19:11   ` Jeremy Sowden
2020-11-05 20:57     ` Jeremy Sowden
2020-11-09 11:10       ` Florian Westphal
2020-11-09 11:38         ` Jeremy Sowden
2020-11-05 14:11 ` [PATCH nft 6/7] tcp: add raw tcp option match support Florian Westphal
2020-11-05 14:11 ` Florian Westphal [this message]

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20201105141144.31430-8-fw@strlen.de \
    --to=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).