From 64bb3f43bb96bb43a478f695f5aea5f4ab50fd4b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Mar 2022 17:53:39 +0200 Subject: src: allow to use typeof of raw expressions in set declaration Use the dynamic datatype to allocate an instance of TYPE_INTEGER and set length and byteorder. Add missing information to the set userdata area for raw payload expressions which allows to rebuild the set typeof from the listing path. A few examples: - With anonymous sets: nft add rule x y ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e } - With named sets: table x { set y { typeof ip saddr . @ih,32,32 elements = { 1.1.1.1 . 0x14 } } } Incremental updates are also supported, eg. nft add element x y { 3.3.3.3 . 0x28 } expr_evaluate_concat() is used to evaluate both set key definitions and set key values, using two different function might help to simplify this code in the future. Signed-off-by: Pablo Neira Ayuso --- src/netlink.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index ac73e96f..775c6f51 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1105,17 +1105,25 @@ static struct expr *netlink_parse_interval_elem(const struct set *set, return range_expr_to_prefix(range); } -static struct expr *concat_elem_expr(struct expr *expr, +static struct expr *concat_elem_expr(struct expr *key, const struct datatype *dtype, struct expr *data, int *off) { const struct datatype *subtype; + struct expr *expr; - subtype = concat_subtype_lookup(dtype->type, --(*off)); - - expr = constant_expr_splice(data, subtype->size); - expr->dtype = subtype; - expr->byteorder = subtype->byteorder; + if (key) { + (*off)--; + expr = constant_expr_splice(data, key->len); + expr->dtype = datatype_get(key->dtype); + expr->byteorder = key->byteorder; + expr->len = key->len; + } else { + subtype = concat_subtype_lookup(dtype->type, --(*off)); + expr = constant_expr_splice(data, subtype->size); + expr->dtype = subtype; + expr->byteorder = subtype->byteorder; + } if (expr->byteorder == BYTEORDER_HOST_ENDIAN) mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE); @@ -1133,13 +1141,18 @@ static struct expr *netlink_parse_concat_elem_key(const struct set *set, struct expr *data) { const struct datatype *dtype = set->key->dtype; - struct expr *concat, *expr; + struct expr *concat, *expr, *n = NULL; int off = dtype->subtypes; + if (set->key->etype == EXPR_CONCAT) + n = list_first_entry(&set->key->expressions, struct expr, list); + concat = concat_expr_alloc(&data->location); while (off > 0) { - expr = concat_elem_expr(expr, dtype, data, &off); + expr = concat_elem_expr(n, dtype, data, &off); compound_expr_add(concat, expr); + if (set->key->etype == EXPR_CONCAT) + n = list_next_entry(n, list); } expr_free(data); @@ -1159,7 +1172,7 @@ static struct expr *netlink_parse_concat_elem(const struct set *set, concat = concat_expr_alloc(&data->location); while (off > 0) { - expr = concat_elem_expr(expr, dtype, data, &off); + expr = concat_elem_expr(NULL, dtype, data, &off); list_add_tail(&expr->list, &expressions); } @@ -1171,7 +1184,7 @@ static struct expr *netlink_parse_concat_elem(const struct set *set, while (off > 0) { left = list_first_entry(&expressions, struct expr, list); - expr = concat_elem_expr(expr, dtype, data, &off); + expr = concat_elem_expr(NULL, dtype, data, &off); list_del(&left->list); range = range_expr_alloc(&data->location, left, expr); -- cgit v1.2.3