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 struct nftnl_set_elem *nftnl_set_elem_alloc(
void)
32 struct nftnl_set_elem *s;
34 s = calloc(1,
sizeof(
struct nftnl_set_elem));
40 EXPORT_SYMBOL(nftnl_set_elem_alloc);
42 void nftnl_set_elem_free(
struct nftnl_set_elem *s)
44 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
47 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
48 nftnl_expr_free(s->expr);
50 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
53 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
58 EXPORT_SYMBOL(nftnl_set_elem_free);
60 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
62 return s->flags & (1 << attr);
64 EXPORT_SYMBOL(nftnl_set_elem_is_set);
66 void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
68 if (!(s->flags & (1 << attr)))
72 case NFTNL_SET_ELEM_CHAIN:
75 case NFTNL_SET_ELEM_FLAGS:
76 case NFTNL_SET_ELEM_KEY:
77 case NFTNL_SET_ELEM_VERDICT:
78 case NFTNL_SET_ELEM_DATA:
79 case NFTNL_SET_ELEM_TIMEOUT:
80 case NFTNL_SET_ELEM_EXPIRATION:
82 case NFTNL_SET_ELEM_USERDATA:
85 case NFTNL_SET_ELEM_EXPR:
86 nftnl_expr_free(s->expr);
88 case NFTNL_SET_ELEM_OBJREF:
95 s->flags &= ~(1 << attr);
97 EXPORT_SYMBOL(nftnl_set_elem_unset);
99 int nftnl_set_elem_set(
struct nftnl_set_elem *s, uint16_t attr,
100 const void *data, uint32_t data_len)
103 case NFTNL_SET_ELEM_FLAGS:
104 s->set_elem_flags = *((uint32_t *)data);
106 case NFTNL_SET_ELEM_KEY:
107 memcpy(&s->key.val, data, data_len);
108 s->key.len = data_len;
110 case NFTNL_SET_ELEM_VERDICT:
111 s->data.verdict = *((uint32_t *)data);
113 case NFTNL_SET_ELEM_CHAIN:
114 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
115 xfree(s->data.chain);
117 s->data.chain = strdup(data);
121 case NFTNL_SET_ELEM_DATA:
122 memcpy(s->data.val, data, data_len);
123 s->data.len = data_len;
125 case NFTNL_SET_ELEM_TIMEOUT:
126 s->timeout = *((uint64_t *)data);
128 case NFTNL_SET_ELEM_USERDATA:
129 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
132 s->user.data = malloc(data_len);
135 memcpy(s->user.data, data, data_len);
136 s->user.len = data_len;
138 case NFTNL_SET_ELEM_OBJREF:
139 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
142 s->objref = strdup(data);
147 s->flags |= (1 << attr);
150 EXPORT_SYMBOL(nftnl_set_elem_set);
152 void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
154 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
156 EXPORT_SYMBOL(nftnl_set_elem_set_u32);
158 void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
160 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
162 EXPORT_SYMBOL(nftnl_set_elem_set_u64);
164 int nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
166 return nftnl_set_elem_set(s, attr, str, strlen(str) + 1);
168 EXPORT_SYMBOL(nftnl_set_elem_set_str);
170 const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
172 if (!(s->flags & (1 << attr)))
176 case NFTNL_SET_ELEM_FLAGS:
177 *data_len =
sizeof(s->set_elem_flags);
178 return &s->set_elem_flags;
179 case NFTNL_SET_ELEM_KEY:
180 *data_len = s->key.len;
182 case NFTNL_SET_ELEM_VERDICT:
183 *data_len =
sizeof(s->data.verdict);
184 return &s->data.verdict;
185 case NFTNL_SET_ELEM_CHAIN:
186 *data_len = strlen(s->data.chain) + 1;
187 return s->data.chain;
188 case NFTNL_SET_ELEM_DATA:
189 *data_len = s->data.len;
191 case NFTNL_SET_ELEM_TIMEOUT:
192 *data_len =
sizeof(s->timeout);
194 case NFTNL_SET_ELEM_EXPIRATION:
195 *data_len =
sizeof(s->expiration);
196 return &s->expiration;
197 case NFTNL_SET_ELEM_USERDATA:
198 *data_len = s->user.len;
200 case NFTNL_SET_ELEM_EXPR:
202 case NFTNL_SET_ELEM_OBJREF:
203 *data_len = strlen(s->objref) + 1;
208 EXPORT_SYMBOL(nftnl_set_elem_get);
210 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
214 return nftnl_set_elem_get(s, attr, &size);
216 EXPORT_SYMBOL(nftnl_set_elem_get_str);
218 uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
221 uint32_t val = *((uint32_t *)nftnl_set_elem_get(s, attr, &size));
224 EXPORT_SYMBOL(nftnl_set_elem_get_u32);
226 uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
229 uint64_t val = *((uint64_t *)nftnl_set_elem_get(s, attr, &size));
232 EXPORT_SYMBOL(nftnl_set_elem_get_u64);
234 struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
236 struct nftnl_set_elem *newelem;
238 newelem = nftnl_set_elem_alloc();
242 memcpy(newelem, elem,
sizeof(*elem));
244 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
245 newelem->data.chain = strdup(elem->data.chain);
246 if (!newelem->data.chain)
252 nftnl_set_elem_free(newelem);
256 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
257 struct nftnl_set_elem *e)
259 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
260 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
261 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
262 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
263 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
264 struct nlattr *nest1;
266 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
267 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
268 mnl_attr_nest_end(nlh, nest1);
270 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
271 struct nlattr *nest1, *nest2;
273 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
274 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
275 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
276 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
277 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
279 mnl_attr_nest_end(nlh, nest1);
280 mnl_attr_nest_end(nlh, nest2);
282 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
283 struct nlattr *nest1;
285 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
286 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
287 mnl_attr_nest_end(nlh, nest1);
289 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
290 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
291 if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
292 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
295 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
296 const struct nftnl_set *s)
298 if (s->flags & (1 << NFTNL_SET_NAME))
299 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
300 if (s->flags & (1 << NFTNL_SET_ID))
301 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
302 if (s->flags & (1 << NFTNL_SET_TABLE))
303 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
306 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
307 struct nftnl_set_elem *elem,
int i)
309 struct nlattr *nest2;
311 nest2 = mnl_attr_nest_start(nlh, i);
312 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
313 mnl_attr_nest_end(nlh, nest2);
318 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
320 struct nftnl_set_elem *elem;
321 struct nlattr *nest1;
324 nftnl_set_elem_nlmsg_build_def(nlh, s);
326 if (list_empty(&s->element_list))
329 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
330 list_for_each_entry(elem, &s->element_list, head)
331 nftnl_set_elem_build(nlh, elem, ++i);
333 mnl_attr_nest_end(nlh, nest1);
335 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
337 static
int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr,
void *data)
339 const struct nlattr **tb = data;
340 int type = mnl_attr_get_type(attr);
342 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
346 case NFTA_SET_ELEM_FLAGS:
347 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
350 case NFTA_SET_ELEM_TIMEOUT:
351 case NFTA_SET_ELEM_EXPIRATION:
352 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
355 case NFTA_SET_ELEM_KEY:
356 case NFTA_SET_ELEM_DATA:
357 case NFTA_SET_ELEM_EXPR:
358 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
361 case NFTA_SET_ELEM_USERDATA:
362 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
371 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
373 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
374 struct nftnl_set_elem *e;
377 e = nftnl_set_elem_alloc();
381 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
385 if (tb[NFTA_SET_ELEM_FLAGS]) {
387 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
388 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
390 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
391 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
392 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
394 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
395 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
396 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
398 if (tb[NFTA_SET_ELEM_KEY]) {
399 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
402 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
404 if (tb[NFTA_SET_ELEM_DATA]) {
405 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
410 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
413 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
414 (1 << NFTNL_SET_ELEM_CHAIN);
417 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
421 if (tb[NFTA_SET_ELEM_EXPR]) {
422 e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
423 if (e->expr == NULL) {
427 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
429 if (tb[NFTA_SET_ELEM_USERDATA]) {
431 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
433 if (e->flags & (1 << NFTNL_RULE_USERDATA))
436 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
437 e->user.data = malloc(e->user.len);
438 if (e->user.data == NULL) {
442 memcpy(e->user.data, udata, e->user.len);
443 e->flags |= (1 << NFTNL_RULE_USERDATA);
445 if (tb[NFTA_SET_ELEM_OBJREF]) {
446 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
447 if (e->objref == NULL) {
451 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
455 list_add_tail(&e->head, &s->element_list);
459 nftnl_expr_free(e->expr);
461 nftnl_set_elem_free(e);
466 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
468 const struct nlattr **tb = data;
469 int type = mnl_attr_get_type(attr);
471 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
475 case NFTA_SET_ELEM_LIST_TABLE:
476 case NFTA_SET_ELEM_LIST_SET:
477 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
480 case NFTA_SET_ELEM_LIST_ELEMENTS:
481 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
490 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
495 mnl_attr_for_each_nested(attr, nest) {
496 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
499 ret = nftnl_set_elems_parse2(s, attr);
506 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
508 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
509 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
512 if (mnl_attr_parse(nlh,
sizeof(*nfg),
513 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
516 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
517 if (s->flags & (1 << NFTNL_SET_TABLE))
520 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
523 s->flags |= (1 << NFTNL_SET_TABLE);
525 if (tb[NFTA_SET_ELEM_LIST_SET]) {
526 if (s->flags & (1 << NFTNL_SET_NAME))
529 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
532 s->flags |= (1 << NFTNL_SET_NAME);
534 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
535 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
536 s->flags |= (1 << NFTNL_SET_ID);
538 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
539 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
544 s->family = nfg->nfgen_family;
545 s->flags |= (1 << NFTNL_SET_FAMILY);
549 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
551 static int nftnl_set_elem_json_parse(
struct nftnl_set_elem *e,
const void *json,
552 struct nftnl_parse_err *err,
553 enum nftnl_parse_input input)
559 tree = nftnl_jansson_create_root(json, &error, err, input);
563 return nftnl_jansson_set_elem_parse(e, tree, err);
571 nftnl_set_elem_do_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
572 const void *data,
struct nftnl_parse_err *err,
573 enum nftnl_parse_input input)
578 case NFTNL_PARSE_JSON:
579 ret = nftnl_set_elem_json_parse(e, data, err, input);
581 case NFTNL_PARSE_XML:
590 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
591 const char *data,
struct nftnl_parse_err *err)
593 return nftnl_set_elem_do_parse(e, type, data, err, NFTNL_PARSE_BUFFER);
595 EXPORT_SYMBOL(nftnl_set_elem_parse);
597 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
598 FILE *fp,
struct nftnl_parse_err *err)
600 return nftnl_set_elem_do_parse(e, type, fp, err, NFTNL_PARSE_FILE);
602 EXPORT_SYMBOL(nftnl_set_elem_parse_file);
604 static int nftnl_set_elem_snprintf_json(
char *buf,
size_t size,
605 const struct nftnl_set_elem *e,
608 int ret, remain = size, offset = 0, type = -1;
610 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
611 ret = snprintf(buf, remain,
"\"flags\":%u,", e->set_elem_flags);
612 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
615 ret = snprintf(buf + offset, remain,
"\"key\":{");
616 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
618 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key,
619 NFTNL_OUTPUT_JSON, flags, DATA_VALUE);
620 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
622 ret = snprintf(buf + offset, remain,
"}");
623 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
625 if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
627 else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
629 else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
633 ret = snprintf(buf + offset, remain,
",\"data\":{");
634 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
636 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
637 NFTNL_OUTPUT_JSON, flags, type);
638 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
640 ret = snprintf(buf + offset, remain,
"}");
641 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
647 static int nftnl_set_elem_snprintf_default(
char *buf,
size_t size,
648 const struct nftnl_set_elem *e)
650 int ret, remain = size, offset = 0, i;
652 ret = snprintf(buf, remain,
"element ");
653 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
655 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
656 ret = snprintf(buf + offset, remain,
"%.8x ", e->key.val[i]);
657 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
660 ret = snprintf(buf + offset, remain,
" : ");
661 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
663 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
664 ret = snprintf(buf + offset, remain,
"%.8x ", e->data.val[i]);
665 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
668 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
669 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
672 ret = snprintf(buf + offset, remain,
" userdata = {");
673 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
675 for (i = 0; i < e->user.len; i++) {
676 char *c = e->user.data;
678 ret = snprintf(buf + offset, remain,
"%c",
679 isalnum(c[i]) ? c[i] : 0);
680 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
683 ret = snprintf(buf + offset, remain,
" }\n");
684 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
690 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t size,
691 const struct nftnl_set_elem *e,
692 uint32_t cmd, uint32_t type,
695 int ret, remain = size, offset = 0;
697 if (type == NFTNL_OUTPUT_XML)
700 ret = nftnl_cmd_header_snprintf(buf + offset, remain, cmd, type, flags);
701 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
704 case NFTNL_OUTPUT_DEFAULT:
705 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e);
707 case NFTNL_OUTPUT_JSON:
708 ret = nftnl_set_elem_snprintf_json(buf + offset, remain, e,
715 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
717 ret = nftnl_cmd_footer_snprintf(buf + offset, remain, cmd, type, flags);
718 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
723 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
724 const struct nftnl_set_elem *e,
725 uint32_t type, uint32_t flags)
730 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
733 EXPORT_SYMBOL(nftnl_set_elem_snprintf);
735 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
736 uint32_t cmd, uint32_t type,
739 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
742 int nftnl_set_elem_fprintf(FILE *fp,
struct nftnl_set_elem *se, uint32_t type,
745 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
746 nftnl_set_elem_do_snprintf);
748 EXPORT_SYMBOL(nftnl_set_elem_fprintf);
750 int nftnl_set_elem_foreach(
struct nftnl_set *s,
751 int (*cb)(
struct nftnl_set_elem *e,
void *data),
754 struct nftnl_set_elem *elem;
757 list_for_each_entry(elem, &s->element_list, head) {
758 ret = cb(elem, data);
764 EXPORT_SYMBOL(nftnl_set_elem_foreach);
767 const struct nftnl_set *set;
768 const struct list_head *list;
769 struct nftnl_set_elem *cur;
773 nftnl_set_elems_iter_create(
const struct nftnl_set *s)
782 iter->list = &s->element_list;
783 if (list_empty(&s->element_list))
786 iter->cur = list_entry(s->element_list.next,
787 struct nftnl_set_elem, head);
791 EXPORT_SYMBOL(nftnl_set_elems_iter_create);
793 struct nftnl_set_elem *
798 EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
802 struct nftnl_set_elem *s = iter->cur;
807 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
808 if (&iter->cur->head == iter->list->next)
813 EXPORT_SYMBOL(nftnl_set_elems_iter_next);
819 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
821 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
822 const struct nlattr *from,
823 const struct nlattr *to)
825 int len = (
void *)to + to->nla_len - (
void *)from;
831 if (len > UINT16_MAX) {
832 nlh->nlmsg_len -= to->nla_len;
838 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
841 struct nftnl_set_elem *elem;
842 struct nlattr *nest1, *nest2;
845 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
848 if (list_empty(&iter->set->element_list))
851 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
852 elem = nftnl_set_elems_iter_next(iter);
853 while (elem != NULL) {
854 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
855 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
857 iter->cur = list_entry(iter->cur->head.prev,
858 struct nftnl_set_elem, head);
862 elem = nftnl_set_elems_iter_next(iter);
864 mnl_attr_nest_end(nlh, nest1);
868 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);