diff options
-rw-r--r-- | include/libnftnl/set.h | 4 | ||||
-rw-r--r-- | src/ruleset.c | 9 | ||||
-rw-r--r-- | src/set.c | 31 | ||||
-rw-r--r-- | src/set_elem.c | 16 |
4 files changed, 59 insertions, 1 deletions
diff --git a/include/libnftnl/set.h b/include/libnftnl/set.h index 7f3504f..55a47b0 100644 --- a/include/libnftnl/set.h +++ b/include/libnftnl/set.h @@ -29,6 +29,8 @@ struct nft_set; 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); @@ -91,6 +93,8 @@ struct nft_set_elem; 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); diff --git a/src/ruleset.c b/src/ruleset.c index 89ea344..280f1bc 100644 --- a/src/ruleset.c +++ b/src/ruleset.c @@ -312,8 +312,15 @@ static int nft_ruleset_parse_set(struct nft_parse_ctx *ctx, 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); @@ -246,6 +246,37 @@ uint32_t nft_set_attr_get_u32(struct nft_set *s, uint16_t attr) } 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) { diff --git a/src/set_elem.c b/src/set_elem.c index 25cd951..e822acc 100644 --- a/src/set_elem.c +++ b/src/set_elem.c @@ -161,6 +161,22 @@ uint32_t nft_set_elem_attr_get_u32(struct nft_set_elem *s, uint16_t attr) } 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) { |