summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libnftnl/set.h1
-rw-r--r--include/set.h4
-rw-r--r--src/set.c29
3 files changed, 34 insertions, 0 deletions
diff --git a/include/libnftnl/set.h b/include/libnftnl/set.h
index 3d50d56..5266b6f 100644
--- a/include/libnftnl/set.h
+++ b/include/libnftnl/set.h
@@ -22,6 +22,7 @@ enum nftnl_set_attr {
NFTNL_SET_DESC_SIZE,
NFTNL_SET_TIMEOUT,
NFTNL_SET_GC_INTERVAL,
+ NFTNL_SET_USERDATA,
__NFTNL_SET_MAX
};
#define NFTNL_SET_MAX (__NFTNL_SET_MAX - 1)
diff --git a/include/set.h b/include/set.h
index c3b96f2..85bd389 100644
--- a/include/set.h
+++ b/include/set.h
@@ -14,6 +14,10 @@ struct nftnl_set {
uint32_t key_len;
uint32_t data_type;
uint32_t data_len;
+ struct {
+ void *data;
+ uint32_t len;
+ } user;
uint32_t id;
enum nft_set_policies policy;
struct {
diff --git a/src/set.c b/src/set.c
index 47e0c45..9315bf0 100644
--- a/src/set.c
+++ b/src/set.c
@@ -87,6 +87,9 @@ void nftnl_set_unset(struct nftnl_set *s, uint16_t attr)
case NFTNL_SET_TIMEOUT:
case NFTNL_SET_GC_INTERVAL:
break;
+ case NFTNL_SET_USERDATA:
+ xfree(s->user.data);
+ break;
default:
return;
}
@@ -164,6 +167,16 @@ int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
case NFTNL_SET_GC_INTERVAL:
s->gc_interval = *((uint32_t *)data);
break;
+ case NFTNL_SET_USERDATA:
+ if (s->flags & (1 << NFTNL_SET_USERDATA))
+ xfree(s->user.data);
+
+ s->user.data = malloc(data_len);
+ if (!s->user.data)
+ return -1;
+ memcpy(s->user.data, data, data_len);
+ s->user.len = data_len;
+ break;
}
s->flags |= (1 << attr);
return 0;
@@ -238,6 +251,9 @@ const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr,
case NFTNL_SET_GC_INTERVAL:
*data_len = sizeof(uint32_t);
return &s->gc_interval;
+ case NFTNL_SET_USERDATA:
+ *data_len = s->user.len;
+ return s->user.data;
}
return NULL;
}
@@ -352,6 +368,8 @@ void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
+ if (s->flags & (1 << NFTNL_SET_USERDATA))
+ mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
}
EXPORT_SYMBOL_ALIAS(nftnl_set_nlmsg_build_payload, nft_set_nlmsg_build_payload);
@@ -380,6 +398,10 @@ static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data)
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
+ case NFTA_SET_USERDATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+ abi_breakage();
+ break;
case NFTA_SET_TIMEOUT:
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
abi_breakage();
@@ -490,6 +512,13 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
}
+ if (tb[NFTA_SET_USERDATA]) {
+ ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
+ mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
+ mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
+ if (ret < 0)
+ return ret;
+ }
if (tb[NFTA_SET_DESC]) {
ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
if (ret < 0)