From a93bc1795b272174a10d90961a248f2c620bfa2c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 12 Apr 2015 21:10:42 +0100 Subject: netlink: handle concat expressions in set data Reconstruct the concat expressions in set data by splicing off the subtype values based on the keytype of the set. Signed-off-by: Patrick McHardy --- src/datatype.c | 2 +- src/netlink.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/datatype.c b/src/datatype.c index a06a58e2..ca834263 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -932,7 +932,7 @@ const struct datatype *concat_type_alloc(uint32_t type) unsigned int size = 0, subtypes = 0, n; n = div_round_up(fls(type), TYPE_BITS); - while (concat_subtype_id(type, --n)) { + while (n > 0 && concat_subtype_id(type, --n)) { i = concat_subtype_lookup(type, n); if (i == NULL) return NULL; diff --git a/src/netlink.c b/src/netlink.c index 3369d223..1167c951 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1383,6 +1383,36 @@ static int netlink_del_setelems_compat(struct netlink_ctx *ctx, return err; } +static struct expr *netlink_parse_concat_elem(const struct datatype *dtype, + struct expr *data) +{ + const struct datatype *subtype; + struct expr *concat, *expr; + int off = dtype->subtypes; + + concat = concat_expr_alloc(&data->location); + while (off > 0) { + 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); + + if (expr->dtype->basetype != NULL && + expr->dtype->basetype->type == TYPE_BITMASK) + expr = bitmask_expr_to_binops(expr); + + compound_expr_add(concat, expr); + data->len -= netlink_padding_len(expr->len); + } + expr_free(data); + + return concat; +} + static int netlink_delinearize_setelem(struct nft_set_elem *nlse, struct set *set) { @@ -1398,6 +1428,8 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, key = netlink_alloc_value(&netlink_location, &nld); key->dtype = set->keytype; key->byteorder = set->keytype->byteorder; + if (set->keytype->subtypes) + key = netlink_parse_concat_elem(set->keytype, key); if (!(set->flags & SET_F_INTERVAL) && key->byteorder == BYTEORDER_HOST_ENDIAN) -- cgit v1.2.3