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 nftnl_expr_free(expr);
60 list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
61 list_del(&elem->head);
62 nftnl_set_elem_free(elem);
67 EXPORT_SYMBOL(nftnl_set_is_set);
68 bool nftnl_set_is_set(
const struct nftnl_set *s, uint16_t attr)
70 return s->flags & (1 << attr);
73 EXPORT_SYMBOL(nftnl_set_unset);
74 void 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:
103 case NFTNL_SET_USERDATA:
107 case NFTNL_SET_EXPRESSIONS:
108 list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
109 nftnl_expr_free(expr);
115 s->flags &= ~(1 << attr);
118 static 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_POLICY] =
sizeof(uint32_t),
128 [NFTNL_SET_DESC_SIZE] =
sizeof(uint32_t),
129 [NFTNL_SET_TIMEOUT] =
sizeof(uint64_t),
130 [NFTNL_SET_GC_INTERVAL] =
sizeof(uint32_t),
133 EXPORT_SYMBOL(nftnl_set_set_data);
134 int nftnl_set_set_data(
struct nftnl_set *s, uint16_t attr,
const void *data,
137 struct nftnl_expr *expr, *tmp;
139 nftnl_assert_attr_exists(attr, NFTNL_SET_MAX);
140 nftnl_assert_validate(data, nftnl_set_validate, attr, data_len);
143 case NFTNL_SET_TABLE:
144 if (s->flags & (1 << NFTNL_SET_TABLE))
147 s->table = strdup(data);
152 if (s->flags & (1 << NFTNL_SET_NAME))
155 s->name = strdup(data);
159 case NFTNL_SET_HANDLE:
160 memcpy(&s->handle, data,
sizeof(s->handle));
162 case NFTNL_SET_FLAGS:
163 memcpy(&s->set_flags, data,
sizeof(s->set_flags));
165 case NFTNL_SET_KEY_TYPE:
166 memcpy(&s->key_type, data,
sizeof(s->key_type));
168 case NFTNL_SET_KEY_LEN:
169 memcpy(&s->key_len, data,
sizeof(s->key_len));
171 case NFTNL_SET_DATA_TYPE:
172 memcpy(&s->data_type, data,
sizeof(s->data_type));
174 case NFTNL_SET_DATA_LEN:
175 memcpy(&s->data_len, data,
sizeof(s->data_len));
177 case NFTNL_SET_OBJ_TYPE:
178 memcpy(&s->obj_type, data,
sizeof(s->obj_type));
180 case NFTNL_SET_FAMILY:
181 memcpy(&s->family, data,
sizeof(s->family));
184 memcpy(&s->id, data,
sizeof(s->id));
186 case NFTNL_SET_POLICY:
187 memcpy(&s->policy, data,
sizeof(s->policy));
189 case NFTNL_SET_DESC_SIZE:
190 memcpy(&s->desc.size, data,
sizeof(s->desc.size));
192 case NFTNL_SET_DESC_CONCAT:
193 memcpy(&s->desc.field_len, data, data_len);
194 while (s->desc.field_len[++s->desc.field_count]);
196 case NFTNL_SET_TIMEOUT:
197 memcpy(&s->timeout, data,
sizeof(s->timeout));
199 case NFTNL_SET_GC_INTERVAL:
200 memcpy(&s->gc_interval, data,
sizeof(s->gc_interval));
202 case NFTNL_SET_USERDATA:
203 if (s->flags & (1 << NFTNL_SET_USERDATA))
206 s->user.data = malloc(data_len);
209 memcpy(s->user.data, data, data_len);
210 s->user.len = data_len;
213 list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
214 nftnl_expr_free(expr);
217 list_add(&expr->head, &s->expr_list);
220 s->flags |= (1 << attr);
224 int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data) __visible;
225 int nftnl_set_set(
struct nftnl_set *s, uint16_t attr,
const void *data)
227 return nftnl_set_set_data(s, attr, data, nftnl_set_validate[attr]);
230 EXPORT_SYMBOL(nftnl_set_set_u32);
231 void nftnl_set_set_u32(
struct nftnl_set *s, uint16_t attr, uint32_t val)
233 nftnl_set_set_data(s, attr, &val,
sizeof(uint32_t));
236 EXPORT_SYMBOL(nftnl_set_set_u64);
237 void nftnl_set_set_u64(
struct nftnl_set *s, uint16_t attr, uint64_t val)
239 nftnl_set_set_data(s, attr, &val,
sizeof(uint64_t));
242 EXPORT_SYMBOL(nftnl_set_set_str);
243 int nftnl_set_set_str(
struct nftnl_set *s, uint16_t attr,
const char *str)
245 return nftnl_set_set_data(s, attr, str, strlen(str) + 1);
248 EXPORT_SYMBOL(nftnl_set_get_data);
249 const void *nftnl_set_get_data(
const struct nftnl_set *s, uint16_t attr,
252 struct nftnl_expr *expr;
254 if (!(s->flags & (1 << attr)))
258 case NFTNL_SET_TABLE:
259 *data_len = strlen(s->table) + 1;
262 *data_len = strlen(s->name) + 1;
264 case NFTNL_SET_HANDLE:
265 *data_len =
sizeof(uint64_t);
267 case NFTNL_SET_FLAGS:
268 *data_len =
sizeof(uint32_t);
269 return &s->set_flags;
270 case NFTNL_SET_KEY_TYPE:
271 *data_len =
sizeof(uint32_t);
273 case NFTNL_SET_KEY_LEN:
274 *data_len =
sizeof(uint32_t);
276 case NFTNL_SET_DATA_TYPE:
277 *data_len =
sizeof(uint32_t);
278 return &s->data_type;
279 case NFTNL_SET_DATA_LEN:
280 *data_len =
sizeof(uint32_t);
282 case NFTNL_SET_OBJ_TYPE:
283 *data_len =
sizeof(uint32_t);
285 case NFTNL_SET_FAMILY:
286 *data_len =
sizeof(uint32_t);
289 *data_len =
sizeof(uint32_t);
291 case NFTNL_SET_POLICY:
292 *data_len =
sizeof(uint32_t);
294 case NFTNL_SET_DESC_SIZE:
295 *data_len =
sizeof(uint32_t);
296 return &s->desc.size;
297 case NFTNL_SET_DESC_CONCAT:
298 *data_len = s->desc.field_count;
299 return s->desc.field_len;
300 case NFTNL_SET_TIMEOUT:
301 *data_len =
sizeof(uint64_t);
303 case NFTNL_SET_GC_INTERVAL:
304 *data_len =
sizeof(uint32_t);
305 return &s->gc_interval;
306 case NFTNL_SET_USERDATA:
307 *data_len = s->user.len;
310 list_for_each_entry(expr, &s->expr_list, head)
317 EXPORT_SYMBOL(nftnl_set_get);
318 const void *nftnl_set_get(
const struct nftnl_set *s, uint16_t attr)
321 return nftnl_set_get_data(s, attr, &data_len);
324 EXPORT_SYMBOL(nftnl_set_get_str);
325 const char *nftnl_set_get_str(
const struct nftnl_set *s, uint16_t attr)
327 return nftnl_set_get(s, attr);
330 EXPORT_SYMBOL(nftnl_set_get_u32);
331 uint32_t nftnl_set_get_u32(
const struct nftnl_set *s, uint16_t attr)
334 const uint32_t *val = nftnl_set_get_data(s, attr, &data_len);
336 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
338 return val ? *val : 0;
341 EXPORT_SYMBOL(nftnl_set_get_u64);
342 uint64_t nftnl_set_get_u64(
const struct nftnl_set *s, uint16_t attr)
345 const uint64_t *val = nftnl_set_get_data(s, attr, &data_len);
347 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
349 return val ? *val : 0;
352 struct nftnl_set *nftnl_set_clone(
const struct nftnl_set *
set)
354 struct nftnl_set *newset;
355 struct nftnl_set_elem *elem, *newelem;
357 newset = nftnl_set_alloc();
361 memcpy(newset,
set,
sizeof(*
set));
363 if (set->flags & (1 << NFTNL_SET_TABLE)) {
364 newset->table = strdup(set->table);
368 if (set->flags & (1 << NFTNL_SET_NAME)) {
369 newset->name = strdup(set->name);
374 INIT_LIST_HEAD(&newset->element_list);
375 list_for_each_entry(elem, &set->element_list, head) {
376 newelem = nftnl_set_elem_clone(elem);
380 list_add_tail(&newelem->head, &newset->element_list);
385 nftnl_set_free(newset);
389 static void nftnl_set_nlmsg_build_desc_size_payload(
struct nlmsghdr *nlh,
392 mnl_attr_put_u32(nlh, NFTA_SET_DESC_SIZE, htonl(s->desc.size));
395 static void nftnl_set_nlmsg_build_desc_concat_payload(
struct nlmsghdr *nlh,
401 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC_CONCAT);
402 for (i = 0; i < NFT_REG32_COUNT && i < s->desc.field_count; i++) {
403 struct nlattr *nest_elem;
405 nest_elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
406 mnl_attr_put_u32(nlh, NFTA_SET_FIELD_LEN,
407 htonl(s->desc.field_len[i]));
408 mnl_attr_nest_end(nlh, nest_elem);
410 mnl_attr_nest_end(nlh, nest);
414 nftnl_set_nlmsg_build_desc_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
418 nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC);
420 if (s->flags & (1 << NFTNL_SET_DESC_SIZE))
421 nftnl_set_nlmsg_build_desc_size_payload(nlh, s);
422 if (s->flags & (1 << NFTNL_SET_DESC_CONCAT))
423 nftnl_set_nlmsg_build_desc_concat_payload(nlh, s);
425 mnl_attr_nest_end(nlh, nest);
428 EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
429 void nftnl_set_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
433 if (s->flags & (1 << NFTNL_SET_TABLE))
434 mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
435 if (s->flags & (1 << NFTNL_SET_NAME))
436 mnl_attr_put_strz(nlh, NFTA_SET_NAME, s->name);
437 if (s->flags & (1 << NFTNL_SET_HANDLE))
438 mnl_attr_put_u64(nlh, NFTA_SET_HANDLE, htobe64(s->handle));
439 if (s->flags & (1 << NFTNL_SET_FLAGS))
440 mnl_attr_put_u32(nlh, NFTA_SET_FLAGS, htonl(s->set_flags));
441 if (s->flags & (1 << NFTNL_SET_KEY_TYPE))
442 mnl_attr_put_u32(nlh, NFTA_SET_KEY_TYPE, htonl(s->key_type));
443 if (s->flags & (1 << NFTNL_SET_KEY_LEN))
444 mnl_attr_put_u32(nlh, NFTA_SET_KEY_LEN, htonl(s->key_len));
446 if (s->flags & (1 << NFTNL_SET_DATA_TYPE))
447 mnl_attr_put_u32(nlh, NFTA_SET_DATA_TYPE, htonl(s->data_type));
448 if (s->flags & (1 << NFTNL_SET_DATA_LEN))
449 mnl_attr_put_u32(nlh, NFTA_SET_DATA_LEN, htonl(s->data_len));
450 if (s->flags & (1 << NFTNL_SET_OBJ_TYPE))
451 mnl_attr_put_u32(nlh, NFTA_SET_OBJ_TYPE, htonl(s->obj_type));
452 if (s->flags & (1 << NFTNL_SET_ID))
453 mnl_attr_put_u32(nlh, NFTA_SET_ID, htonl(s->id));
454 if (s->flags & (1 << NFTNL_SET_POLICY))
455 mnl_attr_put_u32(nlh, NFTA_SET_POLICY, htonl(s->policy));
456 if (s->flags & (1 << NFTNL_SET_DESC_SIZE | 1 << NFTNL_SET_DESC_CONCAT))
457 nftnl_set_nlmsg_build_desc_payload(nlh, s);
458 if (s->flags & (1 << NFTNL_SET_TIMEOUT))
459 mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
460 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
461 mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
462 if (s->flags & (1 << NFTNL_SET_USERDATA))
463 mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
464 if (!list_empty(&s->expr_list)) {
465 struct nftnl_expr *expr;
467 list_for_each_entry(expr, &s->expr_list, head)
470 if (num_exprs == 1) {
471 struct nlattr *nest1;
473 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
474 list_for_each_entry(expr, &s->expr_list, head)
475 nftnl_expr_build_payload(nlh, expr);
477 mnl_attr_nest_end(nlh, nest1);
478 }
else if (num_exprs > 1) {
479 struct nlattr *nest1, *nest2;
481 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS);
482 list_for_each_entry(expr, &s->expr_list, head) {
483 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
484 nftnl_expr_build_payload(nlh, expr);
485 mnl_attr_nest_end(nlh, nest2);
487 mnl_attr_nest_end(nlh, nest1);
492 EXPORT_SYMBOL(nftnl_set_add_expr);
493 void nftnl_set_add_expr(
struct nftnl_set *s,
struct nftnl_expr *expr)
495 list_add_tail(&expr->head, &s->expr_list);
498 EXPORT_SYMBOL(nftnl_set_expr_foreach);
499 int nftnl_set_expr_foreach(
const struct nftnl_set *s,
500 int (*cb)(
struct nftnl_expr *e,
void *data),
503 struct nftnl_expr *cur, *tmp;
506 list_for_each_entry_safe(cur, tmp, &s->expr_list, head) {
514 static int nftnl_set_parse_attr_cb(
const struct nlattr *attr,
void *data)
516 const struct nlattr **tb = data;
517 int type = mnl_attr_get_type(attr);
519 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
525 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
528 case NFTA_SET_HANDLE:
529 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
533 case NFTA_SET_KEY_TYPE:
534 case NFTA_SET_KEY_LEN:
535 case NFTA_SET_DATA_TYPE:
536 case NFTA_SET_DATA_LEN:
538 case NFTA_SET_POLICY:
539 case NFTA_SET_GC_INTERVAL:
540 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
543 case NFTA_SET_USERDATA:
544 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
547 case NFTA_SET_TIMEOUT:
548 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
553 case NFTA_SET_EXPRESSIONS:
554 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
564 nftnl_set_desc_concat_field_parse_attr_cb(
const struct nlattr *attr,
void *data)
566 int type = mnl_attr_get_type(attr);
567 struct nftnl_set *s = data;
569 if (type != NFTA_SET_FIELD_LEN)
572 if (mnl_attr_validate(attr, MNL_TYPE_U32))
575 s->desc.field_len[s->desc.field_count] = ntohl(mnl_attr_get_u32(attr));
576 s->desc.field_count++;
582 nftnl_set_desc_concat_parse_attr_cb(
const struct nlattr *attr,
void *data)
584 int type = mnl_attr_get_type(attr);
585 struct nftnl_set *s = data;
587 if (type != NFTA_LIST_ELEM)
590 return mnl_attr_parse_nested(attr,
591 nftnl_set_desc_concat_field_parse_attr_cb,
595 static int nftnl_set_desc_parse_attr_cb(
const struct nlattr *attr,
void *data)
597 int type = mnl_attr_get_type(attr), err;
598 struct nftnl_set *s = data;
600 if (mnl_attr_type_valid(attr, NFTA_SET_DESC_MAX) < 0)
604 case NFTA_SET_DESC_SIZE:
605 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
610 s->desc.size = ntohl(mnl_attr_get_u32(attr));
611 s->flags |= (1 << NFTNL_SET_DESC_SIZE);
613 case NFTA_SET_DESC_CONCAT:
614 err = mnl_attr_parse_nested(attr,
615 nftnl_set_desc_concat_parse_attr_cb,
617 if (err != MNL_CB_OK)
620 s->flags |= (1 << NFTNL_SET_DESC_CONCAT);
629 static int nftnl_set_desc_parse(
struct nftnl_set *s,
const struct nlattr *attr)
631 return mnl_attr_parse_nested(attr, nftnl_set_desc_parse_attr_cb, s);
634 EXPORT_SYMBOL(nftnl_set_nlmsg_parse);
635 int nftnl_set_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
637 struct nlattr *tb[NFTA_SET_MAX+1] = {};
638 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
639 struct nftnl_expr *expr, *next;
642 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
645 if (tb[NFTA_SET_TABLE]) {
646 if (s->flags & (1 << NFTNL_SET_TABLE))
648 s->table = strdup(mnl_attr_get_str(tb[NFTA_SET_TABLE]));
651 s->flags |= (1 << NFTNL_SET_TABLE);
653 if (tb[NFTA_SET_NAME]) {
654 if (s->flags & (1 << NFTNL_SET_NAME))
656 s->name = strdup(mnl_attr_get_str(tb[NFTA_SET_NAME]));
659 s->flags |= (1 << NFTNL_SET_NAME);
661 if (tb[NFTA_SET_HANDLE]) {
662 s->handle = be64toh(mnl_attr_get_u64(tb[NFTA_SET_HANDLE]));
663 s->flags |= (1 << NFTNL_SET_HANDLE);
665 if (tb[NFTA_SET_FLAGS]) {
666 s->set_flags = ntohl(mnl_attr_get_u32(tb[NFTA_SET_FLAGS]));
667 s->flags |= (1 << NFTNL_SET_FLAGS);
669 if (tb[NFTA_SET_KEY_TYPE]) {
670 s->key_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_TYPE]));
671 s->flags |= (1 << NFTNL_SET_KEY_TYPE);
673 if (tb[NFTA_SET_KEY_LEN]) {
674 s->key_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_LEN]));
675 s->flags |= (1 << NFTNL_SET_KEY_LEN);
677 if (tb[NFTA_SET_DATA_TYPE]) {
678 s->data_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_TYPE]));
679 s->flags |= (1 << NFTNL_SET_DATA_TYPE);
681 if (tb[NFTA_SET_DATA_LEN]) {
682 s->data_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_LEN]));
683 s->flags |= (1 << NFTNL_SET_DATA_LEN);
685 if (tb[NFTA_SET_OBJ_TYPE]) {
686 s->obj_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_OBJ_TYPE]));
687 s->flags |= (1 << NFTNL_SET_OBJ_TYPE);
689 if (tb[NFTA_SET_ID]) {
690 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ID]));
691 s->flags |= (1 << NFTNL_SET_ID);
693 if (tb[NFTA_SET_POLICY]) {
694 s->policy = ntohl(mnl_attr_get_u32(tb[NFTA_SET_POLICY]));
695 s->flags |= (1 << NFTNL_SET_POLICY);
697 if (tb[NFTA_SET_TIMEOUT]) {
698 s->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_TIMEOUT]));
699 s->flags |= (1 << NFTNL_SET_TIMEOUT);
701 if (tb[NFTA_SET_GC_INTERVAL]) {
702 s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
703 s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
705 if (tb[NFTA_SET_USERDATA]) {
706 ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
707 mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
708 mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
712 if (tb[NFTA_SET_DESC]) {
713 ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
717 if (tb[NFTA_SET_EXPR]) {
718 expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
722 list_add(&expr->head, &s->expr_list);
723 s->flags |= (1 << NFTNL_SET_EXPR);
724 }
else if (tb[NFTA_SET_EXPRESSIONS]) {
727 mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) {
728 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
731 expr = nftnl_expr_parse(attr);
735 list_add_tail(&expr->head, &s->expr_list);
737 s->flags |= (1 << NFTNL_SET_EXPRESSIONS);
740 s->family = nfg->nfgen_family;
741 s->flags |= (1 << NFTNL_SET_FAMILY);
745 list_for_each_entry_safe(expr, next, &s->expr_list, head)
746 nftnl_expr_free(expr);
751 static int nftnl_set_do_parse(
struct nftnl_set *s,
enum nftnl_parse_type type,
752 const void *data,
struct nftnl_parse_err *err,
753 enum nftnl_parse_input input)
756 struct nftnl_parse_err perr = {};
759 case NFTNL_PARSE_JSON:
760 case NFTNL_PARSE_XML:
773 EXPORT_SYMBOL(nftnl_set_parse);
774 int nftnl_set_parse(
struct nftnl_set *s,
enum nftnl_parse_type type,
775 const char *data,
struct nftnl_parse_err *err)
777 return nftnl_set_do_parse(s, type, data, err, NFTNL_PARSE_BUFFER);
780 EXPORT_SYMBOL(nftnl_set_parse_file);
781 int nftnl_set_parse_file(
struct nftnl_set *s,
enum nftnl_parse_type type,
782 FILE *fp,
struct nftnl_parse_err *err)
784 return nftnl_set_do_parse(s, type, fp, err, NFTNL_PARSE_FILE);
787 static int nftnl_set_snprintf_default(
char *buf,
size_t size,
788 const struct nftnl_set *s,
789 uint32_t type, uint32_t flags)
792 int remain = size, offset = 0;
793 struct nftnl_set_elem *elem;
795 ret = snprintf(buf, remain,
"%s %s %x",
796 s->name, s->table, s->set_flags);
797 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
799 if (s->flags & (1 << NFTNL_SET_TIMEOUT)) {
800 ret = snprintf(buf + offset, remain,
" timeout %"PRIu64
"ms",
802 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
805 if (s->flags & (1 << NFTNL_SET_GC_INTERVAL)) {
806 ret = snprintf(buf + offset, remain,
" gc_interval %ums",
808 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
811 if (s->flags & (1 << NFTNL_SET_POLICY)) {
812 ret = snprintf(buf + offset, remain,
" policy %u", s->policy);
813 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
816 if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
817 ret = snprintf(buf + offset, remain,
" size %u", s->desc.size);
818 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
822 if (list_empty(&s->element_list))
825 ret = snprintf(buf + offset, remain,
"\n");
826 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
828 list_for_each_entry(elem, &s->element_list, head) {
829 ret = snprintf(buf + offset, remain,
"\t");
830 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
832 ret = nftnl_set_elem_snprintf(buf + offset, remain, elem, type,
834 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
840 static int nftnl_set_cmd_snprintf(
char *buf,
size_t size,
841 const struct nftnl_set *s, uint32_t cmd,
842 uint32_t type, uint32_t flags)
844 int ret, remain = size, offset = 0;
845 uint32_t inner_flags = flags;
847 if (type == NFTNL_OUTPUT_XML)
851 inner_flags &= ~NFTNL_OF_EVENT_ANY;
854 case NFTNL_OUTPUT_DEFAULT:
855 ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
857 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
866 EXPORT_SYMBOL(nftnl_set_snprintf);
867 int nftnl_set_snprintf(
char *buf,
size_t size,
const struct nftnl_set *s,
868 uint32_t type, uint32_t flags)
873 return nftnl_set_cmd_snprintf(buf, size, s, nftnl_flag2cmd(flags), type,
877 static int nftnl_set_do_snprintf(
char *buf,
size_t size,
const void *s,
878 uint32_t cmd, uint32_t type, uint32_t flags)
880 return nftnl_set_snprintf(buf, size, s, type, flags);
883 EXPORT_SYMBOL(nftnl_set_fprintf);
884 int nftnl_set_fprintf(FILE *fp,
const struct nftnl_set *s, uint32_t type,
887 return nftnl_fprintf(fp, s, NFTNL_CMD_UNSPEC, type, flags,
888 nftnl_set_do_snprintf);
891 EXPORT_SYMBOL(nftnl_set_elem_add);
892 void nftnl_set_elem_add(
struct nftnl_set *s,
struct nftnl_set_elem *elem)
894 list_add_tail(&elem->head, &s->element_list);
897 #define SET_NAME_HSIZE 512 900 struct list_head list;
901 struct hlist_head name_hash[SET_NAME_HSIZE];
904 EXPORT_SYMBOL(nftnl_set_list_alloc);
914 INIT_LIST_HEAD(&list->list);
915 for (i = 0; i < SET_NAME_HSIZE; i++)
916 INIT_HLIST_HEAD(&list->name_hash[i]);
921 EXPORT_SYMBOL(nftnl_set_list_free);
924 struct nftnl_set *s, *tmp;
926 list_for_each_entry_safe(s, tmp, &list->list, head) {
928 hlist_del(&s->hnode);
934 EXPORT_SYMBOL(nftnl_set_list_is_empty);
937 return list_empty(&list->list);
940 static uint32_t djb_hash(
const char *key)
942 uint32_t i, hash = 5381;
944 for (i = 0; i < strlen(key); i++)
945 hash = ((hash << 5) + hash) + key[i];
950 EXPORT_SYMBOL(nftnl_set_list_add);
951 void nftnl_set_list_add(
struct nftnl_set *s,
struct nftnl_set_list *list)
953 int key = djb_hash(s->name) % SET_NAME_HSIZE;
955 hlist_add_head(&s->hnode, &list->name_hash[key]);
956 list_add(&s->head, &list->list);
959 EXPORT_SYMBOL(nftnl_set_list_add_tail);
960 void nftnl_set_list_add_tail(
struct nftnl_set *s,
struct nftnl_set_list *list)
962 int key = djb_hash(s->name) % SET_NAME_HSIZE;
964 hlist_add_head(&s->hnode, &list->name_hash[key]);
965 list_add_tail(&s->head, &list->list);
968 EXPORT_SYMBOL(nftnl_set_list_del);
969 void nftnl_set_list_del(
struct nftnl_set *s)
972 hlist_del(&s->hnode);
975 EXPORT_SYMBOL(nftnl_set_list_foreach);
977 int (*cb)(
struct nftnl_set *t,
void *data),
void *data)
979 struct nftnl_set *cur, *tmp;
982 list_for_each_entry_safe(cur, tmp, &set_list->list, head) {
992 struct nftnl_set *cur;
995 EXPORT_SYMBOL(nftnl_set_list_iter_create);
1006 if (nftnl_set_list_is_empty(l))
1009 iter->cur = list_entry(l->list.next,
struct nftnl_set, head);
1014 EXPORT_SYMBOL(nftnl_set_list_iter_cur);
1021 EXPORT_SYMBOL(nftnl_set_list_iter_next);
1024 struct nftnl_set *s = iter->cur;
1030 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set, head);
1031 if (&iter->cur->head == iter->list->list.next)
1037 EXPORT_SYMBOL(nftnl_set_list_iter_destroy);
1043 EXPORT_SYMBOL(nftnl_set_list_lookup_byname);
1045 nftnl_set_list_lookup_byname(
struct nftnl_set_list *set_list,
const char *
set)
1047 int key = djb_hash(
set) % SET_NAME_HSIZE;
1048 struct hlist_node *n;
1049 struct nftnl_set *s;
1051 hlist_for_each_entry(s, n, &set_list->name_hash[key], hnode) {
1052 if (!strcmp(
set, s->name))
1058 int nftnl_set_lookup_id(
struct nftnl_expr *e,
1061 const char *set_name;
1062 struct nftnl_set *s;
1064 set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
1065 if (set_name == NULL)
1068 s = nftnl_set_list_lookup_byname(set_list, set_name);
1072 *set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);