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);
65EXPORT_SYMBOL(nftnl_set_is_set);
66bool nftnl_set_is_set(
const struct nftnl_set *s, uint16_t attr)
68 return s->flags & (1 << attr);
71EXPORT_SYMBOL(nftnl_set_unset);
72void nftnl_set_unset(
struct nftnl_set *s, uint16_t attr)
74 struct nftnl_expr *expr, *tmp;
76 if (!(s->flags & (1 << attr)))
86 case NFTNL_SET_HANDLE:
88 case NFTNL_SET_KEY_TYPE:
89 case NFTNL_SET_KEY_LEN:
90 case NFTNL_SET_DATA_TYPE:
91 case NFTNL_SET_DATA_LEN:
92 case NFTNL_SET_OBJ_TYPE:
93 case NFTNL_SET_FAMILY:
95 case NFTNL_SET_POLICY:
96 case NFTNL_SET_DESC_SIZE:
97 case NFTNL_SET_DESC_CONCAT:
98 case NFTNL_SET_TIMEOUT:
99 case NFTNL_SET_GC_INTERVAL:
101 case NFTNL_SET_USERDATA:
105 case NFTNL_SET_EXPRESSIONS:
106 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
107 list_del(&expr->head);
108 nftnl_expr_free(expr);
115 s->flags &= ~(1 << attr);
118static uint32_t nftnl_set_validate[NFTNL_SET_MAX + 1] = {
119 [NFTNL_SET_HANDLE] =
sizeof(uint64_t),
120 [NFTNL_SET_FLAGS] =
sizeof(uint32_t),
121 [NFTNL_SET_KEY_TYPE] =
sizeof(uint32_t),
122 [NFTNL_SET_KEY_LEN] =
sizeof(uint32_t),
123 [NFTNL_SET_DATA_TYPE] =
sizeof(uint32_t),
124 [NFTNL_SET_DATA_LEN] =
sizeof(uint32_t),
125 [NFTNL_SET_OBJ_TYPE] =
sizeof(uint32_t),
126 [NFTNL_SET_FAMILY] =
sizeof(uint32_t),
127 [NFTNL_SET_ID] =
sizeof(uint32_t),
128 [NFTNL_SET_POLICY] =
sizeof(uint32_t),
129 [NFTNL_SET_DESC_SIZE] =
sizeof(uint32_t),
130 [NFTNL_SET_TIMEOUT] =
sizeof(uint64_t),
131 [NFTNL_SET_GC_INTERVAL] =
sizeof(uint32_t),
134EXPORT_SYMBOL(nftnl_set_set_data);
135int nftnl_set_set_data(
struct nftnl_set *s, uint16_t attr,
const void *data,
138 struct nftnl_expr *expr, *tmp;
140 nftnl_assert_attr_exists(attr, NFTNL_SET_MAX);
141 nftnl_assert_validate(data, nftnl_set_validate, attr, data_len);
144 case NFTNL_SET_TABLE:
145 return nftnl_set_str_attr(&s->table, &s->flags,
146 attr, data, data_len);
148 return nftnl_set_str_attr(&s->name, &s->flags,
149 attr, data, data_len);
150 case NFTNL_SET_HANDLE:
151 memcpy(&s->handle, data,
sizeof(s->handle));
153 case NFTNL_SET_FLAGS:
154 memcpy(&s->set_flags, data,
sizeof(s->set_flags));
156 case NFTNL_SET_KEY_TYPE:
157 memcpy(&s->key_type, data,
sizeof(s->key_type));
159 case NFTNL_SET_KEY_LEN:
160 memcpy(&s->key_len, data,
sizeof(s->key_len));
162 case NFTNL_SET_DATA_TYPE:
163 memcpy(&s->data_type, data,
sizeof(s->data_type));
165 case NFTNL_SET_DATA_LEN:
166 memcpy(&s->data_len, data,
sizeof(s->data_len));
168 case NFTNL_SET_OBJ_TYPE:
169 memcpy(&s->obj_type, data,
sizeof(s->obj_type));
171 case NFTNL_SET_FAMILY:
172 memcpy(&s->family, data,
sizeof(s->family));
175 memcpy(&s->id, data,
sizeof(s->id));
177 case NFTNL_SET_POLICY:
178 memcpy(&s->policy, data,
sizeof(s->policy));
180 case NFTNL_SET_DESC_SIZE:
181 memcpy(&s->desc.size, data,
sizeof(s->desc.size));
183 case NFTNL_SET_DESC_CONCAT:
184 if (data_len >
sizeof(s->desc.field_len))
187 memcpy(&s->desc.field_len, data, data_len);
188 for (s->desc.field_count = 0;
189 s->desc.field_count < NFT_REG32_COUNT;
190 s->desc.field_count++) {
191 if (!s->desc.field_len[s->desc.field_count])
195 case NFTNL_SET_TIMEOUT:
196 memcpy(&s->timeout, data,
sizeof(s->timeout));
198 case NFTNL_SET_GC_INTERVAL:
199 memcpy(&s->gc_interval, data,
sizeof(s->gc_interval));
201 case NFTNL_SET_USERDATA:
202 if (s->flags & (1 << NFTNL_SET_USERDATA))
205 s->user.data = malloc(data_len);
208 memcpy(s->user.data, data, data_len);
209 s->user.len = data_len;
212 list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
213 list_del(&expr->head);
214 nftnl_expr_free(expr);
218 list_add(&expr->head, &s->expr_list);
221 s->flags |= (1 << attr);
225int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data) __visible;
226int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data)
228 return nftnl_set_set_data(s, attr, data, nftnl_set_validate[attr]);
231EXPORT_SYMBOL(nftnl_set_set_u32);
232void nftnl_set_set_u32(
struct nftnl_set *s, uint16_t attr, uint32_t val)
234 nftnl_set_set_data(s, attr, &val,
sizeof(uint32_t));
237EXPORT_SYMBOL(nftnl_set_set_u64);
238void nftnl_set_set_u64(
struct nftnl_set *s, uint16_t attr, uint64_t val)
240 nftnl_set_set_data(s, attr, &val,
sizeof(uint64_t));
243EXPORT_SYMBOL(nftnl_set_set_str);
244int nftnl_set_set_str(
struct nftnl_set *s, uint16_t attr,
const char *str)
246 return nftnl_set_set_data(s, attr, str, strlen(str) + 1);
249EXPORT_SYMBOL(nftnl_set_get_data);
250const void *nftnl_set_get_data(
const struct nftnl_set *s, uint16_t attr,
253 struct nftnl_expr *expr;
255 if (!(s->flags & (1 << attr)))
259 case NFTNL_SET_TABLE:
260 *data_len = strlen(s->table) + 1;
263 *data_len = strlen(s->name) + 1;
265 case NFTNL_SET_HANDLE:
266 *data_len =
sizeof(uint64_t);
268 case NFTNL_SET_FLAGS:
269 *data_len =
sizeof(uint32_t);
270 return &s->set_flags;
271 case NFTNL_SET_KEY_TYPE:
272 *data_len =
sizeof(uint32_t);
274 case NFTNL_SET_KEY_LEN:
275 *data_len =
sizeof(uint32_t);
277 case NFTNL_SET_DATA_TYPE:
278 *data_len =
sizeof(uint32_t);
279 return &s->data_type;
280 case NFTNL_SET_DATA_LEN:
281 *data_len =
sizeof(uint32_t);
283 case NFTNL_SET_OBJ_TYPE:
284 *data_len =
sizeof(uint32_t);
286 case NFTNL_SET_FAMILY:
287 *data_len =
sizeof(uint32_t);
290 *data_len =
sizeof(uint32_t);
292 case NFTNL_SET_POLICY:
293 *data_len =
sizeof(uint32_t);
295 case NFTNL_SET_DESC_SIZE:
296 *data_len =
sizeof(uint32_t);
297 return &s->desc.size;
298 case NFTNL_SET_DESC_CONCAT:
299 *data_len = s->desc.field_count;
300 return s->desc.field_len;
301 case NFTNL_SET_TIMEOUT:
302 *data_len =
sizeof(uint64_t);
304 case NFTNL_SET_GC_INTERVAL:
305 *data_len =
sizeof(uint32_t);
306 return &s->gc_interval;
307 case NFTNL_SET_USERDATA:
308 *data_len = s->user.len;
311 list_for_each_entry(expr, &s->expr_list, head)
318EXPORT_SYMBOL(nftnl_set_get);
319const void *nftnl_set_get(
const struct nftnl_set *s, uint16_t attr)
322 return nftnl_set_get_data(s, attr, &data_len);
325EXPORT_SYMBOL(nftnl_set_get_str);
326const char *nftnl_set_get_str(
const struct nftnl_set *s, uint16_t attr)
328 return nftnl_set_get(s, attr);
331EXPORT_SYMBOL(nftnl_set_get_u32);
332uint32_t nftnl_set_get_u32(
const struct nftnl_set *s, uint16_t attr)
335 const uint32_t *val = nftnl_set_get_data(s, attr, &data_len);
337 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
339 return val ? *val : 0;
342EXPORT_SYMBOL(nftnl_set_get_u64);
343uint64_t nftnl_set_get_u64(
const struct nftnl_set *s, uint16_t attr)
346 const uint64_t *val = nftnl_set_get_data(s, attr, &data_len);
348 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
350 return val ? *val : 0;
353struct nftnl_set *nftnl_set_clone(
const struct nftnl_set *set)
355 struct nftnl_set *newset;
356 struct nftnl_set_elem *elem, *newelem;
358 newset = nftnl_set_alloc();
362 memcpy(newset, set,
sizeof(*set));
364 if (set->flags & (1 << NFTNL_SET_TABLE)) {
365 newset->table = strdup(set->table);
369 if (set->flags & (1 << NFTNL_SET_NAME)) {
370 newset->name = strdup(set->name);
375 INIT_LIST_HEAD(&newset->element_list);
376 list_for_each_entry(elem, &set->element_list, head) {
377 newelem = nftnl_set_elem_clone(elem);
381 list_add_tail(&newelem->head, &newset->element_list);
386 nftnl_set_free(newset);
390static void nftnl_set_nlmsg_build_desc_size_payload(
struct nlmsghdr *nlh,
393 mnl_attr_put_u32(nlh, NFTA_SET_DESC_SIZE, htonl(s->desc.size));
396static void nftnl_set_nlmsg_build_desc_concat_payload(
struct nlmsghdr *nlh,
402 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC_CONCAT);
403 for (i = 0; i < NFT_REG32_COUNT && i < s->desc.field_count; i++) {
404 struct nlattr *nest_elem;
406 nest_elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
407 mnl_attr_put_u32(nlh, NFTA_SET_FIELD_LEN,
408 htonl(s->desc.field_len[i]));
409 mnl_attr_nest_end(nlh, nest_elem);
411 mnl_attr_nest_end(nlh, nest);
415nftnl_set_nlmsg_build_desc_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
419 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC);
421 if (s->flags & (1 << NFTNL_SET_DESC_SIZE))
422 nftnl_set_nlmsg_build_desc_size_payload(nlh, s);
423 if (s->flags & (1 << NFTNL_SET_DESC_CONCAT))
424 nftnl_set_nlmsg_build_desc_concat_payload(nlh, s);
426 mnl_attr_nest_end(nlh, nest);
429EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
430void nftnl_set_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
434 if (s->flags & (1 << NFTNL_SET_TABLE))
435 mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
436 if (s->flags & (1 << NFTNL_SET_NAME))
437 mnl_attr_put_strz(nlh, NFTA_SET_NAME, s->name);
438 if (s->flags & (1 << NFTNL_SET_HANDLE))
439 mnl_attr_put_u64(nlh, NFTA_SET_HANDLE, htobe64(s->handle));
440 if (s->flags & (1 << NFTNL_SET_FLAGS))
441 mnl_attr_put_u32(nlh, NFTA_SET_FLAGS, htonl(s->set_flags));
442 if (s->flags & (1 << NFTNL_SET_KEY_TYPE))
443 mnl_attr_put_u32(nlh, NFTA_SET_KEY_TYPE, htonl(s->key_type));
444 if (s->flags & (1 << NFTNL_SET_KEY_LEN))
445 mnl_attr_put_u32(nlh, NFTA_SET_KEY_LEN, htonl(s->key_len));
447 if (s->flags & (1 << NFTNL_SET_DATA_TYPE))
448 mnl_attr_put_u32(nlh, NFTA_SET_DATA_TYPE, htonl(s->data_type));
449 if (s->flags & (1 << NFTNL_SET_DATA_LEN))
450 mnl_attr_put_u32(nlh, NFTA_SET_DATA_LEN, htonl(s->data_len));
451 if (s->flags & (1 << NFTNL_SET_OBJ_TYPE))
452 mnl_attr_put_u32(nlh, NFTA_SET_OBJ_TYPE, htonl(s->obj_type));
453 if (s->flags & (1 << NFTNL_SET_ID))
454 mnl_attr_put_u32(nlh, NFTA_SET_ID, htonl(s->id));
455 if (s->flags & (1 << NFTNL_SET_POLICY))
456 mnl_attr_put_u32(nlh, NFTA_SET_POLICY, htonl(s->policy));
457 if (s->flags & (1 << NFTNL_SET_DESC_SIZE | 1 << NFTNL_SET_DESC_CONCAT))
458 nftnl_set_nlmsg_build_desc_payload(nlh, s);
459 if (s->flags & (1 << NFTNL_SET_TIMEOUT))
460 mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
461 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
462 mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
463 if (s->flags & (1 << NFTNL_SET_USERDATA))
464 mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
465 if (!list_empty(&s->expr_list)) {
466 struct nftnl_expr *expr;
468 list_for_each_entry(expr, &s->expr_list, head)
471 if (num_exprs == 1) {
472 struct nlattr *nest1;
474 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
475 list_for_each_entry(expr, &s->expr_list, head)
476 nftnl_expr_build_payload(nlh, expr);
478 mnl_attr_nest_end(nlh, nest1);
479 }
else if (num_exprs > 1) {
480 struct nlattr *nest1, *nest2;
482 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS);
483 list_for_each_entry(expr, &s->expr_list, head) {
484 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
485 nftnl_expr_build_payload(nlh, expr);
486 mnl_attr_nest_end(nlh, nest2);
488 mnl_attr_nest_end(nlh, nest1);
493EXPORT_SYMBOL(nftnl_set_add_expr);
494void nftnl_set_add_expr(
struct nftnl_set *s,
struct nftnl_expr *expr)
496 list_add_tail(&expr->head, &s->expr_list);
499EXPORT_SYMBOL(nftnl_set_expr_foreach);
500int nftnl_set_expr_foreach(
const struct nftnl_set *s,
501 int (*cb)(
struct nftnl_expr *e,
void *data),
504 struct nftnl_expr *cur, *tmp;
507 list_for_each_entry_safe(cur, tmp, &s->expr_list, head) {
515static int nftnl_set_parse_attr_cb(
const struct nlattr *attr,
void *data)
517 const struct nlattr **tb = data;
518 int type = mnl_attr_get_type(attr);
520 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
526 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
529 case NFTA_SET_HANDLE:
530 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
534 case NFTA_SET_KEY_TYPE:
535 case NFTA_SET_KEY_LEN:
536 case NFTA_SET_DATA_TYPE:
537 case NFTA_SET_DATA_LEN:
539 case NFTA_SET_POLICY:
540 case NFTA_SET_GC_INTERVAL:
541 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
544 case NFTA_SET_USERDATA:
545 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
548 case NFTA_SET_TIMEOUT:
549 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
554 case NFTA_SET_EXPRESSIONS:
555 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
565nftnl_set_desc_concat_field_parse_attr_cb(
const struct nlattr *attr,
void *data)
567 int type = mnl_attr_get_type(attr);
568 struct nftnl_set *s = data;
570 if (type != NFTA_SET_FIELD_LEN)
573 if (mnl_attr_validate(attr, MNL_TYPE_U32))
576 s->desc.field_len[s->desc.field_count] = ntohl(mnl_attr_get_u32(attr));
577 s->desc.field_count++;
583nftnl_set_desc_concat_parse_attr_cb(
const struct nlattr *attr,
void *data)
585 int type = mnl_attr_get_type(attr);
586 struct nftnl_set *s = data;
588 if (type != NFTA_LIST_ELEM)
591 return mnl_attr_parse_nested(attr,
592 nftnl_set_desc_concat_field_parse_attr_cb,
596static int nftnl_set_desc_parse_attr_cb(
const struct nlattr *attr,
void *data)
598 int type = mnl_attr_get_type(attr), err;
599 struct nftnl_set *s = data;
601 if (mnl_attr_type_valid(attr, NFTA_SET_DESC_MAX) < 0)
605 case NFTA_SET_DESC_SIZE:
606 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
611 s->desc.size = ntohl(mnl_attr_get_u32(attr));
612 s->flags |= (1 << NFTNL_SET_DESC_SIZE);
614 case NFTA_SET_DESC_CONCAT:
615 err = mnl_attr_parse_nested(attr,
616 nftnl_set_desc_concat_parse_attr_cb,
618 if (err != MNL_CB_OK)
621 s->flags |= (1 << NFTNL_SET_DESC_CONCAT);
630static int nftnl_set_desc_parse(
struct nftnl_set *s,
const struct nlattr *attr)
632 return mnl_attr_parse_nested(attr, nftnl_set_desc_parse_attr_cb, s);
635EXPORT_SYMBOL(nftnl_set_nlmsg_parse);
636int nftnl_set_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
638 struct nlattr *tb[NFTA_SET_MAX+1] = {};
639 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
640 struct nftnl_expr *expr, *next;
643 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
646 if (tb[NFTA_SET_TABLE]) {
647 if (s->flags & (1 << NFTNL_SET_TABLE))
649 s->table = strdup(mnl_attr_get_str(tb[NFTA_SET_TABLE]));
652 s->flags |= (1 << NFTNL_SET_TABLE);
654 if (tb[NFTA_SET_NAME]) {
655 if (s->flags & (1 << NFTNL_SET_NAME))
657 s->name = strdup(mnl_attr_get_str(tb[NFTA_SET_NAME]));
660 s->flags |= (1 << NFTNL_SET_NAME);
662 if (tb[NFTA_SET_HANDLE]) {
663 s->handle = be64toh(mnl_attr_get_u64(tb[NFTA_SET_HANDLE]));
664 s->flags |= (1 << NFTNL_SET_HANDLE);
666 if (tb[NFTA_SET_FLAGS]) {
667 s->set_flags = ntohl(mnl_attr_get_u32(tb[NFTA_SET_FLAGS]));
668 s->flags |= (1 << NFTNL_SET_FLAGS);
670 if (tb[NFTA_SET_KEY_TYPE]) {
671 s->key_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_TYPE]));
672 s->flags |= (1 << NFTNL_SET_KEY_TYPE);
674 if (tb[NFTA_SET_KEY_LEN]) {
675 s->key_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_LEN]));
676 s->flags |= (1 << NFTNL_SET_KEY_LEN);
678 if (tb[NFTA_SET_DATA_TYPE]) {
679 s->data_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_TYPE]));
680 s->flags |= (1 << NFTNL_SET_DATA_TYPE);
682 if (tb[NFTA_SET_DATA_LEN]) {
683 s->data_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_LEN]));
684 s->flags |= (1 << NFTNL_SET_DATA_LEN);
686 if (tb[NFTA_SET_OBJ_TYPE]) {
687 s->obj_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_OBJ_TYPE]));
688 s->flags |= (1 << NFTNL_SET_OBJ_TYPE);
690 if (tb[NFTA_SET_ID]) {
691 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ID]));
692 s->flags |= (1 << NFTNL_SET_ID);
694 if (tb[NFTA_SET_POLICY]) {
695 s->policy = ntohl(mnl_attr_get_u32(tb[NFTA_SET_POLICY]));
696 s->flags |= (1 << NFTNL_SET_POLICY);
698 if (tb[NFTA_SET_TIMEOUT]) {
699 s->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_TIMEOUT]));
700 s->flags |= (1 << NFTNL_SET_TIMEOUT);
702 if (tb[NFTA_SET_GC_INTERVAL]) {
703 s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
704 s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
706 if (tb[NFTA_SET_USERDATA]) {
707 ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
708 mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
709 mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
713 if (tb[NFTA_SET_DESC]) {
714 ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
718 if (tb[NFTA_SET_EXPR]) {
719 expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
723 list_add(&expr->head, &s->expr_list);
724 s->flags |= (1 << NFTNL_SET_EXPR);
725 }
else if (tb[NFTA_SET_EXPRESSIONS]) {
728 mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) {
729 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
732 expr = nftnl_expr_parse(attr);
736 list_add_tail(&expr->head, &s->expr_list);
738 s->flags |= (1 << NFTNL_SET_EXPRESSIONS);
741 s->family = nfg->nfgen_family;
742 s->flags |= (1 << NFTNL_SET_FAMILY);
746 list_for_each_entry_safe(expr, next, &s->expr_list, head) {
747 list_del(&expr->head);
748 nftnl_expr_free(expr);
754EXPORT_SYMBOL(nftnl_set_parse);
755int nftnl_set_parse(
struct nftnl_set *s,
enum nftnl_parse_type type,
756 const char *data,
struct nftnl_parse_err *err)
763EXPORT_SYMBOL(nftnl_set_parse_file);
764int nftnl_set_parse_file(
struct nftnl_set *s,
enum nftnl_parse_type type,
765 FILE *fp,
struct nftnl_parse_err *err)
772static int nftnl_set_snprintf_default(
char *buf,
size_t remain,
773 const struct nftnl_set *s,
774 uint32_t type, uint32_t flags)
776 struct nftnl_set_elem *elem;
779 ret = snprintf(buf, remain,
"%s %s %x",
780 s->name, s->table, s->set_flags);
781 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
783 if (s->flags & (1 << NFTNL_SET_TIMEOUT)) {
784 ret = snprintf(buf + offset, remain,
" timeout %"PRIu64
"ms",
786 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
789 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL)) {
790 ret = snprintf(buf + offset, remain,
" gc_interval %ums",
792 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
795 if (s->flags & (1 << NFTNL_SET_POLICY)) {
796 ret = snprintf(buf + offset, remain,
" policy %u", s->policy);
797 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
800 if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
801 ret = snprintf(buf + offset, remain,
" size %u", s->desc.size);
802 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
806 if (list_empty(&s->element_list))
809 ret = snprintf(buf + offset, remain,
"\n");
810 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
812 list_for_each_entry(elem, &s->element_list, head) {
813 ret = snprintf(buf + offset, remain,
"\t");
814 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
816 ret = nftnl_set_elem_snprintf_default(buf + offset, remain,
818 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
824static int nftnl_set_cmd_snprintf(
char *buf,
size_t remain,
825 const struct nftnl_set *s, uint32_t cmd,
826 uint32_t type, uint32_t flags)
828 uint32_t inner_flags = flags;
831 if (type != NFTNL_OUTPUT_DEFAULT)
835 inner_flags &= ~NFTNL_OF_EVENT_ANY;
837 ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
839 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
843EXPORT_SYMBOL(nftnl_set_snprintf);
844int nftnl_set_snprintf(
char *buf,
size_t size,
const struct nftnl_set *s,
845 uint32_t type, uint32_t flags)
850 return nftnl_set_cmd_snprintf(buf, size, s, nftnl_flag2cmd(flags), type,
854static int nftnl_set_do_snprintf(
char *buf,
size_t size,
const void *s,
855 uint32_t cmd, uint32_t type, uint32_t flags)
857 return nftnl_set_snprintf(buf, size, s, type, flags);
860EXPORT_SYMBOL(nftnl_set_fprintf);
861int nftnl_set_fprintf(FILE *fp,
const struct nftnl_set *s, uint32_t type,
864 return nftnl_fprintf(fp, s, NFTNL_CMD_UNSPEC, type, flags,
865 nftnl_set_do_snprintf);
868EXPORT_SYMBOL(nftnl_set_elem_add);
869void nftnl_set_elem_add(
struct nftnl_set *s,
struct nftnl_set_elem *elem)
871 list_add_tail(&elem->head, &s->element_list);
874#define SET_NAME_HSIZE 512
877 struct list_head list;
878 struct hlist_head name_hash[SET_NAME_HSIZE];
881EXPORT_SYMBOL(nftnl_set_list_alloc);
891 INIT_LIST_HEAD(&list->list);
892 for (i = 0; i < SET_NAME_HSIZE; i++)
893 INIT_HLIST_HEAD(&list->name_hash[i]);
898EXPORT_SYMBOL(nftnl_set_list_free);
901 struct nftnl_set *s, *tmp;
903 list_for_each_entry_safe(s, tmp, &list->list, head) {
905 hlist_del(&s->hnode);
911EXPORT_SYMBOL(nftnl_set_list_is_empty);
914 return list_empty(&list->list);
917static uint32_t djb_hash(
const char *key)
919 uint32_t i, hash = 5381;
921 for (i = 0; i < strlen(key); i++)
922 hash = ((hash << 5) + hash) + key[i];
927EXPORT_SYMBOL(nftnl_set_list_add);
928void nftnl_set_list_add(
struct nftnl_set *s,
struct nftnl_set_list *list)
930 int key = djb_hash(s->name) % SET_NAME_HSIZE;
932 hlist_add_head(&s->hnode, &list->name_hash[key]);
933 list_add(&s->head, &list->list);
936EXPORT_SYMBOL(nftnl_set_list_add_tail);
937void nftnl_set_list_add_tail(
struct nftnl_set *s,
struct nftnl_set_list *list)
939 int key = djb_hash(s->name) % SET_NAME_HSIZE;
941 hlist_add_head(&s->hnode, &list->name_hash[key]);
942 list_add_tail(&s->head, &list->list);
945EXPORT_SYMBOL(nftnl_set_list_del);
946void nftnl_set_list_del(
struct nftnl_set *s)
949 hlist_del(&s->hnode);
952EXPORT_SYMBOL(nftnl_set_list_foreach);
954 int (*cb)(
struct nftnl_set *t,
void *data),
void *data)
956 struct nftnl_set *cur, *tmp;
959 list_for_each_entry_safe(cur, tmp, &set_list->list, head) {
969 struct nftnl_set *cur;
972EXPORT_SYMBOL(nftnl_set_list_iter_create);
983 if (nftnl_set_list_is_empty(l))
986 iter->cur = list_entry(l->list.next,
struct nftnl_set, head);
991EXPORT_SYMBOL(nftnl_set_list_iter_cur);
998EXPORT_SYMBOL(nftnl_set_list_iter_next);
1001 struct nftnl_set *s = iter->cur;
1007 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set, head);
1008 if (&iter->cur->head == iter->list->list.next)
1014EXPORT_SYMBOL(nftnl_set_list_iter_destroy);
1020EXPORT_SYMBOL(nftnl_set_list_lookup_byname);
1022nftnl_set_list_lookup_byname(
struct nftnl_set_list *set_list,
const char *set)
1024 int key = djb_hash(set) % SET_NAME_HSIZE;
1025 struct hlist_node *n;
1026 struct nftnl_set *s;
1028 hlist_for_each_entry(s, n, &set_list->name_hash[key], hnode) {
1029 if (!strcmp(set, s->name))
1035int nftnl_set_lookup_id(
struct nftnl_expr *e,
1038 const char *set_name;
1039 struct nftnl_set *s;
1041 set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
1042 if (set_name == NULL)
1045 s = nftnl_set_list_lookup_byname(set_list, set_name);
1049 *set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);