struct nft_set *nft_set_alloc(void);
void nft_set_free(struct nft_set *s);
+struct nft_set *nft_set_clone(const struct nft_set *set);
+
bool nft_set_attr_is_set(const struct nft_set *s, uint16_t attr);
void nft_set_attr_unset(struct nft_set *s, uint16_t attr);
void nft_set_attr_set(struct nft_set *s, uint16_t attr, const void *data);
struct nft_set_elem *nft_set_elem_alloc(void);
void nft_set_elem_free(struct nft_set_elem *s);
+struct nft_set_elem *nft_set_elem_clone(struct nft_set_elem *elem);
+
void nft_set_elem_add(struct nft_set *s, struct nft_set_elem *elem);
void nft_set_elem_attr_unset(struct nft_set_elem *s, uint16_t attr);
struct nft_set *set, uint32_t type,
struct nft_parse_err *err)
{
+ struct nft_set *newset;
+
nft_set_attr_set_u32(set, NFT_SET_ATTR_ID, ctx->set_id++);
- nft_set_list_add_tail(set, ctx->set_list);
+
+ newset = nft_set_clone(set);
+ if (newset == NULL)
+ goto err;
+
+ nft_set_list_add_tail(newset, ctx->set_list);
nft_ruleset_ctx_set_u32(ctx, NFT_RULESET_CTX_TYPE, type);
nft_ruleset_ctx_set(ctx, NFT_RULESET_CTX_SET, set);
}
EXPORT_SYMBOL(nft_set_attr_get_u32);
+struct nft_set *nft_set_clone(const struct nft_set *set)
+{
+ struct nft_set *newset;
+ struct nft_set_elem *elem, *newelem;
+
+ newset = nft_set_alloc();
+ if (newset == NULL)
+ return NULL;
+
+ memcpy(newset, set, sizeof(*set));
+
+ if (set->flags & (1 << NFT_SET_ATTR_TABLE))
+ newset->table = strdup(set->table);
+ if (set->flags & (1 << NFT_SET_ATTR_NAME))
+ newset->name = strdup(set->name);
+
+ INIT_LIST_HEAD(&newset->element_list);
+ list_for_each_entry(elem, &set->element_list, head) {
+ newelem = nft_set_elem_clone(elem);
+ if (newelem == NULL)
+ goto err;
+
+ list_add_tail(&newelem->head, &newset->element_list);
+ }
+
+ return newset;
+err:
+ nft_set_free(newset);
+ return NULL;
+}
+
static void
nft_set_nlmsg_build_desc_payload(struct nlmsghdr *nlh, struct nft_set *s)
{
}
EXPORT_SYMBOL(nft_set_elem_attr_get_u32);
+struct nft_set_elem *nft_set_elem_clone(struct nft_set_elem *elem)
+{
+ struct nft_set_elem *newelem;
+
+ newelem = nft_set_elem_alloc();
+ if (newelem == NULL)
+ return NULL;
+
+ memcpy(newelem, elem, sizeof(*elem));
+
+ if (elem->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN))
+ newelem->data.chain = strdup(elem->data.chain);
+
+ return newelem;
+}
+
void nft_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh,
struct nft_set_elem *e)
{