15#include <netinet/in.h>
19#include <libmnl/libmnl.h>
20#include <linux/netfilter/nfnetlink.h>
21#include <linux/netfilter/nf_tables.h>
23#include <libnftnl/set.h>
24#include <libnftnl/expr.h>
26EXPORT_SYMBOL(nftnl_set_alloc);
27struct nftnl_set *nftnl_set_alloc(
void)
31 s = calloc(1,
sizeof(
struct nftnl_set));
35 INIT_LIST_HEAD(&s->element_list);
36 INIT_LIST_HEAD(&s->expr_list);
40EXPORT_SYMBOL(nftnl_set_free);
41void nftnl_set_free(
const struct nftnl_set *s)
43 struct nftnl_set_elem *elem, *tmp;
44 struct nftnl_expr *expr, *next;
46 if (s->flags & (1 << NFTNL_SET_TABLE))
48 if (s->flags & (1 << NFTNL_SET_NAME))
50 if (s->flags & (1 << NFTNL_SET_USERDATA))
53 list_for_each_entry_safe(expr, next, &s->expr_list, head) {
54 list_del(&expr->head);
55 nftnl_expr_free(expr);
58 list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
59 list_del(&elem->head);
60 nftnl_set_elem_free(elem);
67EXPORT_SYMBOL(nftnl_set_is_set);
68bool nftnl_set_is_set(
const struct nftnl_set *s, uint16_t attr)
70 return s->flags & (1 << attr);
73EXPORT_SYMBOL(nftnl_set_unset);
74void nftnl_set_unset(
struct nftnl_set *s, uint16_t attr)
76 struct nftnl_expr *expr, *tmp;
78 if (!(s->flags & (1 << attr)))
88 case NFTNL_SET_HANDLE:
90 case NFTNL_SET_KEY_TYPE:
91 case NFTNL_SET_KEY_LEN:
92 case NFTNL_SET_DATA_TYPE:
93 case NFTNL_SET_DATA_LEN:
94 case NFTNL_SET_OBJ_TYPE:
95 case NFTNL_SET_FAMILY:
97 case NFTNL_SET_POLICY:
98 case NFTNL_SET_DESC_SIZE:
99 case NFTNL_SET_DESC_CONCAT:
100 case NFTNL_SET_TIMEOUT:
101 case NFTNL_SET_GC_INTERVAL:
102 case NFTNL_SET_COUNT:
104 case NFTNL_SET_USERDATA:
108 case NFTNL_SET_EXPRESSIONS:
109 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
110 list_del(&expr->head);
111 nftnl_expr_free(expr);
118 s->flags &= ~(1 << attr);
121static uint32_t nftnl_set_validate[NFTNL_SET_MAX + 1] = {
122 [NFTNL_SET_HANDLE] =
sizeof(uint64_t),
123 [NFTNL_SET_FLAGS] =
sizeof(uint32_t),
124 [NFTNL_SET_KEY_TYPE] =
sizeof(uint32_t),
125 [NFTNL_SET_KEY_LEN] =
sizeof(uint32_t),
126 [NFTNL_SET_DATA_TYPE] =
sizeof(uint32_t),
127 [NFTNL_SET_DATA_LEN] =
sizeof(uint32_t),
128 [NFTNL_SET_OBJ_TYPE] =
sizeof(uint32_t),
129 [NFTNL_SET_FAMILY] =
sizeof(uint32_t),
130 [NFTNL_SET_ID] =
sizeof(uint32_t),
131 [NFTNL_SET_POLICY] =
sizeof(uint32_t),
132 [NFTNL_SET_DESC_SIZE] =
sizeof(uint32_t),
133 [NFTNL_SET_TIMEOUT] =
sizeof(uint64_t),
134 [NFTNL_SET_GC_INTERVAL] =
sizeof(uint32_t),
135 [NFTNL_SET_COUNT] =
sizeof(uint32_t),
138EXPORT_SYMBOL(nftnl_set_set_data);
139int nftnl_set_set_data(
struct nftnl_set *s, uint16_t attr,
const void *data,
142 struct nftnl_expr *expr, *tmp;
144 nftnl_assert_attr_exists(attr, NFTNL_SET_MAX);
145 nftnl_assert_validate(data, nftnl_set_validate, attr, data_len);
148 case NFTNL_SET_TABLE:
149 return nftnl_set_str_attr(&s->table, &s->flags,
150 attr, data, data_len);
152 return nftnl_set_str_attr(&s->name, &s->flags,
153 attr, data, data_len);
154 case NFTNL_SET_HANDLE:
155 memcpy(&s->handle, data,
sizeof(s->handle));
157 case NFTNL_SET_FLAGS:
158 memcpy(&s->set_flags, data,
sizeof(s->set_flags));
160 case NFTNL_SET_KEY_TYPE:
161 memcpy(&s->key_type, data,
sizeof(s->key_type));
163 case NFTNL_SET_KEY_LEN:
164 memcpy(&s->key_len, data,
sizeof(s->key_len));
166 case NFTNL_SET_DATA_TYPE:
167 memcpy(&s->data_type, data,
sizeof(s->data_type));
169 case NFTNL_SET_DATA_LEN:
170 memcpy(&s->data_len, data,
sizeof(s->data_len));
172 case NFTNL_SET_OBJ_TYPE:
173 memcpy(&s->obj_type, data,
sizeof(s->obj_type));
175 case NFTNL_SET_FAMILY:
176 memcpy(&s->family, data,
sizeof(s->family));
179 memcpy(&s->id, data,
sizeof(s->id));
181 case NFTNL_SET_POLICY:
182 memcpy(&s->policy, data,
sizeof(s->policy));
184 case NFTNL_SET_DESC_SIZE:
185 memcpy(&s->desc.size, data,
sizeof(s->desc.size));
187 case NFTNL_SET_DESC_CONCAT:
188 if (data_len >
sizeof(s->desc.field_len))
191 memcpy(&s->desc.field_len, data, data_len);
192 for (s->desc.field_count = 0;
193 s->desc.field_count < NFT_REG32_COUNT;
194 s->desc.field_count++) {
195 if (!s->desc.field_len[s->desc.field_count])
199 case NFTNL_SET_TIMEOUT:
200 memcpy(&s->timeout, data,
sizeof(s->timeout));
202 case NFTNL_SET_GC_INTERVAL:
203 memcpy(&s->gc_interval, data,
sizeof(s->gc_interval));
205 case NFTNL_SET_COUNT:
206 memcpy(&s->elemcount, data,
sizeof(s->elemcount));
208 case NFTNL_SET_USERDATA:
209 if (s->flags & (1 << NFTNL_SET_USERDATA))
212 s->user.data = malloc(data_len);
215 memcpy(s->user.data, data, data_len);
216 s->user.len = data_len;
219 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
220 list_del(&expr->head);
221 nftnl_expr_free(expr);
225 list_add(&expr->head, &s->expr_list);
228 s->flags |= (1 << attr);
232int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data) __visible;
233int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data)
235 return nftnl_set_set_data(s, attr, data, nftnl_set_validate[attr]);
238EXPORT_SYMBOL(nftnl_set_set_u32);
239void nftnl_set_set_u32(
struct nftnl_set *s, uint16_t attr, uint32_t val)
241 nftnl_set_set_data(s, attr, &val,
sizeof(uint32_t));
244EXPORT_SYMBOL(nftnl_set_set_u64);
245void nftnl_set_set_u64(
struct nftnl_set *s, uint16_t attr, uint64_t val)
247 nftnl_set_set_data(s, attr, &val,
sizeof(uint64_t));
250EXPORT_SYMBOL(nftnl_set_set_str);
251int nftnl_set_set_str(
struct nftnl_set *s, uint16_t attr,
const char *str)
253 return nftnl_set_set_data(s, attr, str, strlen(str) + 1);
256EXPORT_SYMBOL(nftnl_set_get_data);
257const void *nftnl_set_get_data(
const struct nftnl_set *s, uint16_t attr,
260 struct nftnl_expr *expr;
262 if (!(s->flags & (1 << attr)))
266 case NFTNL_SET_TABLE:
267 *data_len = strlen(s->table) + 1;
270 *data_len = strlen(s->name) + 1;
272 case NFTNL_SET_HANDLE:
273 *data_len =
sizeof(uint64_t);
275 case NFTNL_SET_FLAGS:
276 *data_len =
sizeof(uint32_t);
277 return &s->set_flags;
278 case NFTNL_SET_KEY_TYPE:
279 *data_len =
sizeof(uint32_t);
281 case NFTNL_SET_KEY_LEN:
282 *data_len =
sizeof(uint32_t);
284 case NFTNL_SET_DATA_TYPE:
285 *data_len =
sizeof(uint32_t);
286 return &s->data_type;
287 case NFTNL_SET_DATA_LEN:
288 *data_len =
sizeof(uint32_t);
290 case NFTNL_SET_OBJ_TYPE:
291 *data_len =
sizeof(uint32_t);
293 case NFTNL_SET_FAMILY:
294 *data_len =
sizeof(uint32_t);
297 *data_len =
sizeof(uint32_t);
299 case NFTNL_SET_POLICY:
300 *data_len =
sizeof(uint32_t);
302 case NFTNL_SET_DESC_SIZE:
303 *data_len =
sizeof(uint32_t);
304 return &s->desc.size;
305 case NFTNL_SET_DESC_CONCAT:
306 *data_len = s->desc.field_count;
307 return s->desc.field_len;
308 case NFTNL_SET_TIMEOUT:
309 *data_len =
sizeof(uint64_t);
311 case NFTNL_SET_GC_INTERVAL:
312 *data_len =
sizeof(uint32_t);
313 return &s->gc_interval;
314 case NFTNL_SET_COUNT:
315 *data_len =
sizeof(uint32_t);
316 return &s->elemcount;
317 case NFTNL_SET_USERDATA:
318 *data_len = s->user.len;
321 list_for_each_entry(expr, &s->expr_list, head)
328EXPORT_SYMBOL(nftnl_set_get);
329const void *nftnl_set_get(
const struct nftnl_set *s, uint16_t attr)
332 return nftnl_set_get_data(s, attr, &data_len);
335EXPORT_SYMBOL(nftnl_set_get_str);
336const char *nftnl_set_get_str(
const struct nftnl_set *s, uint16_t attr)
338 return nftnl_set_get(s, attr);
341EXPORT_SYMBOL(nftnl_set_get_u32);
342uint32_t nftnl_set_get_u32(
const struct nftnl_set *s, uint16_t attr)
345 const uint32_t *val = nftnl_set_get_data(s, attr, &data_len);
347 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
349 return val ? *val : 0;
352EXPORT_SYMBOL(nftnl_set_get_u64);
353uint64_t nftnl_set_get_u64(
const struct nftnl_set *s, uint16_t attr)
356 const uint64_t *val = nftnl_set_get_data(s, attr, &data_len);
358 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
360 return val ? *val : 0;
363struct nftnl_set *nftnl_set_clone(
const struct nftnl_set *set)
365 struct nftnl_set *newset;
366 struct nftnl_set_elem *elem, *newelem;
368 newset = nftnl_set_alloc();
372 memcpy(newset, set,
sizeof(*set));
374 if (set->flags & (1 << NFTNL_SET_TABLE)) {
375 newset->table = strdup(set->table);
379 if (set->flags & (1 << NFTNL_SET_NAME)) {
380 newset->name = strdup(set->name);
385 INIT_LIST_HEAD(&newset->element_list);
386 list_for_each_entry(elem, &set->element_list, head) {
387 newelem = nftnl_set_elem_clone(elem);
391 list_add_tail(&newelem->head, &newset->element_list);
398 nftnl_set_free(newset);
402static void nftnl_set_nlmsg_build_desc_size_payload(
struct nlmsghdr *nlh,
405 mnl_attr_put_u32(nlh, NFTA_SET_DESC_SIZE, htonl(s->desc.size));
408static void nftnl_set_nlmsg_build_desc_concat_payload(
struct nlmsghdr *nlh,
414 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC_CONCAT);
415 for (i = 0; i < NFT_REG32_COUNT && i < s->desc.field_count; i++) {
416 struct nlattr *nest_elem;
418 nest_elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
419 mnl_attr_put_u32(nlh, NFTA_SET_FIELD_LEN,
420 htonl(s->desc.field_len[i]));
421 mnl_attr_nest_end(nlh, nest_elem);
423 mnl_attr_nest_end(nlh, nest);
427nftnl_set_nlmsg_build_desc_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
431 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC);
433 if (s->flags & (1 << NFTNL_SET_DESC_SIZE))
434 nftnl_set_nlmsg_build_desc_size_payload(nlh, s);
435 if (s->flags & (1 << NFTNL_SET_DESC_CONCAT))
436 nftnl_set_nlmsg_build_desc_concat_payload(nlh, s);
438 mnl_attr_nest_end(nlh, nest);
441EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
442void nftnl_set_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
446 if (s->flags & (1 << NFTNL_SET_TABLE))
447 mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
448 if (s->flags & (1 << NFTNL_SET_NAME))
449 mnl_attr_put_strz(nlh, NFTA_SET_NAME, s->name);
450 if (s->flags & (1 << NFTNL_SET_HANDLE))
451 mnl_attr_put_u64(nlh, NFTA_SET_HANDLE, htobe64(s->handle));
452 if (s->flags & (1 << NFTNL_SET_FLAGS))
453 mnl_attr_put_u32(nlh, NFTA_SET_FLAGS, htonl(s->set_flags));
454 if (s->flags & (1 << NFTNL_SET_KEY_TYPE))
455 mnl_attr_put_u32(nlh, NFTA_SET_KEY_TYPE, htonl(s->key_type));
456 if (s->flags & (1 << NFTNL_SET_KEY_LEN))
457 mnl_attr_put_u32(nlh, NFTA_SET_KEY_LEN, htonl(s->key_len));
459 if (s->flags & (1 << NFTNL_SET_DATA_TYPE))
460 mnl_attr_put_u32(nlh, NFTA_SET_DATA_TYPE, htonl(s->data_type));
461 if (s->flags & (1 << NFTNL_SET_DATA_LEN))
462 mnl_attr_put_u32(nlh, NFTA_SET_DATA_LEN, htonl(s->data_len));
463 if (s->flags & (1 << NFTNL_SET_OBJ_TYPE))
464 mnl_attr_put_u32(nlh, NFTA_SET_OBJ_TYPE, htonl(s->obj_type));
465 if (s->flags & (1 << NFTNL_SET_ID))
466 mnl_attr_put_u32(nlh, NFTA_SET_ID, htonl(s->id));
467 if (s->flags & (1 << NFTNL_SET_POLICY))
468 mnl_attr_put_u32(nlh, NFTA_SET_POLICY, htonl(s->policy));
469 if (s->flags & (1 << NFTNL_SET_DESC_SIZE | 1 << NFTNL_SET_DESC_CONCAT))
470 nftnl_set_nlmsg_build_desc_payload(nlh, s);
471 if (s->flags & (1 << NFTNL_SET_TIMEOUT))
472 mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
473 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
474 mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
475 if (s->flags & (1 << NFTNL_SET_USERDATA))
476 mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
477 if (!list_empty(&s->expr_list)) {
478 struct nftnl_expr *expr;
480 list_for_each_entry(expr, &s->expr_list, head)
483 if (num_exprs == 1) {
484 struct nlattr *nest1;
486 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
487 list_for_each_entry(expr, &s->expr_list, head)
488 nftnl_expr_build_payload(nlh, expr);
490 mnl_attr_nest_end(nlh, nest1);
491 }
else if (num_exprs > 1) {
492 struct nlattr *nest1, *nest2;
494 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS);
495 list_for_each_entry(expr, &s->expr_list, head) {
496 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
497 nftnl_expr_build_payload(nlh, expr);
498 mnl_attr_nest_end(nlh, nest2);
500 mnl_attr_nest_end(nlh, nest1);
505EXPORT_SYMBOL(nftnl_set_add_expr);
506void nftnl_set_add_expr(
struct nftnl_set *s,
struct nftnl_expr *expr)
508 list_add_tail(&expr->head, &s->expr_list);
511EXPORT_SYMBOL(nftnl_set_expr_foreach);
512int nftnl_set_expr_foreach(
const struct nftnl_set *s,
513 int (*cb)(
struct nftnl_expr *e,
void *data),
516 struct nftnl_expr *cur, *tmp;
519 list_for_each_entry_safe(cur, tmp, &s->expr_list, head) {
527static int nftnl_set_parse_attr_cb(
const struct nlattr *attr,
void *data)
529 const struct nlattr **tb = data;
530 int type = mnl_attr_get_type(attr);
532 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
539 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
542 case NFTA_SET_HANDLE:
543 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
547 case NFTA_SET_KEY_TYPE:
548 case NFTA_SET_KEY_LEN:
549 case NFTA_SET_DATA_TYPE:
550 case NFTA_SET_DATA_LEN:
552 case NFTA_SET_POLICY:
553 case NFTA_SET_GC_INTERVAL:
555 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
558 case NFTA_SET_USERDATA:
559 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
562 case NFTA_SET_TIMEOUT:
563 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
568 case NFTA_SET_EXPRESSIONS:
569 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
579nftnl_set_desc_concat_field_parse_attr_cb(
const struct nlattr *attr,
void *data)
581 int type = mnl_attr_get_type(attr);
582 struct nftnl_set *s = data;
584 if (type != NFTA_SET_FIELD_LEN)
587 if (mnl_attr_validate(attr, MNL_TYPE_U32))
590 s->desc.field_len[s->desc.field_count] = ntohl(mnl_attr_get_u32(attr));
591 s->desc.field_count++;
597nftnl_set_desc_concat_parse_attr_cb(
const struct nlattr *attr,
void *data)
599 int type = mnl_attr_get_type(attr);
600 struct nftnl_set *s = data;
602 if (type != NFTA_LIST_ELEM)
605 return mnl_attr_parse_nested(attr,
606 nftnl_set_desc_concat_field_parse_attr_cb,
610static int nftnl_set_desc_parse_attr_cb(
const struct nlattr *attr,
void *data)
612 int type = mnl_attr_get_type(attr), err;
613 struct nftnl_set *s = data;
615 if (mnl_attr_type_valid(attr, NFTA_SET_DESC_MAX) < 0)
619 case NFTA_SET_DESC_SIZE:
620 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
625 s->desc.size = ntohl(mnl_attr_get_u32(attr));
626 s->flags |= (1 << NFTNL_SET_DESC_SIZE);
628 case NFTA_SET_DESC_CONCAT:
629 err = mnl_attr_parse_nested(attr,
630 nftnl_set_desc_concat_parse_attr_cb,
632 if (err != MNL_CB_OK)
635 s->flags |= (1 << NFTNL_SET_DESC_CONCAT);
644static int nftnl_set_desc_parse(
struct nftnl_set *s,
const struct nlattr *attr)
646 return mnl_attr_parse_nested(attr, nftnl_set_desc_parse_attr_cb, s);
649EXPORT_SYMBOL(nftnl_set_nlmsg_parse);
650int nftnl_set_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
652 struct nlattr *tb[NFTA_SET_MAX+1] = {};
653 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
654 struct nftnl_expr *expr, *next;
657 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
660 if (nftnl_parse_str_attr(tb[NFTA_SET_TABLE], NFTNL_SET_TABLE,
661 &s->table, &s->flags) < 0)
663 if (nftnl_parse_str_attr(tb[NFTA_SET_NAME], NFTNL_SET_NAME,
664 &s->name, &s->flags) < 0)
666 if (tb[NFTA_SET_HANDLE]) {
667 s->handle = be64toh(mnl_attr_get_u64(tb[NFTA_SET_HANDLE]));
668 s->flags |= (1 << NFTNL_SET_HANDLE);
670 if (tb[NFTA_SET_FLAGS]) {
671 s->set_flags = ntohl(mnl_attr_get_u32(tb[NFTA_SET_FLAGS]));
672 s->flags |= (1 << NFTNL_SET_FLAGS);
674 if (tb[NFTA_SET_KEY_TYPE]) {
675 s->key_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_TYPE]));
676 s->flags |= (1 << NFTNL_SET_KEY_TYPE);
678 if (tb[NFTA_SET_KEY_LEN]) {
679 s->key_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_LEN]));
680 s->flags |= (1 << NFTNL_SET_KEY_LEN);
682 if (tb[NFTA_SET_DATA_TYPE]) {
683 s->data_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_TYPE]));
684 s->flags |= (1 << NFTNL_SET_DATA_TYPE);
686 if (tb[NFTA_SET_DATA_LEN]) {
687 s->data_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_LEN]));
688 s->flags |= (1 << NFTNL_SET_DATA_LEN);
690 if (tb[NFTA_SET_OBJ_TYPE]) {
691 s->obj_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_OBJ_TYPE]));
692 s->flags |= (1 << NFTNL_SET_OBJ_TYPE);
694 if (tb[NFTA_SET_ID]) {
695 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ID]));
696 s->flags |= (1 << NFTNL_SET_ID);
698 if (tb[NFTA_SET_POLICY]) {
699 s->policy = ntohl(mnl_attr_get_u32(tb[NFTA_SET_POLICY]));
700 s->flags |= (1 << NFTNL_SET_POLICY);
702 if (tb[NFTA_SET_TIMEOUT]) {
703 s->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_TIMEOUT]));
704 s->flags |= (1 << NFTNL_SET_TIMEOUT);
706 if (tb[NFTA_SET_GC_INTERVAL]) {
707 s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
708 s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
710 if (tb[NFTA_SET_USERDATA]) {
711 ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
712 mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
713 mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
717 if (tb[NFTA_SET_DESC]) {
718 ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
722 if (tb[NFTA_SET_EXPR]) {
723 expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
727 list_add(&expr->head, &s->expr_list);
728 s->flags |= (1 << NFTNL_SET_EXPR);
729 }
else if (tb[NFTA_SET_EXPRESSIONS]) {
732 mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) {
733 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
736 expr = nftnl_expr_parse(attr);
740 list_add_tail(&expr->head, &s->expr_list);
742 s->flags |= (1 << NFTNL_SET_EXPRESSIONS);
745 if (tb[NFTA_SET_TYPE]) {
747 s->type = strdup(mnl_attr_get_str(tb[NFTA_SET_TYPE]));
750 if (tb[NFTA_SET_COUNT]) {
751 s->elemcount = ntohl(mnl_attr_get_u32(tb[NFTA_SET_COUNT]));
752 s->flags |= (1 << NFTNL_SET_COUNT);
755 s->family = nfg->nfgen_family;
756 s->flags |= (1 << NFTNL_SET_FAMILY);
760 list_for_each_entry_safe(expr, next, &s->expr_list, head) {
761 list_del(&expr->head);
762 nftnl_expr_free(expr);
768EXPORT_SYMBOL(nftnl_set_parse);
769int nftnl_set_parse(
struct nftnl_set *s,
enum nftnl_parse_type type,
770 const char *data,
struct nftnl_parse_err *err)
777EXPORT_SYMBOL(nftnl_set_parse_file);
778int nftnl_set_parse_file(
struct nftnl_set *s,
enum nftnl_parse_type type,
779 FILE *fp,
struct nftnl_parse_err *err)
786static int nftnl_set_snprintf_default(
char *buf,
size_t remain,
787 const struct nftnl_set *s,
788 uint32_t type, uint32_t flags)
790 struct nftnl_set_elem *elem;
793 ret = snprintf(buf, remain,
"%s %s %x",
794 s->name, s->table, s->set_flags);
795 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
797 if (s->flags & (1 << NFTNL_SET_TIMEOUT)) {
798 ret = snprintf(buf + offset, remain,
" timeout %"PRIu64
"ms",
800 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
803 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL)) {
804 ret = snprintf(buf + offset, remain,
" gc_interval %ums",
806 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
809 if (s->flags & (1 << NFTNL_SET_POLICY)) {
810 ret = snprintf(buf + offset, remain,
" policy %u", s->policy);
811 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
814 if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
815 ret = snprintf(buf + offset, remain,
" size %u", s->desc.size);
816 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
820 ret = snprintf(buf + offset, remain,
" backend %s", s->type);
821 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
825 ret = snprintf(buf + offset, remain,
" count %u", s->elemcount);
826 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
830 if (list_empty(&s->element_list))
833 ret = snprintf(buf + offset, remain,
"\n");
834 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
836 list_for_each_entry(elem, &s->element_list, head) {
837 ret = snprintf(buf + offset, remain,
"\t");
838 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
840 ret = nftnl_set_elem_snprintf_default(buf + offset, remain,
842 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
848static int nftnl_set_cmd_snprintf(
char *buf,
size_t remain,
849 const struct nftnl_set *s, uint32_t cmd,
850 uint32_t type, uint32_t flags)
852 uint32_t inner_flags = flags;
855 if (type != NFTNL_OUTPUT_DEFAULT)
859 inner_flags &= ~NFTNL_OF_EVENT_ANY;
861 ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
863 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
867EXPORT_SYMBOL(nftnl_set_snprintf);
868int nftnl_set_snprintf(
char *buf,
size_t size,
const struct nftnl_set *s,
869 uint32_t type, uint32_t flags)
874 return nftnl_set_cmd_snprintf(buf, size, s, nftnl_flag2cmd(flags), type,
878static int nftnl_set_do_snprintf(
char *buf,
size_t size,
const void *s,
879 uint32_t cmd, uint32_t type, uint32_t flags)
881 return nftnl_set_snprintf(buf, size, s, type, flags);
884EXPORT_SYMBOL(nftnl_set_fprintf);
885int nftnl_set_fprintf(FILE *fp,
const struct nftnl_set *s, uint32_t type,
888 return nftnl_fprintf(fp, s, NFTNL_CMD_UNSPEC, type, flags,
889 nftnl_set_do_snprintf);
892EXPORT_SYMBOL(nftnl_set_elem_add);
893void nftnl_set_elem_add(
struct nftnl_set *s,
struct nftnl_set_elem *elem)
895 list_add_tail(&elem->head, &s->element_list);
898#define SET_NAME_HSIZE 512
901 struct list_head list;
902 struct hlist_head name_hash[SET_NAME_HSIZE];
905EXPORT_SYMBOL(nftnl_set_list_alloc);
915 INIT_LIST_HEAD(&list->list);
916 for (i = 0; i < SET_NAME_HSIZE; i++)
917 INIT_HLIST_HEAD(&list->name_hash[i]);
922EXPORT_SYMBOL(nftnl_set_list_free);
925 struct nftnl_set *s, *tmp;
927 list_for_each_entry_safe(s, tmp, &list->list, head) {
929 hlist_del(&s->hnode);
935EXPORT_SYMBOL(nftnl_set_list_is_empty);
938 return list_empty(&list->list);
941static uint32_t djb_hash(
const char *key)
943 uint32_t i, hash = 5381;
945 for (i = 0; i < strlen(key); i++)
946 hash = ((hash << 5) + hash) + key[i];
951EXPORT_SYMBOL(nftnl_set_list_add);
952void nftnl_set_list_add(
struct nftnl_set *s,
struct nftnl_set_list *list)
954 int key = djb_hash(s->name) % SET_NAME_HSIZE;
956 hlist_add_head(&s->hnode, &list->name_hash[key]);
957 list_add(&s->head, &list->list);
960EXPORT_SYMBOL(nftnl_set_list_add_tail);
961void nftnl_set_list_add_tail(
struct nftnl_set *s,
struct nftnl_set_list *list)
963 int key = djb_hash(s->name) % SET_NAME_HSIZE;
965 hlist_add_head(&s->hnode, &list->name_hash[key]);
966 list_add_tail(&s->head, &list->list);
969EXPORT_SYMBOL(nftnl_set_list_del);
970void nftnl_set_list_del(
struct nftnl_set *s)
973 hlist_del(&s->hnode);
976EXPORT_SYMBOL(nftnl_set_list_foreach);
978 int (*cb)(
struct nftnl_set *t,
void *data),
void *data)
980 struct nftnl_set *cur, *tmp;
983 list_for_each_entry_safe(cur, tmp, &set_list->list, head) {
993 struct nftnl_set *cur;
996EXPORT_SYMBOL(nftnl_set_list_iter_create);
1007 if (nftnl_set_list_is_empty(l))
1010 iter->cur = list_entry(l->list.next,
struct nftnl_set, head);
1015EXPORT_SYMBOL(nftnl_set_list_iter_cur);
1022EXPORT_SYMBOL(nftnl_set_list_iter_next);
1025 struct nftnl_set *s = iter->cur;
1031 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set, head);
1032 if (&iter->cur->head == iter->list->list.next)
1038EXPORT_SYMBOL(nftnl_set_list_iter_destroy);
1044EXPORT_SYMBOL(nftnl_set_list_lookup_byname);
1046nftnl_set_list_lookup_byname(
struct nftnl_set_list *set_list,
const char *set)
1048 int key = djb_hash(set) % SET_NAME_HSIZE;
1049 struct hlist_node *n;
1050 struct nftnl_set *s;
1052 hlist_for_each_entry(s, n, &set_list->name_hash[key], hnode) {
1053 if (!strcmp(set, s->name))
1059int nftnl_set_lookup_id(
struct nftnl_expr *e,
1062 const char *set_name;
1063 struct nftnl_set *s;
1065 set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
1066 if (set_name == NULL)
1069 s = nftnl_set_list_lookup_byname(set_list, set_name);
1073 *set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);