diff options
Diffstat (limited to 'src/netlink.c')
-rw-r--r-- | src/netlink.c | 83 |
1 files changed, 59 insertions, 24 deletions
diff --git a/src/netlink.c b/src/netlink.c index 343d8bea..d31387f8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -205,6 +205,7 @@ struct nft_set *alloc_nft_set(const struct handle *h) static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) { + const struct expr *elem, *key, *data; struct nft_set_elem *nlse; struct nft_data_linearize nld; @@ -212,24 +213,34 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) if (nlse == NULL) memory_allocation_error(); - if (expr->ops->type == EXPR_VALUE || - expr->flags & EXPR_F_INTERVAL_END) { - netlink_gen_data(expr, &nld); - nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, - &nld.value, nld.len); + data = NULL; + if (expr->ops->type == EXPR_MAPPING) { + elem = expr->left; + if (!(expr->flags & EXPR_F_INTERVAL_END)) + data = expr->right; } else { - assert(expr->ops->type == EXPR_MAPPING); - netlink_gen_data(expr->left, &nld); - nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, - &nld.value, nld.len); - netlink_gen_data(expr->right, &nld); - switch (expr->right->ops->type) { + elem = expr; + } + key = elem->key; + + netlink_gen_data(key, &nld); + nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, &nld.value, nld.len); + if (elem->timeout) + nft_set_elem_attr_set_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT, + elem->timeout); + if (elem->comment) + nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_USERDATA, + elem->comment, strlen(elem->comment) + 1); + + if (data != NULL) { + netlink_gen_data(data, &nld); + switch (data->ops->type) { case EXPR_VERDICT: nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT, - expr->right->verdict); - if (expr->chain != NULL) + data->verdict); + if (data->chain != NULL) nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_CHAIN, - nld.chain, strlen(nld.chain)); + nld.chain, strlen(nld.chain)); break; case EXPR_VALUE: nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_DATA, @@ -1063,6 +1074,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx, set->datalen = data_len * BITS_PER_BYTE; } + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_TIMEOUT)) + set->timeout = nft_set_attr_get_u64(nls, NFT_SET_ATTR_TIMEOUT); + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_GC_INTERVAL)) + set->gc_int = nft_set_attr_get_u32(nls, NFT_SET_ATTR_GC_INTERVAL); + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_POLICY)) set->policy = nft_set_attr_get_u32(nls, NFT_SET_ATTR_POLICY); @@ -1126,6 +1142,11 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx, nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN, set->datalen / BITS_PER_BYTE); } + if (set->timeout) + nft_set_attr_set_u64(nls, NFT_SET_ATTR_TIMEOUT, set->timeout); + if (set->gc_int) + nft_set_attr_set_u32(nls, NFT_SET_ATTR_GC_INTERVAL, set->gc_int); + set->handle.set_id = ++set_id; nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, set->handle.set_id); @@ -1368,7 +1389,7 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, struct set *set) { struct nft_data_delinearize nld; - struct expr *expr, *data; + struct expr *expr, *key, *data; uint32_t flags = 0; nld.value = @@ -1376,17 +1397,31 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_FLAGS)) flags = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_FLAGS); - expr = netlink_alloc_value(&netlink_location, &nld); - expr->dtype = set->keytype; - expr->byteorder = set->keytype->byteorder; + key = netlink_alloc_value(&netlink_location, &nld); + key->dtype = set->keytype; + key->byteorder = set->keytype->byteorder; if (!(set->flags & SET_F_INTERVAL) && - 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); + key->byteorder == BYTEORDER_HOST_ENDIAN) + mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE); + + if (key->dtype->basetype != NULL && + key->dtype->basetype->type == TYPE_BITMASK) + key = bitmask_expr_to_binops(key); + + expr = set_elem_expr_alloc(&netlink_location, key); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_TIMEOUT)) + expr->timeout = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_EXPIRATION)) + expr->expiration = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_EXPIRATION); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_USERDATA)) { + const void *data; + uint32_t len; + + data = nft_set_elem_attr_get(nlse, NFT_SET_ELEM_ATTR_USERDATA, &len); + expr->comment = xmalloc(len); + memcpy((char *)expr->comment, data, len); + } if (flags & NFT_SET_ELEM_INTERVAL_END) { expr->flags |= EXPR_F_INTERVAL_END; |