From ad43b84e1942dd171d6e78c7717495e7186e8307 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 9 Apr 2022 15:58:32 +0200 Subject: 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 Signed-off-by: Pablo Neira Ayuso --- src/segtree.c | 59 +++++++++++++++++++++------- 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 -- cgit v1.2.3