19 #include <netinet/in.h>
23 #include <libmnl/libmnl.h>
24 #include <linux/netfilter/nfnetlink.h>
25 #include <linux/netfilter/nf_tables.h>
27 #include <libnftnl/set.h>
28 #include <libnftnl/expr.h>
30 EXPORT_SYMBOL(nftnl_set_alloc);
31 struct nftnl_set *nftnl_set_alloc(
void)
35 s = calloc(1,
sizeof(
struct nftnl_set));
39 INIT_LIST_HEAD(&s->element_list);
40 INIT_LIST_HEAD(&s->expr_list);
44 EXPORT_SYMBOL(nftnl_set_free);
45 void nftnl_set_free(
const struct nftnl_set *s)
47 struct nftnl_set_elem *elem, *tmp;
48 struct nftnl_expr *expr, *next;
50 if (s->flags & (1 << NFTNL_SET_TABLE))
52 if (s->flags & (1 << NFTNL_SET_NAME))
54 if (s->flags & (1 << NFTNL_SET_USERDATA))
57 list_for_each_entry_safe(expr, next, &s->expr_list, head) {
58 list_del(&expr->head);
59 nftnl_expr_free(expr);
62 list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
63 list_del(&elem->head);
64 nftnl_set_elem_free(elem);
69 EXPORT_SYMBOL(nftnl_set_is_set);
70 bool nftnl_set_is_set(
const struct nftnl_set *s, uint16_t attr)
72 return s->flags & (1 << attr);
75 EXPORT_SYMBOL(nftnl_set_unset);
76 void nftnl_set_unset(
struct nftnl_set *s, uint16_t attr)
78 struct nftnl_expr *expr, *tmp;
80 if (!(s->flags & (1 << attr)))
90 case NFTNL_SET_HANDLE:
92 case NFTNL_SET_KEY_TYPE:
93 case NFTNL_SET_KEY_LEN:
94 case NFTNL_SET_DATA_TYPE:
95 case NFTNL_SET_DATA_LEN:
96 case NFTNL_SET_OBJ_TYPE:
97 case NFTNL_SET_FAMILY:
99 case NFTNL_SET_POLICY:
100 case NFTNL_SET_DESC_SIZE:
101 case NFTNL_SET_DESC_CONCAT:
102 case NFTNL_SET_TIMEOUT:
103 case NFTNL_SET_GC_INTERVAL:
105 case NFTNL_SET_USERDATA:
109 case NFTNL_SET_EXPRESSIONS:
110 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
111 list_del(&expr->head);
112 nftnl_expr_free(expr);
119 s->flags &= ~(1 << attr);
122 static uint32_t nftnl_set_validate[NFTNL_SET_MAX + 1] = {
123 [NFTNL_SET_HANDLE] =
sizeof(uint64_t),
124 [NFTNL_SET_FLAGS] =
sizeof(uint32_t),
125 [NFTNL_SET_KEY_TYPE] =
sizeof(uint32_t),
126 [NFTNL_SET_KEY_LEN] =
sizeof(uint32_t),
127 [NFTNL_SET_DATA_TYPE] =
sizeof(uint32_t),
128 [NFTNL_SET_DATA_LEN] =
sizeof(uint32_t),
129 [NFTNL_SET_OBJ_TYPE] =
sizeof(uint32_t),
130 [NFTNL_SET_FAMILY] =
sizeof(uint32_t),
131 [NFTNL_SET_ID] =
sizeof(uint32_t),
132 [NFTNL_SET_POLICY] =
sizeof(uint32_t),
133 [NFTNL_SET_DESC_SIZE] =
sizeof(uint32_t),
134 [NFTNL_SET_TIMEOUT] =
sizeof(uint64_t),
135 [NFTNL_SET_GC_INTERVAL] =
sizeof(uint32_t),
138 EXPORT_SYMBOL(nftnl_set_set_data);
139 int 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 while (s->desc.field_len[++s->desc.field_count]) {
193 if (s->desc.field_count >= NFT_REG32_COUNT)
197 case NFTNL_SET_TIMEOUT:
198 memcpy(&s->timeout, data,
sizeof(s->timeout));
200 case NFTNL_SET_GC_INTERVAL:
201 memcpy(&s->gc_interval, data,
sizeof(s->gc_interval));
203 case NFTNL_SET_USERDATA:
204 if (s->flags & (1 << NFTNL_SET_USERDATA))
207 s->user.data = malloc(data_len);
210 memcpy(s->user.data, data, data_len);
211 s->user.len = data_len;
214 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
215 list_del(&expr->head);
216 nftnl_expr_free(expr);
220 list_add(&expr->head, &s->expr_list);
223 s->flags |= (1 << attr);
227 int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data) __visible;
228 int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data)
230 return nftnl_set_set_data(s, attr, data, nftnl_set_validate[attr]);
233 EXPORT_SYMBOL(nftnl_set_set_u32);
234 void nftnl_set_set_u32(
struct nftnl_set *s, uint16_t attr, uint32_t val)
236 nftnl_set_set_data(s, attr, &val,
sizeof(uint32_t));
239 EXPORT_SYMBOL(nftnl_set_set_u64);
240 void nftnl_set_set_u64(
struct nftnl_set *s, uint16_t attr, uint64_t val)
242 nftnl_set_set_data(s, attr, &val,
sizeof(uint64_t));
245 EXPORT_SYMBOL(nftnl_set_set_str);
246 int nftnl_set_set_str(
struct nftnl_set *s, uint16_t attr,
const char *str)
248 return nftnl_set_set_data(s, attr, str, strlen(str) + 1);
251 EXPORT_SYMBOL(nftnl_set_get_data);
252 const void *nftnl_set_get_data(
const struct nftnl_set *s, uint16_t attr,
255 struct nftnl_expr *expr;
257 if (!(s->flags & (1 << attr)))
261 case NFTNL_SET_TABLE:
262 *data_len = strlen(s->table) + 1;
265 *data_len = strlen(s->name) + 1;
267 case NFTNL_SET_HANDLE:
268 *data_len =
sizeof(uint64_t);
270 case NFTNL_SET_FLAGS:
271 *data_len =
sizeof(uint32_t);
272 return &s->set_flags;
273 case NFTNL_SET_KEY_TYPE:
274 *data_len =
sizeof(uint32_t);
276 case NFTNL_SET_KEY_LEN:
277 *data_len =
sizeof(uint32_t);
279 case NFTNL_SET_DATA_TYPE:
280 *data_len =
sizeof(uint32_t);
281 return &s->data_type;
282 case NFTNL_SET_DATA_LEN:
283 *data_len =
sizeof(uint32_t);
285 case NFTNL_SET_OBJ_TYPE:
286 *data_len =
sizeof(uint32_t);
288 case NFTNL_SET_FAMILY:
289 *data_len =
sizeof(uint32_t);
292 *data_len =
sizeof(uint32_t);
294 case NFTNL_SET_POLICY:
295 *data_len =
sizeof(uint32_t);
297 case NFTNL_SET_DESC_SIZE:
298 *data_len =
sizeof(uint32_t);
299 return &s->desc.size;
300 case NFTNL_SET_DESC_CONCAT:
301 *data_len = s->desc.field_count;
302 return s->desc.field_len;
303 case NFTNL_SET_TIMEOUT:
304 *data_len =
sizeof(uint64_t);
306 case NFTNL_SET_GC_INTERVAL:
307 *data_len =
sizeof(uint32_t);
308 return &s->gc_interval;
309 case NFTNL_SET_USERDATA:
310 *data_len = s->user.len;
313 list_for_each_entry(expr, &s->expr_list, head)
320 EXPORT_SYMBOL(nftnl_set_get);
321 const
void *nftnl_set_get(const struct nftnl_set *s, uint16_t attr)
324 return nftnl_set_get_data(s, attr, &data_len);
327 EXPORT_SYMBOL(nftnl_set_get_str);
328 const char *nftnl_set_get_str(
const struct nftnl_set *s, uint16_t attr)
330 return nftnl_set_get(s, attr);
333 EXPORT_SYMBOL(nftnl_set_get_u32);
334 uint32_t nftnl_set_get_u32(
const struct nftnl_set *s, uint16_t attr)
337 const uint32_t *val = nftnl_set_get_data(s, attr, &data_len);
339 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
341 return val ? *val : 0;
344 EXPORT_SYMBOL(nftnl_set_get_u64);
345 uint64_t nftnl_set_get_u64(
const struct nftnl_set *s, uint16_t attr)
348 const uint64_t *val = nftnl_set_get_data(s, attr, &data_len);
350 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
352 return val ? *val : 0;
355 struct nftnl_set *nftnl_set_clone(
const struct nftnl_set *set)
357 struct nftnl_set *newset;
358 struct nftnl_set_elem *elem, *newelem;
360 newset = nftnl_set_alloc();
364 memcpy(newset, set,
sizeof(*set));
366 if (set->flags & (1 << NFTNL_SET_TABLE)) {
367 newset->table = strdup(set->table);
371 if (set->flags & (1 << NFTNL_SET_NAME)) {
372 newset->name = strdup(set->name);
377 INIT_LIST_HEAD(&newset->element_list);
378 list_for_each_entry(elem, &set->element_list, head) {
379 newelem = nftnl_set_elem_clone(elem);
383 list_add_tail(&newelem->head, &newset->element_list);
388 nftnl_set_free(newset);
392 static void nftnl_set_nlmsg_build_desc_size_payload(
struct nlmsghdr *nlh,
395 mnl_attr_put_u32(nlh, NFTA_SET_DESC_SIZE, htonl(s->desc.size));
398 static void nftnl_set_nlmsg_build_desc_concat_payload(
struct nlmsghdr *nlh,
404 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC_CONCAT);
405 for (i = 0; i < NFT_REG32_COUNT && i < s->desc.field_count; i++) {
406 struct nlattr *nest_elem;
408 nest_elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
409 mnl_attr_put_u32(nlh, NFTA_SET_FIELD_LEN,
410 htonl(s->desc.field_len[i]));
411 mnl_attr_nest_end(nlh, nest_elem);
413 mnl_attr_nest_end(nlh, nest);
417 nftnl_set_nlmsg_build_desc_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
421 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC);
423 if (s->flags & (1 << NFTNL_SET_DESC_SIZE))
424 nftnl_set_nlmsg_build_desc_size_payload(nlh, s);
425 if (s->flags & (1 << NFTNL_SET_DESC_CONCAT))
426 nftnl_set_nlmsg_build_desc_concat_payload(nlh, s);
428 mnl_attr_nest_end(nlh, nest);
431 EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
432 void nftnl_set_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
436 if (s->flags & (1 << NFTNL_SET_TABLE))
437 mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
438 if (s->flags & (1 << NFTNL_SET_NAME))
439 mnl_attr_put_strz(nlh, NFTA_SET_NAME, s->name);
440 if (s->flags & (1 << NFTNL_SET_HANDLE))
441 mnl_attr_put_u64(nlh, NFTA_SET_HANDLE, htobe64(s->handle));
442 if (s->flags & (1 << NFTNL_SET_FLAGS))
443 mnl_attr_put_u32(nlh, NFTA_SET_FLAGS, htonl(s->set_flags));
444 if (s->flags & (1 << NFTNL_SET_KEY_TYPE))
445 mnl_attr_put_u32(nlh, NFTA_SET_KEY_TYPE, htonl(s->key_type));
446 if (s->flags & (1 << NFTNL_SET_KEY_LEN))
447 mnl_attr_put_u32(nlh, NFTA_SET_KEY_LEN, htonl(s->key_len));
449 if (s->flags & (1 << NFTNL_SET_DATA_TYPE))
450 mnl_attr_put_u32(nlh, NFTA_SET_DATA_TYPE, htonl(s->data_type));
451 if (s->flags & (1 << NFTNL_SET_DATA_LEN))
452 mnl_attr_put_u32(nlh, NFTA_SET_DATA_LEN, htonl(s->data_len));
453 if (s->flags & (1 << NFTNL_SET_OBJ_TYPE))
454 mnl_attr_put_u32(nlh, NFTA_SET_OBJ_TYPE, htonl(s->obj_type));
455 if (s->flags & (1 << NFTNL_SET_ID))
456 mnl_attr_put_u32(nlh, NFTA_SET_ID, htonl(s->id));
457 if (s->flags & (1 << NFTNL_SET_POLICY))
458 mnl_attr_put_u32(nlh, NFTA_SET_POLICY, htonl(s->policy));
459 if (s->flags & (1 << NFTNL_SET_DESC_SIZE | 1 << NFTNL_SET_DESC_CONCAT))
460 nftnl_set_nlmsg_build_desc_payload(nlh, s);
461 if (s->flags & (1 << NFTNL_SET_TIMEOUT))
462 mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
463 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
464 mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
465 if (s->flags & (1 << NFTNL_SET_USERDATA))
466 mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
467 if (!list_empty(&s->expr_list)) {
468 struct nftnl_expr *expr;
470 list_for_each_entry(expr, &s->expr_list, head)
473 if (num_exprs == 1) {
474 struct nlattr *nest1;
476 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
477 list_for_each_entry(expr, &s->expr_list, head)
478 nftnl_expr_build_payload(nlh, expr);
480 mnl_attr_nest_end(nlh, nest1);
481 } else if (num_exprs > 1) {
482 struct nlattr *nest1, *nest2;
484 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS);
485 list_for_each_entry(expr, &s->expr_list, head) {
486 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
487 nftnl_expr_build_payload(nlh, expr);
488 mnl_attr_nest_end(nlh, nest2);
490 mnl_attr_nest_end(nlh, nest1);
495 EXPORT_SYMBOL(nftnl_set_add_expr);
496 void nftnl_set_add_expr(
struct nftnl_set *s,
struct nftnl_expr *expr)
498 list_add_tail(&expr->head, &s->expr_list);
501 EXPORT_SYMBOL(nftnl_set_expr_foreach);
502 int nftnl_set_expr_foreach(
const struct nftnl_set *s,
503 int (*cb)(
struct nftnl_expr *e,
void *data),
506 struct nftnl_expr *cur, *tmp;
509 list_for_each_entry_safe(cur, tmp, &s->expr_list, head) {
517 static int nftnl_set_parse_attr_cb(
const struct nlattr *attr,
void *data)
519 const struct nlattr **tb = data;
520 int type = mnl_attr_get_type(attr);
522 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
528 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
531 case NFTA_SET_HANDLE:
532 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
536 case NFTA_SET_KEY_TYPE:
537 case NFTA_SET_KEY_LEN:
538 case NFTA_SET_DATA_TYPE:
539 case NFTA_SET_DATA_LEN:
541 case NFTA_SET_POLICY:
542 case NFTA_SET_GC_INTERVAL:
543 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
546 case NFTA_SET_USERDATA:
547 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
550 case NFTA_SET_TIMEOUT:
551 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
556 case NFTA_SET_EXPRESSIONS:
557 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
567 nftnl_set_desc_concat_field_parse_attr_cb(
const struct nlattr *attr,
void *data)
569 int type = mnl_attr_get_type(attr);
570 struct nftnl_set *s = data;
572 if (type != NFTA_SET_FIELD_LEN)
575 if (mnl_attr_validate(attr, MNL_TYPE_U32))
578 s->desc.field_len[s->desc.field_count] = ntohl(mnl_attr_get_u32(attr));
579 s->desc.field_count++;
585 nftnl_set_desc_concat_parse_attr_cb(
const struct nlattr *attr,
void *data)
587 int type = mnl_attr_get_type(attr);
588 struct nftnl_set *s = data;
590 if (type != NFTA_LIST_ELEM)
593 return mnl_attr_parse_nested(attr,
594 nftnl_set_desc_concat_field_parse_attr_cb,
598 static int nftnl_set_desc_parse_attr_cb(
const struct nlattr *attr,
void *data)
600 int type = mnl_attr_get_type(attr), err;
601 struct nftnl_set *s = data;
603 if (mnl_attr_type_valid(attr, NFTA_SET_DESC_MAX) < 0)
607 case NFTA_SET_DESC_SIZE:
608 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
613 s->desc.size = ntohl(mnl_attr_get_u32(attr));
614 s->flags |= (1 << NFTNL_SET_DESC_SIZE);
616 case NFTA_SET_DESC_CONCAT:
617 err = mnl_attr_parse_nested(attr,
618 nftnl_set_desc_concat_parse_attr_cb,
620 if (err != MNL_CB_OK)
623 s->flags |= (1 << NFTNL_SET_DESC_CONCAT);
632 static int nftnl_set_desc_parse(
struct nftnl_set *s,
const struct nlattr *attr)
634 return mnl_attr_parse_nested(attr, nftnl_set_desc_parse_attr_cb, s);
637 EXPORT_SYMBOL(nftnl_set_nlmsg_parse);
638 int nftnl_set_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
640 struct nlattr *tb[NFTA_SET_MAX+1] = {};
641 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
642 struct nftnl_expr *expr, *next;
645 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
648 if (tb[NFTA_SET_TABLE]) {
649 if (s->flags & (1 << NFTNL_SET_TABLE))
651 s->table = strdup(mnl_attr_get_str(tb[NFTA_SET_TABLE]));
654 s->flags |= (1 << NFTNL_SET_TABLE);
656 if (tb[NFTA_SET_NAME]) {
657 if (s->flags & (1 << NFTNL_SET_NAME))
659 s->name = strdup(mnl_attr_get_str(tb[NFTA_SET_NAME]));
662 s->flags |= (1 << NFTNL_SET_NAME);
664 if (tb[NFTA_SET_HANDLE]) {
665 s->handle = be64toh(mnl_attr_get_u64(tb[NFTA_SET_HANDLE]));
666 s->flags |= (1 << NFTNL_SET_HANDLE);
668 if (tb[NFTA_SET_FLAGS]) {
669 s->set_flags = ntohl(mnl_attr_get_u32(tb[NFTA_SET_FLAGS]));
670 s->flags |= (1 << NFTNL_SET_FLAGS);
672 if (tb[NFTA_SET_KEY_TYPE]) {
673 s->key_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_TYPE]));
674 s->flags |= (1 << NFTNL_SET_KEY_TYPE);
676 if (tb[NFTA_SET_KEY_LEN]) {
677 s->key_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_LEN]));
678 s->flags |= (1 << NFTNL_SET_KEY_LEN);
680 if (tb[NFTA_SET_DATA_TYPE]) {
681 s->data_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_TYPE]));
682 s->flags |= (1 << NFTNL_SET_DATA_TYPE);
684 if (tb[NFTA_SET_DATA_LEN]) {
685 s->data_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_LEN]));
686 s->flags |= (1 << NFTNL_SET_DATA_LEN);
688 if (tb[NFTA_SET_OBJ_TYPE]) {
689 s->obj_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_OBJ_TYPE]));
690 s->flags |= (1 << NFTNL_SET_OBJ_TYPE);
692 if (tb[NFTA_SET_ID]) {
693 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ID]));
694 s->flags |= (1 << NFTNL_SET_ID);
696 if (tb[NFTA_SET_POLICY]) {
697 s->policy = ntohl(mnl_attr_get_u32(tb[NFTA_SET_POLICY]));
698 s->flags |= (1 << NFTNL_SET_POLICY);
700 if (tb[NFTA_SET_TIMEOUT]) {
701 s->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_TIMEOUT]));
702 s->flags |= (1 << NFTNL_SET_TIMEOUT);
704 if (tb[NFTA_SET_GC_INTERVAL]) {
705 s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
706 s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
708 if (tb[NFTA_SET_USERDATA]) {
709 ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
710 mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
711 mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
715 if (tb[NFTA_SET_DESC]) {
716 ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
720 if (tb[NFTA_SET_EXPR]) {
721 expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
725 list_add(&expr->head, &s->expr_list);
726 s->flags |= (1 << NFTNL_SET_EXPR);
727 }
else if (tb[NFTA_SET_EXPRESSIONS]) {
730 mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) {
731 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
734 expr = nftnl_expr_parse(attr);
738 list_add_tail(&expr->head, &s->expr_list);
740 s->flags |= (1 << NFTNL_SET_EXPRESSIONS);
743 s->family = nfg->nfgen_family;
744 s->flags |= (1 << NFTNL_SET_FAMILY);
748 list_for_each_entry_safe(expr, next, &s->expr_list, head) {
749 list_del(&expr->head);
750 nftnl_expr_free(expr);
756 EXPORT_SYMBOL(nftnl_set_parse);
757 int nftnl_set_parse(
struct nftnl_set *s,
enum nftnl_parse_type type,
758 const char *data,
struct nftnl_parse_err *err)
765 EXPORT_SYMBOL(nftnl_set_parse_file);
766 int nftnl_set_parse_file(
struct nftnl_set *s,
enum nftnl_parse_type type,
767 FILE *fp,
struct nftnl_parse_err *err)
774 static int nftnl_set_snprintf_default(
char *buf,
size_t remain,
775 const struct nftnl_set *s,
776 uint32_t type, uint32_t flags)
778 struct nftnl_set_elem *elem;
781 ret = snprintf(buf, remain,
"%s %s %x",
782 s->name, s->table, s->set_flags);
783 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
785 if (s->flags & (1 << NFTNL_SET_TIMEOUT)) {
786 ret = snprintf(buf + offset, remain,
" timeout %"PRIu64
"ms",
788 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
791 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL)) {
792 ret = snprintf(buf + offset, remain,
" gc_interval %ums",
794 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
797 if (s->flags & (1 << NFTNL_SET_POLICY)) {
798 ret = snprintf(buf + offset, remain,
" policy %u", s->policy);
799 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
802 if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
803 ret = snprintf(buf + offset, remain,
" size %u", s->desc.size);
804 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
808 if (list_empty(&s->element_list))
811 ret = snprintf(buf + offset, remain,
"\n");
812 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
814 list_for_each_entry(elem, &s->element_list, head) {
815 ret = snprintf(buf + offset, remain,
"\t");
816 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
818 ret = nftnl_set_elem_snprintf_default(buf + offset, remain,
820 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
826 static int nftnl_set_cmd_snprintf(
char *buf,
size_t remain,
827 const struct nftnl_set *s, uint32_t cmd,
828 uint32_t type, uint32_t flags)
830 uint32_t inner_flags = flags;
833 if (type != NFTNL_OUTPUT_DEFAULT)
837 inner_flags &= ~NFTNL_OF_EVENT_ANY;
839 ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
841 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
845 EXPORT_SYMBOL(nftnl_set_snprintf);
846 int nftnl_set_snprintf(
char *buf,
size_t size,
const struct nftnl_set *s,
847 uint32_t type, uint32_t flags)
852 return nftnl_set_cmd_snprintf(buf, size, s, nftnl_flag2cmd(flags), type,
856 static int nftnl_set_do_snprintf(
char *buf,
size_t size,
const void *s,
857 uint32_t cmd, uint32_t type, uint32_t flags)
859 return nftnl_set_snprintf(buf, size, s, type, flags);
862 EXPORT_SYMBOL(nftnl_set_fprintf);
863 int nftnl_set_fprintf(FILE *fp,
const struct nftnl_set *s, uint32_t type,
866 return nftnl_fprintf(fp, s, NFTNL_CMD_UNSPEC, type, flags,
867 nftnl_set_do_snprintf);
870 EXPORT_SYMBOL(nftnl_set_elem_add);
871 void nftnl_set_elem_add(
struct nftnl_set *s,
struct nftnl_set_elem *elem)
873 list_add_tail(&elem->head, &s->element_list);
876 #define SET_NAME_HSIZE 512
879 struct list_head list;
880 struct hlist_head name_hash[SET_NAME_HSIZE];
883 EXPORT_SYMBOL(nftnl_set_list_alloc);
893 INIT_LIST_HEAD(&list->list);
894 for (i = 0; i < SET_NAME_HSIZE; i++)
895 INIT_HLIST_HEAD(&list->name_hash[i]);
900 EXPORT_SYMBOL(nftnl_set_list_free);
903 struct nftnl_set *s, *tmp;
905 list_for_each_entry_safe(s, tmp, &list->list, head) {
907 hlist_del(&s->hnode);
913 EXPORT_SYMBOL(nftnl_set_list_is_empty);
916 return list_empty(&list->list);
919 static uint32_t djb_hash(
const char *key)
921 uint32_t i, hash = 5381;
923 for (i = 0; i < strlen(key); i++)
924 hash = ((hash << 5) + hash) + key[i];
929 EXPORT_SYMBOL(nftnl_set_list_add);
930 void nftnl_set_list_add(
struct nftnl_set *s,
struct nftnl_set_list *list)
932 int key = djb_hash(s->name) % SET_NAME_HSIZE;
934 hlist_add_head(&s->hnode, &list->name_hash[key]);
935 list_add(&s->head, &list->list);
938 EXPORT_SYMBOL(nftnl_set_list_add_tail);
939 void nftnl_set_list_add_tail(
struct nftnl_set *s,
struct nftnl_set_list *list)
941 int key = djb_hash(s->name) % SET_NAME_HSIZE;
943 hlist_add_head(&s->hnode, &list->name_hash[key]);
944 list_add_tail(&s->head, &list->list);
947 EXPORT_SYMBOL(nftnl_set_list_del);
948 void nftnl_set_list_del(
struct nftnl_set *s)
951 hlist_del(&s->hnode);
954 EXPORT_SYMBOL(nftnl_set_list_foreach);
956 int (*cb)(
struct nftnl_set *t,
void *data),
void *data)
958 struct nftnl_set *cur, *tmp;
961 list_for_each_entry_safe(cur, tmp, &set_list->list, head) {
971 struct nftnl_set *cur;
974 EXPORT_SYMBOL(nftnl_set_list_iter_create);
985 if (nftnl_set_list_is_empty(l))
988 iter->cur = list_entry(l->list.next,
struct nftnl_set, head);
993 EXPORT_SYMBOL(nftnl_set_list_iter_cur);
1000 EXPORT_SYMBOL(nftnl_set_list_iter_next);
1003 struct nftnl_set *s = iter->cur;
1009 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set, head);
1010 if (&iter->cur->head == iter->list->list.next)
1016 EXPORT_SYMBOL(nftnl_set_list_iter_destroy);
1022 EXPORT_SYMBOL(nftnl_set_list_lookup_byname);
1024 nftnl_set_list_lookup_byname(
struct nftnl_set_list *set_list,
const char *set)
1026 int key = djb_hash(set) % SET_NAME_HSIZE;
1027 struct hlist_node *n;
1028 struct nftnl_set *s;
1030 hlist_for_each_entry(s, n, &set_list->name_hash[key], hnode) {
1031 if (!strcmp(set, s->name))
1037 int nftnl_set_lookup_id(
struct nftnl_expr *e,
1040 const char *set_name;
1041 struct nftnl_set *s;
1043 set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
1044 if (set_name == NULL)
1047 s = nftnl_set_list_lookup_byname(set_list, set_name);
1051 *set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);