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 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
392 struct nftnl_set_elem *elem,
int i)
394 struct nlattr *nest2;
396 nest2 = mnl_attr_nest_start(nlh, i);
397 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
398 mnl_attr_nest_end(nlh, nest2);
403 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
404 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
406 struct nftnl_set_elem *elem;
407 struct nlattr *nest1;
410 nftnl_set_elem_nlmsg_build_def(nlh, s);
412 if (list_empty(&s->element_list))
415 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
416 list_for_each_entry(elem, &s->element_list, head)
417 nftnl_set_elem_build(nlh, elem, ++i);
419 mnl_attr_nest_end(nlh, nest1);
422 EXPORT_SYMBOL(nftnl_set_elem_add_expr);
423 void nftnl_set_elem_add_expr(
struct nftnl_set_elem *e,
struct nftnl_expr *expr)
425 list_add_tail(&expr->head, &e->expr_list);
428 EXPORT_SYMBOL(nftnl_set_elem_expr_foreach);
429 int nftnl_set_elem_expr_foreach(
struct nftnl_set_elem *e,
430 int (*cb)(
struct nftnl_expr *e,
void *data),
433 struct nftnl_expr *cur, *tmp;
436 list_for_each_entry_safe(cur, tmp, &e->expr_list, head) {
444 static int nftnl_set_elem_parse_attr_cb(
const struct nlattr *attr,
void *data)
446 const struct nlattr **tb = data;
447 int type = mnl_attr_get_type(attr);
449 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
453 case NFTA_SET_ELEM_FLAGS:
454 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
457 case NFTA_SET_ELEM_TIMEOUT:
458 case NFTA_SET_ELEM_EXPIRATION:
459 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
462 case NFTA_SET_ELEM_KEY:
463 case NFTA_SET_ELEM_KEY_END:
464 case NFTA_SET_ELEM_DATA:
465 case NFTA_SET_ELEM_EXPR:
466 case NFTA_SET_ELEM_EXPRESSIONS:
467 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
470 case NFTA_SET_ELEM_USERDATA:
471 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
480 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
482 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
483 struct nftnl_set_elem *e;
486 e = nftnl_set_elem_alloc();
490 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
494 if (tb[NFTA_SET_ELEM_FLAGS]) {
496 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
497 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
499 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
500 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
501 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
503 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
504 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
505 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
507 if (tb[NFTA_SET_ELEM_KEY]) {
508 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
511 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
513 if (tb[NFTA_SET_ELEM_KEY_END]) {
514 ret = nftnl_parse_data(&e->key_end, tb[NFTA_SET_ELEM_KEY_END],
518 e->flags |= (1 << NFTNL_SET_ELEM_KEY_END);
520 if (tb[NFTA_SET_ELEM_DATA]) {
521 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
526 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
529 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
530 (1 << NFTNL_SET_ELEM_CHAIN);
533 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
537 if (tb[NFTA_SET_ELEM_EXPR]) {
538 struct nftnl_expr *expr;
540 expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
545 list_add_tail(&expr->head, &e->expr_list);
546 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
547 }
else if (tb[NFTA_SET_ELEM_EXPRESSIONS]) {
548 struct nftnl_expr *expr;
551 mnl_attr_for_each_nested(attr, tb[NFTA_SET_ELEM_EXPRESSIONS]) {
552 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) {
556 expr = nftnl_expr_parse(attr);
561 list_add_tail(&expr->head, &e->expr_list);
563 e->flags |= (1 << NFTNL_SET_ELEM_EXPRESSIONS);
565 if (tb[NFTA_SET_ELEM_USERDATA]) {
567 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
569 if (e->flags & (1 << NFTNL_RULE_USERDATA))
572 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
573 e->user.data = malloc(e->user.len);
574 if (e->user.data == NULL) {
578 memcpy(e->user.data, udata, e->user.len);
579 e->flags |= (1 << NFTNL_RULE_USERDATA);
581 if (tb[NFTA_SET_ELEM_OBJREF]) {
582 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
583 if (e->objref == NULL) {
587 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
591 list_add_tail(&e->head, &s->element_list);
595 nftnl_set_elem_free(e);
600 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
602 const struct nlattr **tb = data;
603 int type = mnl_attr_get_type(attr);
605 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
609 case NFTA_SET_ELEM_LIST_TABLE:
610 case NFTA_SET_ELEM_LIST_SET:
611 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
614 case NFTA_SET_ELEM_LIST_ELEMENTS:
615 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
624 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
629 mnl_attr_for_each_nested(attr, nest) {
630 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
633 ret = nftnl_set_elems_parse2(s, attr);
640 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
641 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
643 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
644 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
647 if (mnl_attr_parse(nlh,
sizeof(*nfg),
648 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
651 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
652 if (s->flags & (1 << NFTNL_SET_TABLE))
655 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
658 s->flags |= (1 << NFTNL_SET_TABLE);
660 if (tb[NFTA_SET_ELEM_LIST_SET]) {
661 if (s->flags & (1 << NFTNL_SET_NAME))
664 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
667 s->flags |= (1 << NFTNL_SET_NAME);
669 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
670 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
671 s->flags |= (1 << NFTNL_SET_ID);
673 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
674 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
679 s->family = nfg->nfgen_family;
680 s->flags |= (1 << NFTNL_SET_FAMILY);
685 EXPORT_SYMBOL(nftnl_set_elem_parse);
686 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
687 const char *data,
struct nftnl_parse_err *err)
693 EXPORT_SYMBOL(nftnl_set_elem_parse_file);
694 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
695 FILE *fp,
struct nftnl_parse_err *err)
701 int nftnl_set_elem_snprintf_default(
char *buf,
size_t remain,
702 const struct nftnl_set_elem *e,
703 enum nft_data_types dtype)
705 int dregtype = (dtype == NFT_DATA_VERDICT) ? DATA_VERDICT : DATA_VALUE;
706 int ret, 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 ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
728 DATA_F_NOPFX, dregtype);
729 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
731 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
732 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
735 ret = snprintf(buf + offset, remain,
" userdata = {");
736 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
738 for (i = 0; i < e->user.len; i++) {
739 char *c = e->user.data;
741 ret = snprintf(buf + offset, remain,
"%c",
742 isalnum(c[i]) ? c[i] : 0);
743 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
746 ret = snprintf(buf + offset, remain,
" }\n");
747 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
753 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t remain,
754 const struct nftnl_set_elem *e,
755 uint32_t cmd, uint32_t type,
760 if (type != NFTNL_OUTPUT_DEFAULT)
763 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e,
765 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
769 EXPORT_SYMBOL(nftnl_set_elem_snprintf);
770 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
771 const struct nftnl_set_elem *e,
772 uint32_t type, uint32_t flags)
777 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
781 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
782 uint32_t cmd, uint32_t type,
785 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
788 EXPORT_SYMBOL(nftnl_set_elem_fprintf);
789 int nftnl_set_elem_fprintf(FILE *fp,
const struct nftnl_set_elem *se, uint32_t type,
792 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
793 nftnl_set_elem_do_snprintf);
796 EXPORT_SYMBOL(nftnl_set_elem_foreach);
797 int nftnl_set_elem_foreach(
struct nftnl_set *s,
798 int (*cb)(
struct nftnl_set_elem *e,
void *data),
801 struct nftnl_set_elem *elem;
804 list_for_each_entry(elem, &s->element_list, head) {
805 ret = cb(elem, data);
813 const struct nftnl_set *set;
814 const struct list_head *list;
815 struct nftnl_set_elem *cur;
818 EXPORT_SYMBOL(nftnl_set_elems_iter_create);
820 nftnl_set_elems_iter_create(
const struct nftnl_set *s)
829 iter->list = &s->element_list;
830 if (list_empty(&s->element_list))
833 iter->cur = list_entry(s->element_list.next,
834 struct nftnl_set_elem, head);
839 EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
840 struct nftnl_set_elem *
846 EXPORT_SYMBOL(nftnl_set_elems_iter_next);
849 struct nftnl_set_elem *s = iter->cur;
854 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
855 if (&iter->cur->head == iter->list->next)
861 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
867 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
868 const struct nlattr *from,
869 const struct nlattr *to)
871 int len = (
void *)to + to->nla_len - (
void *)from;
877 if (len > UINT16_MAX) {
878 nlh->nlmsg_len -= to->nla_len;
884 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);
885 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
888 struct nftnl_set_elem *elem;
889 struct nlattr *nest1, *nest2;
892 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
895 if (list_empty(&iter->set->element_list))
898 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
899 elem = nftnl_set_elems_iter_next(iter);
900 while (elem != NULL) {
901 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
902 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
904 iter->cur = list_entry(iter->cur->head.prev,
905 struct nftnl_set_elem, head);
909 elem = nftnl_set_elems_iter_next(iter);
911 mnl_attr_nest_end(nlh, nest1);