diff options
author | Florian Westphal <fw@strlen.de> | 2022-04-09 15:58:32 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2022-04-13 13:43:44 +0200 |
commit | ad43b84e1942dd171d6e78c7717495e7186e8307 (patch) | |
tree | d1e5ae82b21f96013505bbf7a4ed56f818d06854 /src/segtree.c | |
parent | 06db230895a8643e8ef42dbad0edcb69a069b75c (diff) |
segtree: add support for get element with sets that contain ifnames
nft get element inet filter s { bla, prefixfoo }
table inet filter {
set s {
type ifname
flags interval
elements = { "prefixfoo*",
"bla" }
}
Also add test cases for this.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/segtree.c')
-rw-r--r-- | src/segtree.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/src/segtree.c b/src/segtree.c index 0135a074..3ccf5ee1 100644 --- a/src/segtree.c +++ b/src/segtree.c @@ -774,6 +774,12 @@ static struct expr *get_set_interval_find(const struct set *cache_set, list_for_each_entry(i, &set->init->expressions, list) { switch (i->key->etype) { + case EXPR_VALUE: + if (expr_basetype(i->key)->type != TYPE_STRING) + break; + /* string type, check if its a range (wildcard), so + * fall through. + */ case EXPR_PREFIX: case EXPR_RANGE: range_expr_value_low(val, i); @@ -796,6 +802,18 @@ out: return range; } +static struct expr *expr_value(struct expr *expr) +{ + switch (expr->etype) { + case EXPR_MAPPING: + return expr->left->key; + case EXPR_SET_ELEM: + return expr->key; + default: + BUG("invalid expression type %s\n", expr_name(expr)); + } +} + static struct expr *__expr_to_set_elem(struct expr *low, struct expr *expr) { struct expr *elem = set_elem_expr_alloc(&low->location, expr); @@ -812,6 +830,31 @@ static struct expr *__expr_to_set_elem(struct expr *low, struct expr *expr) return elem; } +static struct expr *expr_to_set_elem(struct expr *e) +{ + unsigned int len = div_round_up(e->len, BITS_PER_BYTE); + unsigned int str_len; + char data[len + 1]; + struct expr *expr; + + if (expr_basetype(expr_value(e))->type != TYPE_STRING) + return expr_clone(e); + + mpz_export_data(data, expr_value(e)->value, BYTEORDER_BIG_ENDIAN, len); + + str_len = strnlen(data, len); + if (str_len >= len || str_len == 0) + return expr_clone(e); + + data[str_len] = '*'; + + expr = constant_expr_alloc(&e->location, e->dtype, + BYTEORDER_HOST_ENDIAN, + (str_len + 1) * BITS_PER_BYTE, data); + + return __expr_to_set_elem(e, expr); +} + int get_set_decompose(struct set *cache_set, struct set *set) { struct expr *i, *next, *range; @@ -846,7 +889,7 @@ int get_set_decompose(struct set *cache_set, struct set *set) compound_expr_add(new_init, range); else compound_expr_add(new_init, - expr_clone(left)); + expr_to_set_elem(left)); } left = i; } @@ -856,7 +899,7 @@ int get_set_decompose(struct set *cache_set, struct set *set) if (range) compound_expr_add(new_init, range); else - compound_expr_add(new_init, expr_clone(left)); + compound_expr_add(new_init, expr_to_set_elem(left)); } expr_free(set->init); @@ -878,18 +921,6 @@ static bool range_is_prefix(const mpz_t range) return ret; } -static struct expr *expr_value(struct expr *expr) -{ - switch (expr->etype) { - case EXPR_MAPPING: - return expr->left->key; - case EXPR_SET_ELEM: - return expr->key; - default: - BUG("invalid expression type %s\n", expr_name(expr)); - } -} - static int expr_value_cmp(const void *p1, const void *p2) { struct expr *e1 = *(void * const *)p1; |