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>
30EXPORT_SYMBOL(nftnl_set_elem_alloc);
31struct nftnl_set_elem *nftnl_set_elem_alloc(
void)
33 struct nftnl_set_elem *s;
35 s = calloc(1,
sizeof(
struct nftnl_set_elem));
39 INIT_LIST_HEAD(&s->expr_list);
44EXPORT_SYMBOL(nftnl_set_elem_free);
45void nftnl_set_elem_free(
struct nftnl_set_elem *s)
47 struct nftnl_expr *e, *tmp;
49 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
52 list_for_each_entry_safe(e, tmp, &s->expr_list, head)
55 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
58 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
64EXPORT_SYMBOL(nftnl_set_elem_is_set);
65bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
67 return s->flags & (1 << attr);
70EXPORT_SYMBOL(nftnl_set_elem_unset);
71void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
73 struct nftnl_expr *expr, *tmp;
75 if (!(s->flags & (1 << attr)))
79 case NFTNL_SET_ELEM_CHAIN:
82 case NFTNL_SET_ELEM_FLAGS:
83 case NFTNL_SET_ELEM_KEY:
84 case NFTNL_SET_ELEM_KEY_END:
85 case NFTNL_SET_ELEM_VERDICT:
86 case NFTNL_SET_ELEM_DATA:
87 case NFTNL_SET_ELEM_TIMEOUT:
88 case NFTNL_SET_ELEM_EXPIRATION:
90 case NFTNL_SET_ELEM_USERDATA:
93 case NFTNL_SET_ELEM_EXPR:
94 case NFTNL_SET_ELEM_EXPRESSIONS:
95 list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
96 nftnl_expr_free(expr);
98 case NFTNL_SET_ELEM_OBJREF:
105 s->flags &= ~(1 << attr);
108static uint32_t nftnl_set_elem_validate[NFTNL_SET_ELEM_MAX + 1] = {
109 [NFTNL_SET_ELEM_FLAGS] =
sizeof(uint32_t),
110 [NFTNL_SET_ELEM_VERDICT] =
sizeof(uint32_t),
111 [NFTNL_SET_ELEM_TIMEOUT] =
sizeof(uint64_t),
112 [NFTNL_SET_ELEM_EXPIRATION] =
sizeof(uint64_t),
115EXPORT_SYMBOL(nftnl_set_elem_set);
116int nftnl_set_elem_set(
struct nftnl_set_elem *s, uint16_t attr,
117 const void *data, uint32_t data_len)
119 struct nftnl_expr *expr, *tmp;
121 nftnl_assert_attr_exists(attr, NFTNL_SET_ELEM_MAX);
122 nftnl_assert_validate(data, nftnl_set_elem_validate, attr, data_len);
125 case NFTNL_SET_ELEM_FLAGS:
126 memcpy(&s->set_elem_flags, data,
sizeof(s->set_elem_flags));
128 case NFTNL_SET_ELEM_KEY:
129 memcpy(&s->key.val, data, data_len);
130 s->key.len = data_len;
132 case NFTNL_SET_ELEM_KEY_END:
133 memcpy(&s->key_end.val, data, data_len);
134 s->key_end.len = data_len;
136 case NFTNL_SET_ELEM_VERDICT:
137 memcpy(&s->data.verdict, data,
sizeof(s->data.verdict));
139 case NFTNL_SET_ELEM_CHAIN:
140 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
141 xfree(s->data.chain);
143 s->data.chain = strdup(data);
147 case NFTNL_SET_ELEM_DATA:
148 memcpy(s->data.val, data, data_len);
149 s->data.len = data_len;
151 case NFTNL_SET_ELEM_TIMEOUT:
152 memcpy(&s->timeout, data,
sizeof(s->timeout));
154 case NFTNL_SET_ELEM_EXPIRATION:
155 memcpy(&s->expiration, data,
sizeof(s->expiration));
157 case NFTNL_SET_ELEM_USERDATA:
158 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
161 s->user.data = malloc(data_len);
164 memcpy(s->user.data, data, data_len);
165 s->user.len = data_len;
167 case NFTNL_SET_ELEM_OBJREF:
168 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
171 s->objref = strdup(data);
175 case NFTNL_SET_ELEM_EXPR:
176 list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
177 nftnl_expr_free(expr);
180 list_add(&expr->head, &s->expr_list);
183 s->flags |= (1 << attr);
187EXPORT_SYMBOL(nftnl_set_elem_set_u32);
188void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
190 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
193EXPORT_SYMBOL(nftnl_set_elem_set_u64);
194void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
196 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
199EXPORT_SYMBOL(nftnl_set_elem_set_str);
200int nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
202 return nftnl_set_elem_set(s, attr, str, strlen(str) + 1);
205EXPORT_SYMBOL(nftnl_set_elem_get);
206const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
208 struct nftnl_expr *expr;
210 if (!(s->flags & (1 << attr)))
214 case NFTNL_SET_ELEM_FLAGS:
215 *data_len =
sizeof(s->set_elem_flags);
216 return &s->set_elem_flags;
217 case NFTNL_SET_ELEM_KEY:
218 *data_len = s->key.len;
220 case NFTNL_SET_ELEM_KEY_END:
221 *data_len = s->key_end.len;
222 return &s->key_end.val;
223 case NFTNL_SET_ELEM_VERDICT:
224 *data_len =
sizeof(s->data.verdict);
225 return &s->data.verdict;
226 case NFTNL_SET_ELEM_CHAIN:
227 *data_len = strlen(s->data.chain) + 1;
228 return s->data.chain;
229 case NFTNL_SET_ELEM_DATA:
230 *data_len = s->data.len;
232 case NFTNL_SET_ELEM_TIMEOUT:
233 *data_len =
sizeof(s->timeout);
235 case NFTNL_SET_ELEM_EXPIRATION:
236 *data_len =
sizeof(s->expiration);
237 return &s->expiration;
238 case NFTNL_SET_ELEM_USERDATA:
239 *data_len = s->user.len;
241 case NFTNL_SET_ELEM_EXPR:
242 list_for_each_entry(expr, &s->expr_list, head)
245 case NFTNL_SET_ELEM_OBJREF:
246 *data_len = strlen(s->objref) + 1;
252EXPORT_SYMBOL(nftnl_set_elem_get_str);
253const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
257 return nftnl_set_elem_get(s, attr, &size);
260EXPORT_SYMBOL(nftnl_set_elem_get_u32);
261uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
265 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
270EXPORT_SYMBOL(nftnl_set_elem_get_u64);
271uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
276 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
281struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
283 struct nftnl_set_elem *newelem;
285 newelem = nftnl_set_elem_alloc();
289 memcpy(newelem, elem,
sizeof(*elem));
291 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
292 newelem->data.chain = strdup(elem->data.chain);
293 if (!newelem->data.chain)
299 nftnl_set_elem_free(newelem);
303EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build_payload);
304void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
305 struct nftnl_set_elem *e)
307 struct nftnl_expr *expr;
310 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
311 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
312 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
313 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
314 if (e->flags & (1 << NFTNL_SET_ELEM_EXPIRATION))
315 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_EXPIRATION, htobe64(e->expiration));
316 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
317 struct nlattr *nest1;
319 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
320 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
321 mnl_attr_nest_end(nlh, nest1);
323 if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
324 struct nlattr *nest1;
326 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY_END);
327 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key_end.len,
329 mnl_attr_nest_end(nlh, nest1);
331 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
332 struct nlattr *nest1, *nest2;
334 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
335 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
336 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
337 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
338 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
340 mnl_attr_nest_end(nlh, nest1);
341 mnl_attr_nest_end(nlh, nest2);
343 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
344 struct nlattr *nest1;
346 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
347 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
348 mnl_attr_nest_end(nlh, nest1);
350 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
351 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
352 if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
353 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
355 if (!list_empty(&e->expr_list)) {
356 list_for_each_entry(expr, &e->expr_list, head)
359 if (num_exprs == 1) {
360 struct nlattr *nest1;
362 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR);
363 list_for_each_entry(expr, &e->expr_list, head)
364 nftnl_expr_build_payload(nlh, expr);
366 mnl_attr_nest_end(nlh, nest1);
367 }
else if (num_exprs > 1) {
368 struct nlattr *nest1, *nest2;
370 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPRESSIONS);
371 list_for_each_entry(expr, &e->expr_list, head) {
372 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
373 nftnl_expr_build_payload(nlh, expr);
374 mnl_attr_nest_end(nlh, nest2);
376 mnl_attr_nest_end(nlh, nest1);
381static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
382 const struct nftnl_set *s)
384 if (s->flags & (1 << NFTNL_SET_NAME))
385 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
386 if (s->flags & (1 << NFTNL_SET_ID))
387 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
388 if (s->flags & (1 << NFTNL_SET_TABLE))
389 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
392EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build);
393struct nlattr *nftnl_set_elem_nlmsg_build(
struct nlmsghdr *nlh,
394 struct nftnl_set_elem *elem,
int i)
396 struct nlattr *nest2;
398 nest2 = mnl_attr_nest_start(nlh, i);
399 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
400 mnl_attr_nest_end(nlh, nest2);
405EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
406void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
408 struct nftnl_set_elem *elem;
409 struct nlattr *nest1;
412 nftnl_set_elem_nlmsg_build_def(nlh, s);
414 if (list_empty(&s->element_list))
417 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
418 list_for_each_entry(elem, &s->element_list, head)
419 nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
421 mnl_attr_nest_end(nlh, nest1);
424EXPORT_SYMBOL(nftnl_set_elem_add_expr);
425void nftnl_set_elem_add_expr(
struct nftnl_set_elem *e,
struct nftnl_expr *expr)
427 list_add_tail(&expr->head, &e->expr_list);
430EXPORT_SYMBOL(nftnl_set_elem_expr_foreach);
431int nftnl_set_elem_expr_foreach(
struct nftnl_set_elem *e,
432 int (*cb)(
struct nftnl_expr *e,
void *data),
435 struct nftnl_expr *cur, *tmp;
438 list_for_each_entry_safe(cur, tmp, &e->expr_list, head) {
446static int nftnl_set_elem_parse_attr_cb(
const struct nlattr *attr,
void *data)
448 const struct nlattr **tb = data;
449 int type = mnl_attr_get_type(attr);
451 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
455 case NFTA_SET_ELEM_FLAGS:
456 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
459 case NFTA_SET_ELEM_TIMEOUT:
460 case NFTA_SET_ELEM_EXPIRATION:
461 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
464 case NFTA_SET_ELEM_KEY:
465 case NFTA_SET_ELEM_KEY_END:
466 case NFTA_SET_ELEM_DATA:
467 case NFTA_SET_ELEM_EXPR:
468 case NFTA_SET_ELEM_EXPRESSIONS:
469 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
472 case NFTA_SET_ELEM_USERDATA:
473 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
482static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
484 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
485 struct nftnl_set_elem *e;
488 e = nftnl_set_elem_alloc();
492 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
496 if (tb[NFTA_SET_ELEM_FLAGS]) {
498 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
499 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
501 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
502 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
503 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
505 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
506 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
507 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
509 if (tb[NFTA_SET_ELEM_KEY]) {
510 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
513 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
515 if (tb[NFTA_SET_ELEM_KEY_END]) {
516 ret = nftnl_parse_data(&e->key_end, tb[NFTA_SET_ELEM_KEY_END],
520 e->flags |= (1 << NFTNL_SET_ELEM_KEY_END);
522 if (tb[NFTA_SET_ELEM_DATA]) {
523 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
528 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
531 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
532 (1 << NFTNL_SET_ELEM_CHAIN);
535 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
539 if (tb[NFTA_SET_ELEM_EXPR]) {
540 struct nftnl_expr *expr;
542 expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
547 list_add_tail(&expr->head, &e->expr_list);
548 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
549 }
else if (tb[NFTA_SET_ELEM_EXPRESSIONS]) {
550 struct nftnl_expr *expr;
553 mnl_attr_for_each_nested(attr, tb[NFTA_SET_ELEM_EXPRESSIONS]) {
554 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) {
558 expr = nftnl_expr_parse(attr);
563 list_add_tail(&expr->head, &e->expr_list);
565 e->flags |= (1 << NFTNL_SET_ELEM_EXPRESSIONS);
567 if (tb[NFTA_SET_ELEM_USERDATA]) {
569 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
571 if (e->flags & (1 << NFTNL_RULE_USERDATA))
574 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
575 e->user.data = malloc(e->user.len);
576 if (e->user.data == NULL) {
580 memcpy(e->user.data, udata, e->user.len);
581 e->flags |= (1 << NFTNL_RULE_USERDATA);
583 if (tb[NFTA_SET_ELEM_OBJREF]) {
584 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
585 if (e->objref == NULL) {
589 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
593 list_add_tail(&e->head, &s->element_list);
597 nftnl_set_elem_free(e);
602nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
604 const struct nlattr **tb = data;
605 int type = mnl_attr_get_type(attr);
607 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
611 case NFTA_SET_ELEM_LIST_TABLE:
612 case NFTA_SET_ELEM_LIST_SET:
613 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
616 case NFTA_SET_ELEM_LIST_ELEMENTS:
617 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
626static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
631 mnl_attr_for_each_nested(attr, nest) {
632 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
635 ret = nftnl_set_elems_parse2(s, attr);
642EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
643int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
645 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
646 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
649 if (mnl_attr_parse(nlh,
sizeof(*nfg),
650 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
653 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
654 if (s->flags & (1 << NFTNL_SET_TABLE))
657 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
660 s->flags |= (1 << NFTNL_SET_TABLE);
662 if (tb[NFTA_SET_ELEM_LIST_SET]) {
663 if (s->flags & (1 << NFTNL_SET_NAME))
666 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
669 s->flags |= (1 << NFTNL_SET_NAME);
671 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
672 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
673 s->flags |= (1 << NFTNL_SET_ID);
675 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
676 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
681 s->family = nfg->nfgen_family;
682 s->flags |= (1 << NFTNL_SET_FAMILY);
687EXPORT_SYMBOL(nftnl_set_elem_parse);
688int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
689 const char *data,
struct nftnl_parse_err *err)
695EXPORT_SYMBOL(nftnl_set_elem_parse_file);
696int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
697 FILE *fp,
struct nftnl_parse_err *err)
703int nftnl_set_elem_snprintf_default(
char *buf,
size_t remain,
704 const struct nftnl_set_elem *e)
706 int ret, dregtype = DATA_VALUE, offset = 0, i;
708 ret = snprintf(buf, remain,
"element ");
709 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
711 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key,
712 DATA_F_NOPFX, DATA_VALUE);
713 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
715 if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
716 ret = snprintf(buf + offset, remain,
" - ");
717 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
719 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key_end,
720 DATA_F_NOPFX, DATA_VALUE);
721 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
724 ret = snprintf(buf + offset, remain,
" : ");
725 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
727 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
728 dregtype = DATA_VERDICT;
730 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
731 DATA_F_NOPFX, dregtype);
732 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
734 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
735 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
738 ret = snprintf(buf + offset, remain,
" userdata = { ");
739 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
741 for (i = 0; i < e->user.len; i++) {
742 char *c = e->user.data;
744 ret = snprintf(buf + offset, remain,
745 isprint(c[i]) ?
"%c" :
"\\x%02hhx",
747 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
750 ret = snprintf(buf + offset, remain,
" }");
751 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
757static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t remain,
758 const struct nftnl_set_elem *e,
759 uint32_t cmd, uint32_t type,
764 if (type != NFTNL_OUTPUT_DEFAULT)
767 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e);
768 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
773EXPORT_SYMBOL(nftnl_set_elem_snprintf);
774int nftnl_set_elem_snprintf(
char *buf,
size_t size,
775 const struct nftnl_set_elem *e,
776 uint32_t type, uint32_t flags)
781 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
785static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
786 uint32_t cmd, uint32_t type,
789 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
792EXPORT_SYMBOL(nftnl_set_elem_fprintf);
793int nftnl_set_elem_fprintf(FILE *fp,
const struct nftnl_set_elem *se, uint32_t type,
796 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
797 nftnl_set_elem_do_snprintf);
800EXPORT_SYMBOL(nftnl_set_elem_foreach);
801int nftnl_set_elem_foreach(
struct nftnl_set *s,
802 int (*cb)(
struct nftnl_set_elem *e,
void *data),
805 struct nftnl_set_elem *elem;
808 list_for_each_entry(elem, &s->element_list, head) {
809 ret = cb(elem, data);
817 const struct nftnl_set *set;
818 const struct list_head *list;
819 struct nftnl_set_elem *cur;
822EXPORT_SYMBOL(nftnl_set_elems_iter_create);
824nftnl_set_elems_iter_create(
const struct nftnl_set *s)
833 iter->list = &s->element_list;
834 if (list_empty(&s->element_list))
837 iter->cur = list_entry(s->element_list.next,
838 struct nftnl_set_elem, head);
843EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
844struct nftnl_set_elem *
850EXPORT_SYMBOL(nftnl_set_elems_iter_next);
853 struct nftnl_set_elem *s = iter->cur;
858 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
859 if (&iter->cur->head == iter->list->next)
865EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
871static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
872 const struct nlattr *from,
873 const struct nlattr *to)
875 int len = (
void *)to + to->nla_len - (
void *)from;
881 if (len > UINT16_MAX) {
882 nlh->nlmsg_len -= to->nla_len;
888EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);
889int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
892 struct nftnl_set_elem *elem;
893 struct nlattr *nest1, *nest2;
896 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
899 if (list_empty(&iter->set->element_list))
902 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
903 elem = nftnl_set_elems_iter_next(iter);
904 while (elem != NULL) {
905 nest2 = nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
906 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
908 iter->cur = list_entry(iter->cur->head.prev,
909 struct nftnl_set_elem, head);
913 elem = nftnl_set_elems_iter_next(iter);
915 mnl_attr_nest_end(nlh, nest1);