101 lines
3.2 KiB
Diff
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
|