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_ALIAS(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);
54 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
59 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_free, nft_set_elem_free);
61 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
63 return s->flags & (1 << attr);
65 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_is_set, nft_set_elem_attr_is_set);
67 void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
70 case NFTNL_SET_ELEM_CHAIN:
71 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
78 case NFTNL_SET_ELEM_FLAGS:
79 case NFTNL_SET_ELEM_KEY:
80 case NFTNL_SET_ELEM_VERDICT:
81 case NFTNL_SET_ELEM_DATA:
82 case NFTNL_SET_ELEM_TIMEOUT:
83 case NFTNL_SET_ELEM_EXPIRATION:
84 case NFTNL_SET_ELEM_USERDATA:
86 case NFTNL_SET_ELEM_EXPR:
87 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR)) {
88 nftnl_expr_free(s->expr);
96 s->flags &= ~(1 << attr);
98 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_unset, nft_set_elem_attr_unset);
100 void nftnl_set_elem_set(
struct nftnl_set_elem *s, uint16_t attr,
101 const void *data, uint32_t data_len)
104 case NFTNL_SET_ELEM_FLAGS:
105 s->set_elem_flags = *((uint32_t *)data);
107 case NFTNL_SET_ELEM_KEY:
108 memcpy(&s->key.val, data, data_len);
109 s->key.len = data_len;
111 case NFTNL_SET_ELEM_VERDICT:
112 s->data.verdict = *((uint32_t *)data);
114 case NFTNL_SET_ELEM_CHAIN:
116 xfree(s->data.chain);
118 s->data.chain = strdup(data);
120 case NFTNL_SET_ELEM_DATA:
121 memcpy(s->data.val, data, data_len);
122 s->data.len = data_len;
124 case NFTNL_SET_ELEM_TIMEOUT:
125 s->timeout = *((uint64_t *)data);
127 case NFTNL_SET_ELEM_USERDATA:
128 if (s->user.data != NULL)
131 s->user.data = malloc(data_len);
134 memcpy(s->user.data, data, data_len);
135 s->user.len = data_len;
140 s->flags |= (1 << attr);
142 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set, nft_set_elem_attr_set);
144 void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
146 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
148 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_u32, nft_set_elem_attr_set_u32);
150 void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
152 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
154 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_u64, nft_set_elem_attr_set_u64);
156 void nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
158 nftnl_set_elem_set(s, attr, str, strlen(str));
160 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_str, nft_set_elem_attr_set_str);
162 const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
164 if (!(s->flags & (1 << attr)))
168 case NFTNL_SET_ELEM_FLAGS:
169 return &s->set_elem_flags;
170 case NFTNL_SET_ELEM_KEY:
171 *data_len = s->key.len;
173 case NFTNL_SET_ELEM_VERDICT:
174 return &s->data.verdict;
175 case NFTNL_SET_ELEM_CHAIN:
176 return s->data.chain;
177 case NFTNL_SET_ELEM_DATA:
178 *data_len = s->data.len;
180 case NFTNL_SET_ELEM_TIMEOUT:
182 case NFTNL_SET_ELEM_EXPIRATION:
183 return &s->expiration;
184 case NFTNL_SET_ELEM_USERDATA:
185 *data_len = s->user.len;
187 case NFTNL_SET_ELEM_EXPR:
192 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get, nft_set_elem_attr_get);
194 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
198 return nftnl_set_elem_get(s, attr, &size);
200 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_str, nft_set_elem_attr_get_str);
202 uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
205 uint32_t val = *((uint32_t *)nftnl_set_elem_get(s, attr, &size));
208 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_u32, nft_set_elem_attr_get_u32);
210 uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
213 uint64_t val = *((uint64_t *)nftnl_set_elem_get(s, attr, &size));
216 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_u64, nft_set_elem_attr_get_u64);
218 struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
220 struct nftnl_set_elem *newelem;
222 newelem = nftnl_set_elem_alloc();
226 memcpy(newelem, elem,
sizeof(*elem));
228 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN))
229 newelem->data.chain = strdup(elem->data.chain);
234 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
235 struct nftnl_set_elem *e)
237 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
238 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
239 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
240 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
241 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
242 struct nlattr *nest1;
244 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
245 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
246 mnl_attr_nest_end(nlh, nest1);
248 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
249 struct nlattr *nest1, *nest2;
251 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
252 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
253 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
254 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
255 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
257 mnl_attr_nest_end(nlh, nest1);
258 mnl_attr_nest_end(nlh, nest2);
260 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
261 struct nlattr *nest1;
263 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
264 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
265 mnl_attr_nest_end(nlh, nest1);
267 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
268 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
271 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
274 if (s->flags & (1 << NFTNL_SET_NAME))
275 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
276 if (s->flags & (1 << NFTNL_SET_ID))
277 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
278 if (s->flags & (1 << NFTNL_SET_TABLE))
279 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
282 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
283 struct nftnl_set_elem *elem,
int i)
285 struct nlattr *nest2;
287 nest2 = mnl_attr_nest_start(nlh, i);
288 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
289 mnl_attr_nest_end(nlh, nest2);
294 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
296 struct nftnl_set_elem *elem;
297 struct nlattr *nest1;
300 nftnl_set_elem_nlmsg_build_def(nlh, s);
302 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
303 list_for_each_entry(elem, &s->element_list, head)
304 nftnl_set_elem_build(nlh, elem, ++i);
306 mnl_attr_nest_end(nlh, nest1);
308 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_build_payload, nft_set_elems_nlmsg_build_payload);
310 static
int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr,
void *data)
312 const struct nlattr **tb = data;
313 int type = mnl_attr_get_type(attr);
315 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
319 case NFTA_SET_ELEM_FLAGS:
320 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
323 case NFTA_SET_ELEM_TIMEOUT:
324 case NFTA_SET_ELEM_EXPIRATION:
325 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
328 case NFTA_SET_ELEM_KEY:
329 case NFTA_SET_ELEM_DATA:
330 case NFTA_SET_ELEM_EXPR:
331 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
334 case NFTA_SET_ELEM_USERDATA:
335 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
344 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
346 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
347 struct nftnl_set_elem *e;
350 e = nftnl_set_elem_alloc();
354 if (mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb) < 0) {
355 nftnl_set_elem_free(e);
359 if (tb[NFTA_SET_ELEM_FLAGS]) {
361 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
362 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
364 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
365 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
366 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
368 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
369 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
370 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
372 if (tb[NFTA_SET_ELEM_KEY]) {
373 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
374 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
376 if (tb[NFTA_SET_ELEM_DATA]) {
377 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
380 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
383 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
384 (1 << NFTNL_SET_ELEM_CHAIN);
387 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
391 if (tb[NFTA_SET_ELEM_EXPR]) {
392 e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
395 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
397 if (tb[NFTA_SET_ELEM_USERDATA]) {
399 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
404 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
405 e->user.data = malloc(e->user.len);
406 if (e->user.data == NULL)
408 memcpy(e->user.data, udata, e->user.len);
409 e->flags |= (1 << NFTNL_RULE_USERDATA);
414 nftnl_set_elem_free(e);
419 list_add_tail(&e->head, &s->element_list);
425 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
427 const struct nlattr **tb = data;
428 int type = mnl_attr_get_type(attr);
430 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
434 case NFTA_SET_ELEM_LIST_TABLE:
435 case NFTA_SET_ELEM_LIST_SET:
436 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
439 case NFTA_SET_ELEM_LIST_ELEMENTS:
440 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
449 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
454 mnl_attr_for_each_nested(attr, nest) {
455 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
458 ret = nftnl_set_elems_parse2(s, attr);
463 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
465 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
466 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
469 if (mnl_attr_parse(nlh,
sizeof(*nfg),
470 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
473 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
476 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
477 s->flags |= (1 << NFTNL_SET_TABLE);
479 if (tb[NFTA_SET_ELEM_LIST_SET]) {
482 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
483 s->flags |= (1 << NFTNL_SET_NAME);
485 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
486 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
487 s->flags |= (1 << NFTNL_SET_ID);
489 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS])
490 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
492 s->family = nfg->nfgen_family;
493 s->flags |= (1 << NFTNL_SET_FAMILY);
497 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_parse, nft_set_elems_nlmsg_parse);
500 int nftnl_mxml_set_elem_parse(mxml_node_t *tree,
struct nftnl_set_elem *e,
501 struct nftnl_parse_err *err)
504 uint32_t set_elem_flags;
506 if (nftnl_mxml_num_parse(tree,
"flags", MXML_DESCEND_FIRST, BASE_DEC,
507 &set_elem_flags, NFTNL_TYPE_U32, NFTNL_XML_MAND,
509 nftnl_set_elem_set_u32(e, NFTNL_SET_ELEM_FLAGS, set_elem_flags);
511 if (nftnl_mxml_data_reg_parse(tree,
"key", &e->key,
512 NFTNL_XML_MAND, err) == DATA_VALUE)
513 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
516 set_elem_data = nftnl_mxml_data_reg_parse(tree,
"data",
517 &e->data, NFTNL_XML_OPT, err);
518 switch (set_elem_data) {
520 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
523 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
524 if (e->data.chain != NULL)
525 e->flags |= (1 << NFTNL_SET_ELEM_CHAIN);
534 static int nftnl_set_elem_xml_parse(
struct nftnl_set_elem *e,
const void *xml,
535 struct nftnl_parse_err *err,
536 enum nftnl_parse_input input)
542 tree = nftnl_mxml_build_tree(xml,
"set_elem", err, input);
546 ret = nftnl_mxml_set_elem_parse(tree, e, err);
555 static int nftnl_set_elem_json_parse(
struct nftnl_set_elem *e,
const void *json,
556 struct nftnl_parse_err *err,
557 enum nftnl_parse_input input)
563 tree = nftnl_jansson_create_root(json, &error, err, input);
567 return nftnl_jansson_set_elem_parse(e, tree, err);
575 nftnl_set_elem_do_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
576 const void *data,
struct nftnl_parse_err *err,
577 enum nftnl_parse_input input)
582 case NFTNL_PARSE_XML:
583 ret = nftnl_set_elem_xml_parse(e, data, err, input);
585 case NFTNL_PARSE_JSON:
586 ret = nftnl_set_elem_json_parse(e, data, err, input);
596 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
597 const char *data,
struct nftnl_parse_err *err)
599 return nftnl_set_elem_do_parse(e, type, data, err, NFTNL_PARSE_BUFFER);
601 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_parse, nft_set_elem_parse);
603 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
604 FILE *fp,
struct nftnl_parse_err *err)
606 return nftnl_set_elem_do_parse(e, type, fp, err, NFTNL_PARSE_FILE);
608 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_parse_file, nft_set_elem_parse_file);
610 static int nftnl_set_elem_snprintf_json(
char *buf,
size_t size,
611 const struct nftnl_set_elem *e,
614 int ret, len = size, offset = 0, type = -1;
616 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
617 ret = snprintf(buf, len,
"\"flags\":%u,", e->set_elem_flags);
618 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
621 ret = snprintf(buf + offset, len,
"\"key\":{");
622 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
624 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
625 NFTNL_OUTPUT_JSON, flags, DATA_VALUE);
626 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
628 ret = snprintf(buf + offset, len,
"}");
629 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
631 if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
633 else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
635 else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
639 ret = snprintf(buf + offset, len,
",\"data\":{");
640 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
642 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
643 NFTNL_OUTPUT_JSON, flags, type);
644 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
646 ret = snprintf(buf + offset, len,
"}");
647 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
653 static int nftnl_set_elem_snprintf_default(
char *buf,
size_t size,
654 const struct nftnl_set_elem *e)
656 int ret, len = size, offset = 0, i;
658 ret = snprintf(buf, len,
"element ");
659 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
661 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
662 ret = snprintf(buf+offset, len,
"%.8x ", e->key.val[i]);
663 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
666 ret = snprintf(buf+offset, len,
" : ");
667 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
669 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
670 ret = snprintf(buf+offset, len,
"%.8x ", e->data.val[i]);
671 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
674 ret = snprintf(buf+offset, len,
"%u [end]", e->set_elem_flags);
675 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
678 ret = snprintf(buf+offset, len,
" userdata = {");
679 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
681 for (i = 0; i < e->user.len; i++) {
682 char *c = e->user.data;
684 ret = snprintf(buf+offset, len,
"%c",
685 isalnum(c[i]) ? c[i] : 0);
686 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
689 ret = snprintf(buf+offset, len,
" }\n");
690 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
696 static int nftnl_set_elem_snprintf_xml(
char *buf,
size_t size,
697 const struct nftnl_set_elem *e,
700 int ret, len = size, offset = 0, type = DATA_NONE;
702 ret = snprintf(buf, size,
"<set_elem>");
703 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
705 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
706 ret = snprintf(buf + offset, size,
"<flags>%u</flags>",
708 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
711 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
712 ret = snprintf(buf + offset, len,
"<key>");
713 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
715 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
716 NFTNL_OUTPUT_XML, flags, DATA_VALUE);
717 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
719 ret = snprintf(buf + offset, len,
"</key>");
720 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
723 if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
725 else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
727 else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
730 if (type != DATA_NONE) {
731 ret = snprintf(buf + offset, len,
"<data>");
732 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
734 ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
735 NFTNL_OUTPUT_XML, flags, type);
736 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
738 ret = snprintf(buf + offset, len,
"</data>");
739 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
742 ret = snprintf(buf + offset, len,
"</set_elem>");
743 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
748 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t size,
749 const struct nftnl_set_elem *e,
750 uint32_t cmd, uint32_t type,
753 int ret, len = size, offset = 0;
755 ret = nftnl_cmd_header_snprintf(buf + offset, len, cmd, type, flags);
756 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
759 case NFTNL_OUTPUT_DEFAULT:
760 ret = nftnl_set_elem_snprintf_default(buf+offset, len, e);
762 case NFTNL_OUTPUT_XML:
763 ret = nftnl_set_elem_snprintf_xml(buf+offset, len, e, flags);
765 case NFTNL_OUTPUT_JSON:
766 ret = nftnl_set_elem_snprintf_json(buf+offset, len, e, flags);
772 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
774 ret = nftnl_cmd_footer_snprintf(buf + offset, len, cmd, type, flags);
775 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
780 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
781 const struct nftnl_set_elem *e,
782 uint32_t type, uint32_t flags)
784 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
787 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_snprintf, nft_set_elem_snprintf);
789 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
790 uint32_t cmd, uint32_t type,
793 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
796 int nftnl_set_elem_fprintf(FILE *fp,
struct nftnl_set_elem *se, uint32_t type,
799 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
800 nftnl_set_elem_do_snprintf);
802 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_fprintf, nft_set_elem_fprintf);
804 int nftnl_set_elem_foreach(
struct nftnl_set *s,
805 int (*cb)(
struct nftnl_set_elem *e,
void *data),
808 struct nftnl_set_elem *elem;
811 list_for_each_entry(elem, &s->element_list, head) {
812 ret = cb(elem, data);
818 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_foreach, nft_set_elem_foreach);
821 struct nftnl_set *set;
822 struct list_head *list;
823 struct nftnl_set_elem *cur;
835 iter->list = &s->element_list;
836 if (list_empty(&s->element_list))
839 iter->cur = list_entry(s->element_list.next,
840 struct nftnl_set_elem, head);
844 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_create, nft_set_elems_iter_create);
850 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_cur, nft_set_elems_iter_cur);
854 struct nftnl_set_elem *s = iter->cur;
859 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
860 if (&iter->cur->head == iter->list->next)
865 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_next, nft_set_elems_iter_next);
871 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_destroy, nft_set_elems_iter_destroy);
873 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
874 const struct nlattr *from,
875 const struct nlattr *to)
877 int len = (
void *)to + to->nla_len - (
void *)from;
883 if (len > UINT16_MAX) {
884 nlh->nlmsg_len -= to->nla_len;
890 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
893 struct nftnl_set_elem *elem;
894 struct nlattr *nest1, *nest2;
897 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
899 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
900 elem = nftnl_set_elems_iter_next(iter);
901 while (elem != NULL) {
902 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
903 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
905 iter->cur = list_entry(iter->cur->head.prev,
906 struct nftnl_set_elem, head);
910 elem = nftnl_set_elems_iter_next(iter);
912 mnl_attr_nest_end(nlh, nest1);
916 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_build_payload_iter, nft_set_elems_nlmsg_build_payload_iter);