18 #include <netinet/in.h>
22 #include <libmnl/libmnl.h>
23 #include <linux/netfilter/nfnetlink.h>
24 #include <linux/netfilter/nf_tables.h>
26 #include <libnftnl/set.h>
27 #include <libnftnl/rule.h>
28 #include <libnftnl/expr.h>
30 EXPORT_SYMBOL(nftnl_set_elem_alloc);
31 struct nftnl_set_elem *nftnl_set_elem_alloc(
void)
33 struct nftnl_set_elem *s;
35 s = calloc(1,
sizeof(
struct nftnl_set_elem));
42 EXPORT_SYMBOL(nftnl_set_elem_free);
43 void nftnl_set_elem_free(
struct nftnl_set_elem *s)
45 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
48 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
49 nftnl_expr_free(s->expr);
51 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
54 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
60 EXPORT_SYMBOL(nftnl_set_elem_is_set);
61 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
63 return s->flags & (1 << attr);
66 EXPORT_SYMBOL(nftnl_set_elem_unset);
67 void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
69 if (!(s->flags & (1 << attr)))
73 case NFTNL_SET_ELEM_CHAIN:
76 case NFTNL_SET_ELEM_FLAGS:
77 case NFTNL_SET_ELEM_KEY:
78 case NFTNL_SET_ELEM_KEY_END:
79 case NFTNL_SET_ELEM_VERDICT:
80 case NFTNL_SET_ELEM_DATA:
81 case NFTNL_SET_ELEM_TIMEOUT:
82 case NFTNL_SET_ELEM_EXPIRATION:
84 case NFTNL_SET_ELEM_USERDATA:
87 case NFTNL_SET_ELEM_EXPR:
88 nftnl_expr_free(s->expr);
90 case NFTNL_SET_ELEM_OBJREF:
97 s->flags &= ~(1 << attr);
100 static uint32_t nftnl_set_elem_validate[NFTNL_SET_ELEM_MAX + 1] = {
101 [NFTNL_SET_ELEM_FLAGS] =
sizeof(uint32_t),
102 [NFTNL_SET_ELEM_VERDICT] =
sizeof(uint32_t),
103 [NFTNL_SET_ELEM_TIMEOUT] =
sizeof(uint64_t),
104 [NFTNL_SET_ELEM_EXPIRATION] =
sizeof(uint64_t),
107 EXPORT_SYMBOL(nftnl_set_elem_set);
108 int nftnl_set_elem_set(
struct nftnl_set_elem *s, uint16_t attr,
109 const void *data, uint32_t data_len)
111 nftnl_assert_attr_exists(attr, NFTNL_SET_ELEM_MAX);
112 nftnl_assert_validate(data, nftnl_set_elem_validate, attr, data_len);
115 case NFTNL_SET_ELEM_FLAGS:
116 memcpy(&s->set_elem_flags, data,
sizeof(s->set_elem_flags));
118 case NFTNL_SET_ELEM_KEY:
119 memcpy(&s->key.val, data, data_len);
120 s->key.len = data_len;
122 case NFTNL_SET_ELEM_KEY_END:
123 memcpy(&s->key_end.val, data, data_len);
124 s->key_end.len = data_len;
126 case NFTNL_SET_ELEM_VERDICT:
127 memcpy(&s->data.verdict, data,
sizeof(s->data.verdict));
129 case NFTNL_SET_ELEM_CHAIN:
130 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
131 xfree(s->data.chain);
133 s->data.chain = strdup(data);
137 case NFTNL_SET_ELEM_DATA:
138 memcpy(s->data.val, data, data_len);
139 s->data.len = data_len;
141 case NFTNL_SET_ELEM_TIMEOUT:
142 memcpy(&s->timeout, data,
sizeof(s->timeout));
144 case NFTNL_SET_ELEM_EXPIRATION:
145 memcpy(&s->expiration, data,
sizeof(s->expiration));
147 case NFTNL_SET_ELEM_USERDATA:
148 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
151 s->user.data = malloc(data_len);
154 memcpy(s->user.data, data, data_len);
155 s->user.len = data_len;
157 case NFTNL_SET_ELEM_OBJREF:
158 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
161 s->objref = strdup(data);
165 case NFTNL_SET_ELEM_EXPR:
166 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
167 nftnl_expr_free(s->expr);
169 s->expr = (
void *)data;
172 s->flags |= (1 << attr);
176 EXPORT_SYMBOL(nftnl_set_elem_set_u32);
177 void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
179 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
182 EXPORT_SYMBOL(nftnl_set_elem_set_u64);
183 void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
185 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
188 EXPORT_SYMBOL(nftnl_set_elem_set_str);
189 int nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
191 return nftnl_set_elem_set(s, attr, str, strlen(str) + 1);
194 EXPORT_SYMBOL(nftnl_set_elem_get);
195 const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
197 if (!(s->flags & (1 << attr)))
201 case NFTNL_SET_ELEM_FLAGS:
202 *data_len =
sizeof(s->set_elem_flags);
203 return &s->set_elem_flags;
204 case NFTNL_SET_ELEM_KEY:
205 *data_len = s->key.len;
207 case NFTNL_SET_ELEM_KEY_END:
208 *data_len = s->key_end.len;
209 return &s->key_end.val;
210 case NFTNL_SET_ELEM_VERDICT:
211 *data_len =
sizeof(s->data.verdict);
212 return &s->data.verdict;
213 case NFTNL_SET_ELEM_CHAIN:
214 *data_len = strlen(s->data.chain) + 1;
215 return s->data.chain;
216 case NFTNL_SET_ELEM_DATA:
217 *data_len = s->data.len;
219 case NFTNL_SET_ELEM_TIMEOUT:
220 *data_len =
sizeof(s->timeout);
222 case NFTNL_SET_ELEM_EXPIRATION:
223 *data_len =
sizeof(s->expiration);
224 return &s->expiration;
225 case NFTNL_SET_ELEM_USERDATA:
226 *data_len = s->user.len;
228 case NFTNL_SET_ELEM_EXPR:
230 case NFTNL_SET_ELEM_OBJREF:
231 *data_len = strlen(s->objref) + 1;
237 EXPORT_SYMBOL(nftnl_set_elem_get_str);
238 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
242 return nftnl_set_elem_get(s, attr, &size);
245 EXPORT_SYMBOL(nftnl_set_elem_get_u32);
246 uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
250 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
255 EXPORT_SYMBOL(nftnl_set_elem_get_u64);
256 uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
261 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
266 struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
268 struct nftnl_set_elem *newelem;
270 newelem = nftnl_set_elem_alloc();
274 memcpy(newelem, elem,
sizeof(*elem));
276 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
277 newelem->data.chain = strdup(elem->data.chain);
278 if (!newelem->data.chain)
284 nftnl_set_elem_free(newelem);
288 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
289 struct nftnl_set_elem *e)
291 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
292 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
293 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
294 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
295 if (e->flags & (1 << NFTNL_SET_ELEM_EXPIRATION))
296 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_EXPIRATION, htobe64(e->expiration));
297 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
298 struct nlattr *nest1;
300 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
301 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
302 mnl_attr_nest_end(nlh, nest1);
304 if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
305 struct nlattr *nest1;
307 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY_END);
308 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key_end.len,
310 mnl_attr_nest_end(nlh, nest1);
312 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
313 struct nlattr *nest1, *nest2;
315 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
316 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
317 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
318 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
319 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
321 mnl_attr_nest_end(nlh, nest1);
322 mnl_attr_nest_end(nlh, nest2);
324 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
325 struct nlattr *nest1;
327 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
328 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
329 mnl_attr_nest_end(nlh, nest1);
331 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
332 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
333 if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
334 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
335 if (e->flags & (1 << NFTNL_SET_ELEM_EXPR)) {
336 struct nlattr *nest1;
338 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR);
339 nftnl_expr_build_payload(nlh, e->expr);
340 mnl_attr_nest_end(nlh, nest1);
344 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
345 const struct nftnl_set *s)
347 if (s->flags & (1 << NFTNL_SET_NAME))
348 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
349 if (s->flags & (1 << NFTNL_SET_ID))
350 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
351 if (s->flags & (1 << NFTNL_SET_TABLE))
352 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
355 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
356 struct nftnl_set_elem *elem,
int i)
358 struct nlattr *nest2;
360 nest2 = mnl_attr_nest_start(nlh, i);
361 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
362 mnl_attr_nest_end(nlh, nest2);
367 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
368 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
370 struct nftnl_set_elem *elem;
371 struct nlattr *nest1;
374 nftnl_set_elem_nlmsg_build_def(nlh, s);
376 if (list_empty(&s->element_list))
379 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
380 list_for_each_entry(elem, &s->element_list, head)
381 nftnl_set_elem_build(nlh, elem, ++i);
383 mnl_attr_nest_end(nlh, nest1);
386 static
int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr,
void *data)
388 const struct nlattr **tb = data;
389 int type = mnl_attr_get_type(attr);
391 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
395 case NFTA_SET_ELEM_FLAGS:
396 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
399 case NFTA_SET_ELEM_TIMEOUT:
400 case NFTA_SET_ELEM_EXPIRATION:
401 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
404 case NFTA_SET_ELEM_KEY:
405 case NFTA_SET_ELEM_KEY_END:
406 case NFTA_SET_ELEM_DATA:
407 case NFTA_SET_ELEM_EXPR:
408 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
411 case NFTA_SET_ELEM_USERDATA:
412 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
421 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
423 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
424 struct nftnl_set_elem *e;
427 e = nftnl_set_elem_alloc();
431 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
435 if (tb[NFTA_SET_ELEM_FLAGS]) {
437 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
438 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
440 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
441 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
442 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
444 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
445 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
446 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
448 if (tb[NFTA_SET_ELEM_KEY]) {
449 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
452 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
454 if (tb[NFTA_SET_ELEM_KEY_END]) {
455 ret = nftnl_parse_data(&e->key_end, tb[NFTA_SET_ELEM_KEY_END],
459 e->flags |= (1 << NFTNL_SET_ELEM_KEY_END);
461 if (tb[NFTA_SET_ELEM_DATA]) {
462 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
467 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
470 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
471 (1 << NFTNL_SET_ELEM_CHAIN);
474 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
478 if (tb[NFTA_SET_ELEM_EXPR]) {
479 e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
480 if (e->expr == NULL) {
484 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
486 if (tb[NFTA_SET_ELEM_USERDATA]) {
488 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
490 if (e->flags & (1 << NFTNL_RULE_USERDATA))
493 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
494 e->user.data = malloc(e->user.len);
495 if (e->user.data == NULL) {
499 memcpy(e->user.data, udata, e->user.len);
500 e->flags |= (1 << NFTNL_RULE_USERDATA);
502 if (tb[NFTA_SET_ELEM_OBJREF]) {
503 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
504 if (e->objref == NULL) {
508 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
512 list_add_tail(&e->head, &s->element_list);
516 nftnl_expr_free(e->expr);
518 nftnl_set_elem_free(e);
523 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
525 const struct nlattr **tb = data;
526 int type = mnl_attr_get_type(attr);
528 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
532 case NFTA_SET_ELEM_LIST_TABLE:
533 case NFTA_SET_ELEM_LIST_SET:
534 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
537 case NFTA_SET_ELEM_LIST_ELEMENTS:
538 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
547 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
552 mnl_attr_for_each_nested(attr, nest) {
553 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
556 ret = nftnl_set_elems_parse2(s, attr);
563 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
564 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
566 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
567 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
570 if (mnl_attr_parse(nlh,
sizeof(*nfg),
571 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
574 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
575 if (s->flags & (1 << NFTNL_SET_TABLE))
578 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
581 s->flags |= (1 << NFTNL_SET_TABLE);
583 if (tb[NFTA_SET_ELEM_LIST_SET]) {
584 if (s->flags & (1 << NFTNL_SET_NAME))
587 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
590 s->flags |= (1 << NFTNL_SET_NAME);
592 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
593 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
594 s->flags |= (1 << NFTNL_SET_ID);
596 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
597 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
602 s->family = nfg->nfgen_family;
603 s->flags |= (1 << NFTNL_SET_FAMILY);
608 EXPORT_SYMBOL(nftnl_set_elem_parse);
609 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
610 const char *data,
struct nftnl_parse_err *err)
616 EXPORT_SYMBOL(nftnl_set_elem_parse_file);
617 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
618 FILE *fp,
struct nftnl_parse_err *err)
624 static int nftnl_set_elem_snprintf_default(
char *buf,
size_t size,
625 const struct nftnl_set_elem *e)
627 int ret, remain = size, offset = 0, i;
629 ret = snprintf(buf, remain,
"element ");
630 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
632 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
633 ret = snprintf(buf + offset, remain,
"%.8x ", e->key.val[i]);
634 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
637 ret = snprintf(buf + offset, remain,
" : ");
638 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
640 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
641 ret = snprintf(buf + offset, remain,
"%.8x ", e->data.val[i]);
642 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
645 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
646 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
649 ret = snprintf(buf + offset, remain,
" userdata = {");
650 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
652 for (i = 0; i < e->user.len; i++) {
653 char *c = e->user.data;
655 ret = snprintf(buf + offset, remain,
"%c",
656 isalnum(c[i]) ? c[i] : 0);
657 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
660 ret = snprintf(buf + offset, remain,
" }\n");
661 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
667 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t size,
668 const struct nftnl_set_elem *e,
669 uint32_t cmd, uint32_t type,
672 int ret, remain = size, offset = 0;
675 case NFTNL_OUTPUT_DEFAULT:
676 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e);
677 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
679 case NFTNL_OUTPUT_XML:
680 case NFTNL_OUTPUT_JSON:
689 EXPORT_SYMBOL(nftnl_set_elem_snprintf);
690 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
691 const struct nftnl_set_elem *e,
692 uint32_t type, uint32_t flags)
697 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
701 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
702 uint32_t cmd, uint32_t type,
705 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
708 EXPORT_SYMBOL(nftnl_set_elem_fprintf);
709 int nftnl_set_elem_fprintf(FILE *fp,
struct nftnl_set_elem *se, uint32_t type,
712 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
713 nftnl_set_elem_do_snprintf);
716 EXPORT_SYMBOL(nftnl_set_elem_foreach);
717 int nftnl_set_elem_foreach(
struct nftnl_set *s,
718 int (*cb)(
struct nftnl_set_elem *e,
void *data),
721 struct nftnl_set_elem *elem;
724 list_for_each_entry(elem, &s->element_list, head) {
725 ret = cb(elem, data);
733 const struct nftnl_set *set;
734 const struct list_head *list;
735 struct nftnl_set_elem *cur;
738 EXPORT_SYMBOL(nftnl_set_elems_iter_create);
740 nftnl_set_elems_iter_create(
const struct nftnl_set *s)
749 iter->list = &s->element_list;
750 if (list_empty(&s->element_list))
753 iter->cur = list_entry(s->element_list.next,
754 struct nftnl_set_elem, head);
759 EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
760 struct nftnl_set_elem *
766 EXPORT_SYMBOL(nftnl_set_elems_iter_next);
769 struct nftnl_set_elem *s = iter->cur;
774 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
775 if (&iter->cur->head == iter->list->next)
781 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
787 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
788 const struct nlattr *from,
789 const struct nlattr *to)
791 int len = (
void *)to + to->nla_len - (
void *)from;
797 if (len > UINT16_MAX) {
798 nlh->nlmsg_len -= to->nla_len;
804 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);
805 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
808 struct nftnl_set_elem *elem;
809 struct nlattr *nest1, *nest2;
812 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
815 if (list_empty(&iter->set->element_list))
818 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
819 elem = nftnl_set_elems_iter_next(iter);
820 while (elem != NULL) {
821 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
822 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
824 iter->cur = list_entry(iter->cur->head.prev,
825 struct nftnl_set_elem, head);
829 elem = nftnl_set_elems_iter_next(iter);
831 mnl_attr_nest_end(nlh, nest1);