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));
39 INIT_LIST_HEAD(&s->expr_list);
44 EXPORT_SYMBOL(nftnl_set_elem_free);
45 void 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))
64 EXPORT_SYMBOL(nftnl_set_elem_is_set);
65 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
67 return s->flags & (1 << attr);
70 EXPORT_SYMBOL(nftnl_set_elem_unset);
71 void 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);
108 static 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),
115 EXPORT_SYMBOL(nftnl_set_elem_set);
116 int 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);
187 EXPORT_SYMBOL(nftnl_set_elem_set_u32);
188 void 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));
193 EXPORT_SYMBOL(nftnl_set_elem_set_u64);
194 void 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));
199 EXPORT_SYMBOL(nftnl_set_elem_set_str);
200 int 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);
205 EXPORT_SYMBOL(nftnl_set_elem_get);
206 const 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;
252 EXPORT_SYMBOL(nftnl_set_elem_get_str);
253 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
257 return nftnl_set_elem_get(s, attr, &size);
260 EXPORT_SYMBOL(nftnl_set_elem_get_u32);
261 uint32_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));
270 EXPORT_SYMBOL(nftnl_set_elem_get_u64);
271 uint64_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));
281 struct 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);
303 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
304 struct nftnl_set_elem *e)
306 struct nftnl_expr *expr;
309 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
310 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
311 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
312 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
313 if (e->flags & (1 << NFTNL_SET_ELEM_EXPIRATION))
314 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_EXPIRATION, htobe64(e->expiration));
315 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
316 struct nlattr *nest1;
318 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
319 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
320 mnl_attr_nest_end(nlh, nest1);
322 if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
323 struct nlattr *nest1;
325 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY_END);
326 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key_end.len,
328 mnl_attr_nest_end(nlh, nest1);
330 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
331 struct nlattr *nest1, *nest2;
333 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
334 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
335 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
336 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
337 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
339 mnl_attr_nest_end(nlh, nest1);
340 mnl_attr_nest_end(nlh, nest2);
342 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
343 struct nlattr *nest1;
345 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
346 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
347 mnl_attr_nest_end(nlh, nest1);
349 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
350 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
351 if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
352 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
354 if (!list_empty(&e->expr_list)) {
355 list_for_each_entry(expr, &e->expr_list, head)
358 if (num_exprs == 1) {
359 struct nlattr *nest1;
361 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR);
362 list_for_each_entry(expr, &e->expr_list, head)
363 nftnl_expr_build_payload(nlh, expr);
365 mnl_attr_nest_end(nlh, nest1);
366 }
else if (num_exprs > 1) {
367 struct nlattr *nest1, *nest2;
369 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPRESSIONS);
370 list_for_each_entry(expr, &e->expr_list, head) {
371 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
372 nftnl_expr_build_payload(nlh, expr);
373 mnl_attr_nest_end(nlh, nest2);
375 mnl_attr_nest_end(nlh, nest1);
380 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
381 const struct nftnl_set *s)
383 if (s->flags & (1 << NFTNL_SET_NAME))
384 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
385 if (s->flags & (1 << NFTNL_SET_ID))
386 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
387 if (s->flags & (1 << NFTNL_SET_TABLE))
388 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
391 EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build);
392 struct nlattr *nftnl_set_elem_nlmsg_build(
struct nlmsghdr *nlh,
393 struct nftnl_set_elem *elem,
int i)
395 struct nlattr *nest2;
397 nest2 = mnl_attr_nest_start(nlh, i);
398 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
399 mnl_attr_nest_end(nlh, nest2);
404 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
405 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
407 struct nftnl_set_elem *elem;
408 struct nlattr *nest1;
411 nftnl_set_elem_nlmsg_build_def(nlh, s);
413 if (list_empty(&s->element_list))
416 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
417 list_for_each_entry(elem, &s->element_list, head)
418 nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
420 mnl_attr_nest_end(nlh, nest1);
423 EXPORT_SYMBOL(nftnl_set_elem_add_expr);
424 void nftnl_set_elem_add_expr(
struct nftnl_set_elem *e,
struct nftnl_expr *expr)
426 list_add_tail(&expr->head, &e->expr_list);
429 EXPORT_SYMBOL(nftnl_set_elem_expr_foreach);
430 int nftnl_set_elem_expr_foreach(
struct nftnl_set_elem *e,
431 int (*cb)(
struct nftnl_expr *e,
void *data),
434 struct nftnl_expr *cur, *tmp;
437 list_for_each_entry_safe(cur, tmp, &e->expr_list, head) {
445 static int nftnl_set_elem_parse_attr_cb(
const struct nlattr *attr,
void *data)
447 const struct nlattr **tb = data;
448 int type = mnl_attr_get_type(attr);
450 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
454 case NFTA_SET_ELEM_FLAGS:
455 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
458 case NFTA_SET_ELEM_TIMEOUT:
459 case NFTA_SET_ELEM_EXPIRATION:
460 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
463 case NFTA_SET_ELEM_KEY:
464 case NFTA_SET_ELEM_KEY_END:
465 case NFTA_SET_ELEM_DATA:
466 case NFTA_SET_ELEM_EXPR:
467 case NFTA_SET_ELEM_EXPRESSIONS:
468 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
471 case NFTA_SET_ELEM_USERDATA:
472 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
481 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
483 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
484 struct nftnl_set_elem *e;
487 e = nftnl_set_elem_alloc();
491 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
495 if (tb[NFTA_SET_ELEM_FLAGS]) {
497 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
498 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
500 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
501 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
502 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
504 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
505 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
506 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
508 if (tb[NFTA_SET_ELEM_KEY]) {
509 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
512 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
514 if (tb[NFTA_SET_ELEM_KEY_END]) {
515 ret = nftnl_parse_data(&e->key_end, tb[NFTA_SET_ELEM_KEY_END],
519 e->flags |= (1 << NFTNL_SET_ELEM_KEY_END);
521 if (tb[NFTA_SET_ELEM_DATA]) {
522 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
527 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
530 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
531 (1 << NFTNL_SET_ELEM_CHAIN);
534 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
538 if (tb[NFTA_SET_ELEM_EXPR]) {
539 struct nftnl_expr *expr;
541 expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
546 list_add_tail(&expr->head, &e->expr_list);
547 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
548 }
else if (tb[NFTA_SET_ELEM_EXPRESSIONS]) {
549 struct nftnl_expr *expr;
552 mnl_attr_for_each_nested(attr, tb[NFTA_SET_ELEM_EXPRESSIONS]) {
553 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) {
557 expr = nftnl_expr_parse(attr);
562 list_add_tail(&expr->head, &e->expr_list);
564 e->flags |= (1 << NFTNL_SET_ELEM_EXPRESSIONS);
566 if (tb[NFTA_SET_ELEM_USERDATA]) {
568 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
570 if (e->flags & (1 << NFTNL_RULE_USERDATA))
573 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
574 e->user.data = malloc(e->user.len);
575 if (e->user.data == NULL) {
579 memcpy(e->user.data, udata, e->user.len);
580 e->flags |= (1 << NFTNL_RULE_USERDATA);
582 if (tb[NFTA_SET_ELEM_OBJREF]) {
583 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
584 if (e->objref == NULL) {
588 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
592 list_add_tail(&e->head, &s->element_list);
596 nftnl_set_elem_free(e);
601 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
603 const struct nlattr **tb = data;
604 int type = mnl_attr_get_type(attr);
606 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
610 case NFTA_SET_ELEM_LIST_TABLE:
611 case NFTA_SET_ELEM_LIST_SET:
612 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
615 case NFTA_SET_ELEM_LIST_ELEMENTS:
616 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
625 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
630 mnl_attr_for_each_nested(attr, nest) {
631 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
634 ret = nftnl_set_elems_parse2(s, attr);
641 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
642 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
644 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
645 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
648 if (mnl_attr_parse(nlh,
sizeof(*nfg),
649 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
652 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
653 if (s->flags & (1 << NFTNL_SET_TABLE))
656 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
659 s->flags |= (1 << NFTNL_SET_TABLE);
661 if (tb[NFTA_SET_ELEM_LIST_SET]) {
662 if (s->flags & (1 << NFTNL_SET_NAME))
665 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
668 s->flags |= (1 << NFTNL_SET_NAME);
670 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
671 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
672 s->flags |= (1 << NFTNL_SET_ID);
674 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
675 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
680 s->family = nfg->nfgen_family;
681 s->flags |= (1 << NFTNL_SET_FAMILY);
686 EXPORT_SYMBOL(nftnl_set_elem_parse);
687 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
688 const char *data,
struct nftnl_parse_err *err)
694 EXPORT_SYMBOL(nftnl_set_elem_parse_file);
695 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
696 FILE *fp,
struct nftnl_parse_err *err)
702 int nftnl_set_elem_snprintf_default(
char *buf,
size_t remain,
703 const struct nftnl_set_elem *e)
705 int ret, dregtype = DATA_VALUE, offset = 0, i;
707 ret = snprintf(buf, remain,
"element ");
708 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
710 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key,
711 DATA_F_NOPFX, DATA_VALUE);
712 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
714 if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
715 ret = snprintf(buf + offset, remain,
" - ");
716 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
718 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key_end,
719 DATA_F_NOPFX, DATA_VALUE);
720 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
723 ret = snprintf(buf + offset, remain,
" : ");
724 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
726 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
727 dregtype = DATA_VERDICT;
729 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
730 DATA_F_NOPFX, dregtype);
731 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
733 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
734 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
737 ret = snprintf(buf + offset, remain,
" userdata = {");
738 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
740 for (i = 0; i < e->user.len; i++) {
741 char *c = e->user.data;
743 ret = snprintf(buf + offset, remain,
"%c",
744 isalnum(c[i]) ? c[i] : 0);
745 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
748 ret = snprintf(buf + offset, remain,
" }\n");
749 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
755 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t remain,
756 const struct nftnl_set_elem *e,
757 uint32_t cmd, uint32_t type,
762 if (type != NFTNL_OUTPUT_DEFAULT)
765 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e);
766 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
771 EXPORT_SYMBOL(nftnl_set_elem_snprintf);
772 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
773 const struct nftnl_set_elem *e,
774 uint32_t type, uint32_t flags)
779 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
783 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
784 uint32_t cmd, uint32_t type,
787 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
790 EXPORT_SYMBOL(nftnl_set_elem_fprintf);
791 int nftnl_set_elem_fprintf(FILE *fp,
const struct nftnl_set_elem *se, uint32_t type,
794 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
795 nftnl_set_elem_do_snprintf);
798 EXPORT_SYMBOL(nftnl_set_elem_foreach);
799 int nftnl_set_elem_foreach(
struct nftnl_set *s,
800 int (*cb)(
struct nftnl_set_elem *e,
void *data),
803 struct nftnl_set_elem *elem;
806 list_for_each_entry(elem, &s->element_list, head) {
807 ret = cb(elem, data);
815 const struct nftnl_set *set;
816 const struct list_head *list;
817 struct nftnl_set_elem *cur;
820 EXPORT_SYMBOL(nftnl_set_elems_iter_create);
822 nftnl_set_elems_iter_create(
const struct nftnl_set *s)
831 iter->list = &s->element_list;
832 if (list_empty(&s->element_list))
835 iter->cur = list_entry(s->element_list.next,
836 struct nftnl_set_elem, head);
841 EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
842 struct nftnl_set_elem *
848 EXPORT_SYMBOL(nftnl_set_elems_iter_next);
851 struct nftnl_set_elem *s = iter->cur;
856 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
857 if (&iter->cur->head == iter->list->next)
863 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
869 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
870 const struct nlattr *from,
871 const struct nlattr *to)
873 int len = (
void *)to + to->nla_len - (
void *)from;
879 if (len > UINT16_MAX) {
880 nlh->nlmsg_len -= to->nla_len;
886 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);
887 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
890 struct nftnl_set_elem *elem;
891 struct nlattr *nest1, *nest2;
894 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
897 if (list_empty(&iter->set->element_list))
900 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
901 elem = nftnl_set_elems_iter_next(iter);
902 while (elem != NULL) {
903 nest2 = nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
904 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
906 iter->cur = list_entry(iter->cur->head.prev,
907 struct nftnl_set_elem, head);
911 elem = nftnl_set_elems_iter_next(iter);
913 mnl_attr_nest_end(nlh, nest1);