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 | |
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>
-rw-r--r-- | src/segtree.c | 59 | ||||
-rwxr-xr-x | tests/shell/testcases/sets/sets_with_ifnames | 21 |
2 files changed, 65 insertions, 15 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; diff --git a/tests/shell/testcases/sets/sets_with_ifnames b/tests/shell/testcases/sets/sets_with_ifnames index 0f9a6b5b..10e6c331 100755 --- a/tests/shell/testcases/sets/sets_with_ifnames +++ b/tests/shell/testcases/sets/sets_with_ifnames @@ -22,11 +22,22 @@ check_elem() setname=$1 ifname=$2 fail=$3 + result=$4 + + if [ -z "$result" ]; then + result=$ifname + fi if [ $fail -eq 1 ]; then ip netns exec "$ns1" $NFT get element inet testifsets $setname { "$ifname" } && exit 2 else - ip netns exec "$ns1" $NFT get element inet testifsets $setname { "$ifname" } || exit 3 + result=$(ip netns exec "$ns1" $NFT get element inet testifsets $setname { "$ifname" } | grep "$result" ) + + if [ -z "$result" ] ; then + echo "empty result, expected $ifname" + ip netns exec "$ns1" $NFT get element inet testifsets $setname { "$ifname" } + exit 1 + fi fi } @@ -61,6 +72,14 @@ done check_elem simple foo 1 +for n in ppp0 othername;do + check_elem simple_wild $n 0 +done + +check_elem simple_wild enoent 1 +check_elem simple_wild ppp0 0 +check_elem simple_wild abcdefghijk 0 'abcdef\*' + set -e ip -net "$ns1" link set lo up ip -net "$ns2" link set lo up |