From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Florian Westphal <fw@strlen.de>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [PATCH nft] src: allow to map key to nfqueue number
Date: Thu, 7 Nov 2024 00:34:39 +0100 [thread overview]
Message-ID: <Zyv9D385olTWUv1k@calendula> (raw)
In-Reply-To: <Zyv3tBgF9jW5D0v-@calendula>
[-- Attachment #1: Type: text/plain, Size: 381 bytes --]
On Thu, Nov 07, 2024 at 12:11:53AM +0100, Pablo Neira Ayuso wrote:
> On Wed, Nov 06, 2024 at 05:03:55PM +0100, Pablo Neira Ayuso wrote:
> > I can take a look later today based on your patch, I think I can reuse
> > 90% of it, it is just a subtle detail what I am referring to.
>
> See attachment, not better than your proposal, just a different focus.
Actually, this attachment.
[-- Attachment #2: 0001-src-allow-to-map-key-to-nfqueue-number.patch --]
[-- Type: text/x-diff, Size: 7367 bytes --]
From bf41080edeb3a35e02991ca3ba020a9c79925e12 Mon Sep 17 00:00:00 2001
From: Florian Westphal <fw@strlen.de>
Date: Fri, 25 Oct 2024 09:47:25 +0200
Subject: [PATCH] src: allow to map key to nfqueue number
Allow to specify a numeric queue id as part of a map.
The parser side is easy, but the reverse direction (listing) is not.
'queue' is a statement, it doesn't have an expression.
Add a generic 'queue_type' datatype as a shim to the real basetype with
constant expressions, this is used only for udata build/parse, it stores
the "key" (the parser token, here "queue") as udata in kernel and can
then restore the original key.
Add a dumpfile to validate parser & output.
JSON support is missing because JSON allow typeof only since quite
recently.
Joint work with Pablo.
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1455
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/datatype.h | 4 +-
src/datatype.c | 18 +++++
src/expression.c | 80 +++++++++++++++++++
src/json. | 0
src/netlink.c | 6 +-
src/parser_bison.y | 4 +
tests/shell/testcases/nft-f/dumps/nfqueue.nft | 11 +++
tests/shell/testcases/nft-f/nfqueue | 6 ++
8 files changed, 127 insertions(+), 2 deletions(-)
create mode 100644 src/json.
create mode 100644 tests/shell/testcases/nft-f/dumps/nfqueue.nft
create mode 100755 tests/shell/testcases/nft-f/nfqueue
diff --git a/include/datatype.h b/include/datatype.h
index 75d6d6b8c628..8b950f9165a5 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -140,7 +140,8 @@ struct parse_ctx;
struct datatype {
uint32_t type;
enum byteorder byteorder:8;
- uint32_t alloc:1;
+ uint32_t alloc:1,
+ is_typeof:1;
unsigned int size;
unsigned int subtypes;
const char *name;
@@ -271,6 +272,7 @@ extern const struct datatype boolean_type;
extern const struct datatype priority_type;
extern const struct datatype policy_type;
extern const struct datatype cgroupv2_type;
+extern const struct datatype queue_type;
/* private datatypes for reject statement. */
extern const struct datatype reject_icmp_code_type;
diff --git a/src/datatype.c b/src/datatype.c
index ea73eaf9a691..0c13bbd4270e 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -505,6 +505,24 @@ const struct datatype xinteger_type = {
.parse = integer_type_parse,
};
+static void queue_type_print(const struct expr *expr, struct output_ctx *octx)
+{
+ nft_gmp_print(octx, "queue");
+}
+
+/* Dummy queue_type for set declaration with typeof, see
+ * constant_expr_build_udata and constant_expr_parse_udata,
+ * basetype is used for elements.
+*/
+const struct datatype queue_type = {
+ .type = TYPE_INTEGER,
+ .is_typeof = 1,
+ .name = "queue",
+ .desc = "queue",
+ .basetype = &integer_type,
+ .print = queue_type_print,
+};
+
static void string_type_print(const struct expr *expr, struct output_ctx *octx)
{
unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
diff --git a/src/expression.c b/src/expression.c
index c0cb7f22eb73..62786f483eed 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -371,6 +371,84 @@ struct expr *variable_expr_alloc(const struct location *loc,
return expr;
}
+#define NFTNL_UDATA_CONSTANT_TYPE 0
+#define NFTNL_UDATA_CONSTANT_MAX NFTNL_UDATA_CONSTANT_TYPE
+
+#define CONSTANT_EXPR_NFQUEUE_ID 0
+
+static int constant_expr_build_udata(struct nftnl_udata_buf *udbuf,
+ const struct expr *expr)
+{
+ uint32_t type;
+
+ if (expr->dtype == &queue_type)
+ type = CONSTANT_EXPR_NFQUEUE_ID;
+ else
+ return -1;
+
+ if (!nftnl_udata_put_u32(udbuf, NFTNL_UDATA_CONSTANT_TYPE, type))
+ return -1;
+
+ return 0;
+}
+
+static int constant_parse_udata(const struct nftnl_udata *attr, void *data)
+{
+ const struct nftnl_udata **ud = data;
+ uint8_t type = nftnl_udata_type(attr);
+ uint8_t len = nftnl_udata_len(attr);
+ uint32_t value;
+
+ switch (type) {
+ case NFTNL_UDATA_CONSTANT_TYPE:
+ if (len != sizeof(uint32_t))
+ return -1;
+
+ value = nftnl_udata_get_u32(attr);
+ switch (value) {
+ case CONSTANT_EXPR_NFQUEUE_ID:
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ ud[type] = attr;
+
+ return 0;
+}
+
+static struct expr *constant_expr_parse_udata(const struct nftnl_udata *attr)
+{
+ const struct nftnl_udata *ud[NFTNL_UDATA_CONSTANT_MAX + 1] = {};
+ const struct datatype *dtype = NULL;
+ uint32_t type;
+ int err;
+
+ err = nftnl_udata_parse(nftnl_udata_get(attr), nftnl_udata_len(attr),
+ constant_parse_udata, ud);
+ if (err < 0)
+ return NULL;
+
+ if (!ud[NFTNL_UDATA_CONSTANT_TYPE])
+ return NULL;
+
+ type = nftnl_udata_get_u32(ud[NFTNL_UDATA_CONSTANT_TYPE]);
+ switch (type) {
+ case CONSTANT_EXPR_NFQUEUE_ID:
+ dtype = &queue_type;
+ break;
+ default:
+ break;
+ }
+
+ return constant_expr_alloc(&internal_location, dtype, BYTEORDER_HOST_ENDIAN,
+ 16, NULL);
+}
+
static void constant_expr_print(const struct expr *expr,
struct output_ctx *octx)
{
@@ -401,6 +479,8 @@ static const struct expr_ops constant_expr_ops = {
.cmp = constant_expr_cmp,
.clone = constant_expr_clone,
.destroy = constant_expr_destroy,
+ .build_udata = constant_expr_build_udata,
+ .parse_udata = constant_expr_parse_udata,
};
struct expr *constant_expr_alloc(const struct location *loc,
diff --git a/src/json. b/src/json.
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/src/netlink.c b/src/netlink.c
index 25ee3419772b..36140fb63d6f 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1466,7 +1466,11 @@ key_end:
data = netlink_alloc_data(&netlink_location, &nld,
set->data->dtype->type == TYPE_VERDICT ?
NFT_REG_VERDICT : NFT_REG_1);
- datatype_set(data, set->data->dtype);
+
+ if (set->data->dtype->is_typeof)
+ datatype_set(data, set->data->dtype->basetype);
+ else
+ datatype_set(data, set->data->dtype);
data->byteorder = set->data->byteorder;
if (set->data->dtype->subtypes) {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 602fc60e6de3..6e6f3cf8335d 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2173,6 +2173,10 @@ typeof_data_expr : INTERVAL typeof_expr
{
$$ = $1;
}
+ | QUEUE
+ {
+ $$ = constant_expr_alloc(&@$, &queue_type, BYTEORDER_HOST_ENDIAN, 16, NULL);
+ }
;
typeof_expr : primary_expr
diff --git a/tests/shell/testcases/nft-f/dumps/nfqueue.nft b/tests/shell/testcases/nft-f/dumps/nfqueue.nft
new file mode 100644
index 000000000000..7fe3ca669544
--- /dev/null
+++ b/tests/shell/testcases/nft-f/dumps/nfqueue.nft
@@ -0,0 +1,11 @@
+table inet t {
+ map get_queue_id {
+ typeof ip saddr . ip daddr . tcp dport : queue
+ elements = { 127.0.0.1 . 127.0.0.1 . 22 : 1,
+ 127.0.0.1 . 127.0.0.2 . 22 : 2 }
+ }
+
+ chain test {
+ queue flags bypass to ip saddr . ip daddr . tcp dport map @get_queue_id
+ }
+}
diff --git a/tests/shell/testcases/nft-f/nfqueue b/tests/shell/testcases/nft-f/nfqueue
new file mode 100755
index 000000000000..07820b7c4fdd
--- /dev/null
+++ b/tests/shell/testcases/nft-f/nfqueue
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -e
+dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+
+$NFT -f "$dumpfile"
--
2.30.2
next prev parent reply other threads:[~2024-11-06 23:34 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-25 7:47 [PATCH nft] src: allow to map key to nfqueue number Florian Westphal
2024-11-06 13:28 ` Pablo Neira Ayuso
2024-11-06 13:52 ` Florian Westphal
2024-11-06 14:32 ` Florian Westphal
2024-11-06 16:03 ` Pablo Neira Ayuso
2024-11-06 23:11 ` Pablo Neira Ayuso
2024-11-06 23:34 ` Pablo Neira Ayuso [this message]
2024-11-08 12:08 ` Florian Westphal
2024-11-11 10:38 ` Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zyv9D385olTWUv1k@calendula \
--to=pablo@netfilter.org \
--cc=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 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.