nftables/backport-segtree-add-string-range-reversal-support.patch
xinghe 2a3e281bef fix Community bugs
(cherry picked from commit 1258053e29d80addcc11865a921c9bfaa91eb903)
2022-09-05 16:09:33 +08:00

101 lines
3.2 KiB
Diff

From 5e393ea1fc0ad6b59e90103bf83e93b2449d519e Mon Sep 17 00:00:00 2001
From: Florian Westphal <fw@strlen.de>
Date: Sat, 9 Apr 2022 15:58:29 +0200
Subject: segtree: add string "range" reversal support
Previous commits allows to use set key as a range, i.e.
key ifname
flags interval
elements = { eth* }
and then have it match on any interface starting with 'eth'.
Listing is broken however, we need to reverse-translate the (128bit)
number back to a string.
'eth*' is stored as interval
00687465 0000000 .. 00697465 0000000, i.e. "eth-eti",
this adds the needed endianess fixups.
Conflict: NA
Reference: https://git.netfilter.org/nftables/patch/?id=5e393ea1fc0ad6b59e90103bf83e93b2449d519e
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/segtree.c | 47 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/segtree.c b/src/segtree.c
index b4e76bf5..bed8bbcf 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -1032,6 +1032,33 @@ static struct expr *interval_to_prefix(struct expr *low, struct expr *i, const m
return __expr_to_set_elem(low, prefix);
}
+static struct expr *interval_to_string(struct expr *low, struct expr *i, const mpz_t range)
+{
+ unsigned int len = div_round_up(i->len, BITS_PER_BYTE);
+ unsigned int prefix_len, str_len;
+ char data[len + 2];
+ struct expr *expr;
+
+ prefix_len = expr_value(i)->len - mpz_scan0(range, 0);
+
+ if (prefix_len > i->len || prefix_len % BITS_PER_BYTE)
+ return interval_to_prefix(low, i, range);
+
+ mpz_export_data(data, expr_value(low)->value, BYTEORDER_BIG_ENDIAN, len);
+
+ str_len = strnlen(data, len);
+ if (str_len >= len || str_len == 0)
+ return interval_to_prefix(low, i, range);
+
+ data[str_len] = '*';
+
+ expr = constant_expr_alloc(&low->location, low->dtype,
+ BYTEORDER_HOST_ENDIAN,
+ (str_len + 1) * BITS_PER_BYTE, data);
+
+ return __expr_to_set_elem(low, expr);
+}
+
static struct expr *interval_to_range(struct expr *low, struct expr *i, mpz_t range)
{
struct expr *tmp;
@@ -1130,16 +1157,24 @@ void interval_map_decompose(struct expr *set)
mpz_and(p, expr_value(low)->value, range);
- if (!mpz_cmp_ui(range, 0))
+ if (!mpz_cmp_ui(range, 0)) {
+ if (expr_basetype(low)->type == TYPE_STRING)
+ mpz_switch_byteorder(expr_value(low)->value, low->len / BITS_PER_BYTE);
+
compound_expr_add(set, expr_get(low));
- else if ((!range_is_prefix(range) ||
- !(i->dtype->flags & DTYPE_F_PREFIX)) ||
- mpz_cmp_ui(p, 0)) {
- struct expr *expr = interval_to_range(low, i, range);
+ } else if (range_is_prefix(range) && !mpz_cmp_ui(p, 0)) {
+ struct expr *expr;
+
+ if (i->dtype->flags & DTYPE_F_PREFIX)
+ expr = interval_to_prefix(low, i, range);
+ else if (expr_basetype(i)->type == TYPE_STRING)
+ expr = interval_to_string(low, i, range);
+ else
+ expr = interval_to_range(low, i, range);
compound_expr_add(set, expr);
} else {
- struct expr *expr = interval_to_prefix(low, i, range);
+ struct expr *expr = interval_to_range(low, i, range);
compound_expr_add(set, expr);
}
--
cgit v1.2.3