diff options
-rw-r--r-- | src/netlink_delinearize.c | 46 | ||||
-rwxr-xr-x | tests/shell/testcases/sets/0045concat_ipv4_service | 16 | ||||
-rw-r--r-- | tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft | 12 |
3 files changed, 73 insertions, 1 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index bd75ad5c..0c2b439e 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -134,6 +134,50 @@ err: return NULL; } +static struct expr *netlink_parse_concat_key(struct netlink_parse_ctx *ctx, + const struct location *loc, + unsigned int reg, + const struct expr *key) +{ + uint32_t type = key->dtype->type; + unsigned int n, len = key->len; + struct expr *concat, *expr; + unsigned int consumed; + + concat = concat_expr_alloc(loc); + n = div_round_up(fls(type), TYPE_BITS); + + while (len > 0) { + const struct datatype *i; + + expr = netlink_get_register(ctx, loc, reg); + if (expr == NULL) { + netlink_error(ctx, loc, + "Concat expression size mismatch"); + goto err; + } + + if (n > 0 && concat_subtype_id(type, --n)) { + i = concat_subtype_lookup(type, n); + + expr_set_type(expr, i, i->byteorder); + } + + compound_expr_add(concat, expr); + + consumed = netlink_padded_len(expr->len); + assert(consumed > 0); + len -= consumed; + reg += netlink_register_space(expr->len); + } + + return concat; + +err: + expr_free(concat); + return NULL; +} + static struct expr *netlink_parse_concat_data(struct netlink_parse_ctx *ctx, const struct location *loc, unsigned int reg, @@ -1572,7 +1616,7 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx, if (expr->len < set->key->len) { expr_free(expr); - expr = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len); + expr = netlink_parse_concat_key(ctx, loc, sreg, set->key); if (expr == NULL) return; } diff --git a/tests/shell/testcases/sets/0045concat_ipv4_service b/tests/shell/testcases/sets/0045concat_ipv4_service new file mode 100755 index 00000000..5b40f973 --- /dev/null +++ b/tests/shell/testcases/sets/0045concat_ipv4_service @@ -0,0 +1,16 @@ +#!/bin/bash + +$NFT -f - <<EOF +table inet t { + set s { + type ipv4_addr . inet_service + size 65536 + flags dynamic,timeout + elements = { 192.168.7.1 . 22 } + } + + chain c { + tcp dport 21 add @s { ip saddr . 22 timeout 60s } + } +} +EOF diff --git a/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft b/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft new file mode 100644 index 00000000..e548a17a --- /dev/null +++ b/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft @@ -0,0 +1,12 @@ +table inet t { + set s { + type ipv4_addr . inet_service + size 65536 + flags dynamic,timeout + elements = { 192.168.7.1 . 22 } + } + + chain c { + tcp dport 21 add @s { ip saddr . 22 timeout 1m } + } +} |