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, nft_set_elem_alloc);
42 void nftnl_set_elem_free(
struct nftnl_set_elem *s)
44 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
51 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
52 nftnl_expr_free(s->expr);
56 EXPORT_SYMBOL(nftnl_set_elem_free, nft_set_elem_free);
58 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
60 return s->flags & (1 << attr);
62 EXPORT_SYMBOL(nftnl_set_elem_is_set, nft_set_elem_attr_is_set);
64 void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
67 case NFTNL_SET_ELEM_CHAIN:
68 if (s->flags & (1 << 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:
81 case NFTNL_SET_ELEM_USERDATA:
83 case NFTNL_SET_ELEM_EXPR:
84 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR)) {
85 nftnl_expr_free(s->expr);
93 s->flags &= ~(1 << attr);
95 EXPORT_SYMBOL(nftnl_set_elem_unset, nft_set_elem_attr_unset);
97 void nftnl_set_elem_set(
struct nftnl_set_elem *s, uint16_t attr,
98 const void *data, uint32_t data_len)
101 case NFTNL_SET_ELEM_FLAGS:
102 s->set_elem_flags = *((uint32_t *)data);
104 case NFTNL_SET_ELEM_KEY:
105 memcpy(&s->key.val, data, data_len);
106 s->key.len = data_len;
108 case NFTNL_SET_ELEM_VERDICT:
109 s->data.verdict = *((uint32_t *)data);
111 case NFTNL_SET_ELEM_CHAIN:
113 xfree(s->data.chain);
115 s->data.chain = strdup(data);
117 case NFTNL_SET_ELEM_DATA:
118 memcpy(s->data.val, data, data_len);
119 s->data.len = data_len;
121 case NFTNL_SET_ELEM_TIMEOUT:
122 s->timeout = *((uint64_t *)data);
124 case NFTNL_SET_ELEM_USERDATA:
125 s->user.data = (
void *)data;
126 s->user.len = data_len;
131 s->flags |= (1 << attr);
133 EXPORT_SYMBOL(nftnl_set_elem_set, nft_set_elem_attr_set);
135 void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
137 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
139 EXPORT_SYMBOL(nftnl_set_elem_set_u32, nft_set_elem_attr_set_u32);
141 void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
143 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
145 EXPORT_SYMBOL(nftnl_set_elem_set_u64, nft_set_elem_attr_set_u64);
147 void nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
149 nftnl_set_elem_set(s, attr, str, strlen(str));
151 EXPORT_SYMBOL(nftnl_set_elem_set_str, nft_set_elem_attr_set_str);
153 const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
155 if (!(s->flags & (1 << attr)))
159 case NFTNL_SET_ELEM_FLAGS:
160 return &s->set_elem_flags;
161 case NFTNL_SET_ELEM_KEY:
162 *data_len = s->key.len;
164 case NFTNL_SET_ELEM_VERDICT:
165 return &s->data.verdict;
166 case NFTNL_SET_ELEM_CHAIN:
167 return s->data.chain;
168 case NFTNL_SET_ELEM_DATA:
169 *data_len = s->data.len;
171 case NFTNL_SET_ELEM_TIMEOUT:
173 case NFTNL_SET_ELEM_EXPIRATION:
174 return &s->expiration;
175 case NFTNL_SET_ELEM_USERDATA:
176 *data_len = s->user.len;
178 case NFTNL_SET_ELEM_EXPR:
183 EXPORT_SYMBOL(nftnl_set_elem_get, nft_set_elem_attr_get);
185 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
189 return nftnl_set_elem_get(s, attr, &size);
191 EXPORT_SYMBOL(nftnl_set_elem_get_str, nft_set_elem_attr_get_str);
193 uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
196 uint32_t val = *((uint32_t *)nftnl_set_elem_get(s, attr, &size));
199 EXPORT_SYMBOL(nftnl_set_elem_get_u32, nft_set_elem_attr_get_u32);
201 uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
204 uint64_t val = *((uint64_t *)nftnl_set_elem_get(s, attr, &size));
207 EXPORT_SYMBOL(nftnl_set_elem_get_u64, nft_set_elem_attr_get_u64);
209 struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
211 struct nftnl_set_elem *newelem;
213 newelem = nftnl_set_elem_alloc();
217 memcpy(newelem, elem,
sizeof(*elem));
219 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN))
220 newelem->data.chain = strdup(elem->data.chain);
225 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
226 struct nftnl_set_elem *e)
228 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
229 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
230 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
231 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
232 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
233 struct nlattr *nest1;
235 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
236 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
237 mnl_attr_nest_end(nlh, nest1);
239 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
240 struct nlattr *nest1, *nest2;
242 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
243 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
244 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
245 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
246 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
248 mnl_attr_nest_end(nlh, nest1);
249 mnl_attr_nest_end(nlh, nest2);
251 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
252 struct nlattr *nest1;
254 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
255 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
256 mnl_attr_nest_end(nlh, nest1);
258 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
259 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
262 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
265 if (s->flags & (1 << NFTNL_SET_NAME))
266 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
267 if (s->flags & (1 << NFTNL_SET_ID))
268 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
269 if (s->flags & (1 << NFTNL_SET_TABLE))
270 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
273 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
274 struct nftnl_set_elem *elem,
int i)
276 struct nlattr *nest2;
278 nest2 = mnl_attr_nest_start(nlh, i);
279 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
280 mnl_attr_nest_end(nlh, nest2);
285 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
287 struct nftnl_set_elem *elem;
288 struct nlattr *nest1;
291 nftnl_set_elem_nlmsg_build_def(nlh, s);
293 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
294 list_for_each_entry(elem, &s->element_list, head)
295 nftnl_set_elem_build(nlh, elem, ++i);
297 mnl_attr_nest_end(nlh, nest1);
299 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload, nft_set_elems_nlmsg_build_payload);
301 static
int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr,
void *data)
303 const struct nlattr **tb = data;
304 int type = mnl_attr_get_type(attr);
306 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
310 case NFTA_SET_ELEM_FLAGS:
311 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
314 case NFTA_SET_ELEM_TIMEOUT:
315 case NFTA_SET_ELEM_EXPIRATION:
316 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
319 case NFTA_SET_ELEM_KEY:
320 case NFTA_SET_ELEM_DATA:
321 case NFTA_SET_ELEM_EXPR:
322 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
325 case NFTA_SET_ELEM_USERDATA:
326 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
335 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
337 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
338 struct nftnl_set_elem *e;
341 e = nftnl_set_elem_alloc();
345 if (mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb) < 0) {
346 nftnl_set_elem_free(e);
350 if (tb[NFTA_SET_ELEM_FLAGS]) {
352 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
353 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
355 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
356 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
357 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
359 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
360 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
361 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
363 if (tb[NFTA_SET_ELEM_KEY]) {
364 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
365 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
367 if (tb[NFTA_SET_ELEM_DATA]) {
368 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
371 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
374 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
375 (1 << NFTNL_SET_ELEM_CHAIN);
378 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
382 if (tb[NFTA_SET_ELEM_EXPR]) {
383 e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
386 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
388 if (tb[NFTA_SET_ELEM_USERDATA]) {
390 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
395 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
396 e->user.data = malloc(e->user.len);
397 if (e->user.data == NULL)
399 memcpy(e->user.data, udata, e->user.len);
400 e->flags |= (1 << NFTNL_RULE_USERDATA);
405 nftnl_set_elem_free(e);
410 list_add_tail(&e->head, &s->element_list);
416 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
418 const struct nlattr **tb = data;
419 int type = mnl_attr_get_type(attr);
421 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
425 case NFTA_SET_ELEM_LIST_TABLE:
426 case NFTA_SET_ELEM_LIST_SET:
427 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
430 case NFTA_SET_ELEM_LIST_ELEMENTS:
431 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
440 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
445 mnl_attr_for_each_nested(attr, nest) {
446 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
449 ret = nftnl_set_elems_parse2(s, attr);
454 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
456 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
457 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
460 if (mnl_attr_parse(nlh,
sizeof(*nfg),
461 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
464 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
467 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
468 s->flags |= (1 << NFTNL_SET_TABLE);
470 if (tb[NFTA_SET_ELEM_LIST_SET]) {
473 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
474 s->flags |= (1 << NFTNL_SET_NAME);
476 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
477 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
478 s->flags |= (1 << NFTNL_SET_ID);
480 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS])
481 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
483 s->family = nfg->nfgen_family;
484 s->flags |= (1 << NFTNL_SET_FAMILY);
488 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse, nft_set_elems_nlmsg_parse);
491 int nftnl_mxml_set_elem_parse(mxml_node_t *tree,
struct nftnl_set_elem *e,
492 struct nftnl_parse_err *err)
495 uint32_t set_elem_flags;
497 if (nftnl_mxml_num_parse(tree,
"flags", MXML_DESCEND_FIRST, BASE_DEC,
498 &set_elem_flags, NFTNL_TYPE_U32, NFTNL_XML_MAND,
500 nftnl_set_elem_set_u32(e, NFTNL_SET_ELEM_FLAGS, set_elem_flags);
502 if (nftnl_mxml_data_reg_parse(tree,
"key", &e->key,
503 NFTNL_XML_MAND, err) == DATA_VALUE)
504 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
507 set_elem_data = nftnl_mxml_data_reg_parse(tree,
"data",
508 &e->data, NFTNL_XML_OPT, err);
509 switch (set_elem_data) {
511 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
514 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
515 if (e->data.chain != NULL)
516 e->flags |= (1 << NFTNL_SET_ELEM_CHAIN);
525 static int nftnl_set_elem_xml_parse(
struct nftnl_set_elem *e,
const void *xml,
526 struct nftnl_parse_err *err,
527 enum nftnl_parse_input input)
533 tree = nftnl_mxml_build_tree(xml,
"set_elem", err, input);
537 ret = nftnl_mxml_set_elem_parse(tree, e, err);
546 static int nftnl_set_elem_json_parse(
struct nftnl_set_elem *e,
const void *json,
547 struct nftnl_parse_err *err,
548 enum nftnl_parse_input input)
554 tree = nftnl_jansson_create_root(json, &error, err, input);
558 return nftnl_jansson_set_elem_parse(e, tree, err);
566 nftnl_set_elem_do_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
567 const void *data,
struct nftnl_parse_err *err,
568 enum nftnl_parse_input input)
573 case NFTNL_PARSE_XML:
574 ret = nftnl_set_elem_xml_parse(e, data, err, input);
576 case NFTNL_PARSE_JSON:
577 ret = nftnl_set_elem_json_parse(e, data, err, input);
587 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
588 const char *data,
struct nftnl_parse_err *err)
590 return nftnl_set_elem_do_parse(e, type, data, err, NFTNL_PARSE_BUFFER);
592 EXPORT_SYMBOL(nftnl_set_elem_parse, nft_set_elem_parse);
594 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
595 FILE *fp,
struct nftnl_parse_err *err)
597 return nftnl_set_elem_do_parse(e, type, fp, err, NFTNL_PARSE_FILE);
599 EXPORT_SYMBOL(nftnl_set_elem_parse_file, nft_set_elem_parse_file);
601 static int nftnl_set_elem_snprintf_json(
char *buf,
size_t size,
602 struct nftnl_set_elem *e, uint32_t flags)
604 int ret, len = size, offset = 0, type = -1;
606 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
607 ret = snprintf(buf, len,
"\"flags\":%u,", e->set_elem_flags);
608 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
611 ret = snprintf(buf + offset, len,
"\"key\":{");
612 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
614 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
615 NFTNL_OUTPUT_JSON, flags, DATA_VALUE);
616 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
618 ret = snprintf(buf + offset, len,
"}");
619 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
621 if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
623 else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
625 else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
629 ret = snprintf(buf + offset, len,
",\"data\":{");
630 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
632 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
633 NFTNL_OUTPUT_JSON, flags, type);
634 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
636 ret = snprintf(buf + offset, len,
"}");
637 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
643 static int nftnl_set_elem_snprintf_default(
char *buf,
size_t size,
644 struct nftnl_set_elem *e)
646 int ret, len = size, offset = 0, i;
648 ret = snprintf(buf, len,
"element ");
649 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
651 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
652 ret = snprintf(buf+offset, len,
"%.8x ", e->key.val[i]);
653 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
656 ret = snprintf(buf+offset, len,
" : ");
657 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
659 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
660 ret = snprintf(buf+offset, len,
"%.8x ", e->data.val[i]);
661 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
664 ret = snprintf(buf+offset, len,
"%u [end]", e->set_elem_flags);
665 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
668 ret = snprintf(buf+offset, len,
" userdata = {");
669 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
671 for (i = 0; i < e->user.len; i++) {
672 char *c = e->user.data;
674 ret = snprintf(buf+offset, len,
"%c",
675 isalnum(c[i]) ? c[i] : 0);
676 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
679 ret = snprintf(buf+offset, len,
" }\n");
680 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
686 static int nftnl_set_elem_snprintf_xml(
char *buf,
size_t size,
687 struct nftnl_set_elem *e, uint32_t flags)
689 int ret, len = size, offset = 0, type = DATA_NONE;
691 ret = snprintf(buf, size,
"<set_elem>");
692 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
694 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
695 ret = snprintf(buf + offset, size,
"<flags>%u</flags>",
697 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
700 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
701 ret = snprintf(buf + offset, len,
"<key>");
702 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
704 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
705 NFTNL_OUTPUT_XML, flags, DATA_VALUE);
706 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
708 ret = snprintf(buf + offset, len,
"</key>");
709 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
712 if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
714 else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
716 else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
719 if (type != DATA_NONE) {
720 ret = snprintf(buf + offset, len,
"<data>");
721 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
723 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
724 NFTNL_OUTPUT_XML, flags, type);
725 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
727 ret = snprintf(buf + offset, len,
"</data>");
728 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
731 ret = snprintf(buf + offset, len,
"</set_elem>");
732 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
737 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t size,
738 struct nftnl_set_elem *e, uint32_t cmd,
739 uint32_t type, uint32_t flags)
741 int ret, len = size, offset = 0;
743 ret = nftnl_cmd_header_snprintf(buf + offset, len, cmd, type, flags);
744 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
747 case NFTNL_OUTPUT_DEFAULT:
748 ret = nftnl_set_elem_snprintf_default(buf+offset, len, e);
750 case NFTNL_OUTPUT_XML:
751 ret = nftnl_set_elem_snprintf_xml(buf+offset, len, e, flags);
753 case NFTNL_OUTPUT_JSON:
754 ret = nftnl_set_elem_snprintf_json(buf+offset, len, e, flags);
760 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
762 ret = nftnl_cmd_footer_snprintf(buf + offset, len, cmd, type, flags);
763 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
768 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
struct nftnl_set_elem *e,
769 uint32_t type, uint32_t flags)
771 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
774 EXPORT_SYMBOL(nftnl_set_elem_snprintf, nft_set_elem_snprintf);
776 static inline int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
void *e,
777 uint32_t cmd, uint32_t type,
780 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
783 int nftnl_set_elem_fprintf(FILE *fp,
struct nftnl_set_elem *se, uint32_t type,
786 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
787 nftnl_set_elem_do_snprintf);
789 EXPORT_SYMBOL(nftnl_set_elem_fprintf, nft_set_elem_fprintf);
791 int nftnl_set_elem_foreach(
struct nftnl_set *s,
792 int (*cb)(
struct nftnl_set_elem *e,
void *data),
795 struct nftnl_set_elem *elem;
798 list_for_each_entry(elem, &s->element_list, head) {
799 ret = cb(elem, data);
805 EXPORT_SYMBOL(nftnl_set_elem_foreach, nft_set_elem_foreach);
808 struct nftnl_set *set;
809 struct list_head *list;
810 struct nftnl_set_elem *cur;
822 iter->list = &s->element_list;
823 if (list_empty(&s->element_list))
826 iter->cur = list_entry(s->element_list.next,
827 struct nftnl_set_elem, head);
831 EXPORT_SYMBOL(nftnl_set_elems_iter_create, nft_set_elems_iter_create);
837 EXPORT_SYMBOL(nftnl_set_elems_iter_cur, nft_set_elems_iter_cur);
841 struct nftnl_set_elem *s = iter->cur;
846 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
847 if (&iter->cur->head == iter->list->next)
852 EXPORT_SYMBOL(nftnl_set_elems_iter_next, nft_set_elems_iter_next);
858 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy, nft_set_elems_iter_destroy);
860 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
861 const struct nlattr *from,
862 const struct nlattr *to)
864 int len = (
void *)to + to->nla_len - (
void *)from;
870 if (len > UINT16_MAX) {
871 nlh->nlmsg_len -= to->nla_len;
877 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
880 struct nftnl_set_elem *elem;
881 struct nlattr *nest1, *nest2;
884 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
886 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
887 elem = nftnl_set_elems_iter_next(iter);
888 while (elem != NULL) {
889 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
890 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
892 iter->cur = list_entry(iter->cur->head.prev,
893 struct nftnl_set_elem, head);
897 elem = nftnl_set_elems_iter_next(iter);
899 mnl_attr_nest_end(nlh, nest1);
903 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter, nft_set_elems_nlmsg_build_payload_iter);