18 #include <netinet/in.h>
21 #include <libmnl/libmnl.h>
22 #include <linux/netfilter/nfnetlink.h>
23 #include <linux/netfilter/nf_tables.h>
25 #include <libnftnl/set.h>
26 #include <libnftnl/rule.h>
28 #include "linux_list.h"
29 #include "expr/data_reg.h"
31 struct nft_set_elem *nft_set_elem_alloc(
void)
33 struct nft_set_elem *s;
35 s = calloc(1,
sizeof(
struct nft_set_elem));
41 EXPORT_SYMBOL(nft_set_elem_alloc);
43 void nft_set_elem_free(
struct nft_set_elem *s)
45 if (s->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN)) {
53 EXPORT_SYMBOL(nft_set_elem_free);
55 bool nft_set_elem_attr_is_set(
const struct nft_set_elem *s, uint16_t attr)
57 return s->flags & (1 << attr);
59 EXPORT_SYMBOL(nft_set_elem_attr_is_set);
61 void nft_set_elem_attr_unset(
struct nft_set_elem *s, uint16_t attr)
64 case NFT_SET_ELEM_ATTR_CHAIN:
65 if (s->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN)) {
72 case NFT_SET_ELEM_ATTR_FLAGS:
73 case NFT_SET_ELEM_ATTR_KEY:
74 case NFT_SET_ELEM_ATTR_VERDICT:
75 case NFT_SET_ELEM_ATTR_DATA:
81 s->flags &= ~(1 << attr);
83 EXPORT_SYMBOL(nft_set_elem_attr_unset);
85 void nft_set_elem_attr_set(
struct nft_set_elem *s, uint16_t attr,
86 const void *data, uint32_t data_len)
89 case NFT_SET_ELEM_ATTR_FLAGS:
90 s->set_elem_flags = *((uint32_t *)data);
92 case NFT_SET_ELEM_ATTR_KEY:
93 memcpy(&s->key.val, data, data_len);
94 s->key.len = data_len;
96 case NFT_SET_ELEM_ATTR_VERDICT:
97 s->data.verdict = *((uint32_t *)data);
99 case NFT_SET_ELEM_ATTR_CHAIN:
101 xfree(s->data.chain);
103 s->data.chain = strdup(data);
105 case NFT_SET_ELEM_ATTR_DATA:
106 memcpy(s->data.val, data, data_len);
107 s->data.len = data_len;
112 s->flags |= (1 << attr);
114 EXPORT_SYMBOL(nft_set_elem_attr_set);
116 void nft_set_elem_attr_set_u32(
struct nft_set_elem *s, uint16_t attr, uint32_t val)
118 nft_set_elem_attr_set(s, attr, &val,
sizeof(uint32_t));
120 EXPORT_SYMBOL(nft_set_elem_attr_set_u32);
122 void nft_set_elem_attr_set_str(
struct nft_set_elem *s, uint16_t attr,
const char *str)
124 nft_set_elem_attr_set(s, attr, str, strlen(str));
126 EXPORT_SYMBOL(nft_set_elem_attr_set_str);
128 const void *nft_set_elem_attr_get(
struct nft_set_elem *s, uint16_t attr, uint32_t *data_len)
130 if (!(s->flags & (1 << attr)))
134 case NFT_SET_ELEM_ATTR_FLAGS:
135 return &s->set_elem_flags;
136 case NFT_SET_ELEM_ATTR_KEY:
137 *data_len = s->key.len;
139 case NFT_SET_ELEM_ATTR_VERDICT:
140 return &s->data.verdict;
141 case NFT_SET_ELEM_ATTR_CHAIN:
142 return s->data.chain;
143 case NFT_SET_ELEM_ATTR_DATA:
144 *data_len = s->data.len;
149 EXPORT_SYMBOL(nft_set_elem_attr_get);
151 const char *nft_set_elem_attr_get_str(
struct nft_set_elem *s, uint16_t attr)
155 return nft_set_elem_attr_get(s, attr, &size);
157 EXPORT_SYMBOL(nft_set_elem_attr_get_str);
159 uint32_t nft_set_elem_attr_get_u32(
struct nft_set_elem *s, uint16_t attr)
162 uint32_t val = *((uint32_t *)nft_set_elem_attr_get(s, attr, &size));
165 EXPORT_SYMBOL(nft_set_elem_attr_get_u32);
167 void nft_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
168 struct nft_set_elem *e)
170 if (e->flags & (1 << NFT_SET_ELEM_ATTR_FLAGS))
171 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
172 if (e->flags & (1 << NFT_SET_ELEM_ATTR_KEY)) {
173 struct nlattr *nest1;
175 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
176 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
177 mnl_attr_nest_end(nlh, nest1);
179 if (e->flags & (1 << NFT_SET_ELEM_ATTR_VERDICT)) {
180 struct nlattr *nest1, *nest2;
182 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
183 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
184 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
185 if (e->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN))
186 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
188 mnl_attr_nest_end(nlh, nest1);
189 mnl_attr_nest_end(nlh, nest2);
191 if (e->flags & (1 << NFT_SET_ELEM_ATTR_DATA)) {
192 struct nlattr *nest1;
194 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
195 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
196 mnl_attr_nest_end(nlh, nest1);
200 void nft_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nft_set *s)
202 struct nft_set_elem *elem;
203 struct nlattr *nest1;
206 if (s->flags & (1 << NFT_SET_ATTR_NAME))
207 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
208 if (s->flags & (1 << NFT_SET_ATTR_ID))
209 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
210 if (s->flags & (1 << NFT_SET_ATTR_TABLE))
211 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
213 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
214 list_for_each_entry(elem, &s->element_list, head) {
215 struct nlattr *nest2;
217 nest2 = mnl_attr_nest_start(nlh, ++i);
218 nft_set_elem_nlmsg_build_payload(nlh, elem);
219 mnl_attr_nest_end(nlh, nest2);
221 mnl_attr_nest_end(nlh, nest1);
223 EXPORT_SYMBOL(nft_set_elems_nlmsg_build_payload);
225 static int nft_set_elem_parse_attr_cb(
const struct nlattr *attr,
void *data)
227 const struct nlattr **tb = data;
228 int type = mnl_attr_get_type(attr);
230 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
234 case NFTA_SET_ELEM_FLAGS:
235 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
236 perror(
"mnl_attr_validate");
240 case NFTA_SET_ELEM_KEY:
241 case NFTA_SET_ELEM_DATA:
242 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
243 perror(
"mnl_attr_validate");
253 static int nft_set_elems_parse2(
struct nft_set *s,
const struct nlattr *nest)
255 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
256 struct nft_set_elem *e;
259 e = nft_set_elem_alloc();
263 if (mnl_attr_parse_nested(nest, nft_set_elem_parse_attr_cb, tb) < 0) {
264 nft_set_elem_free(e);
268 if (tb[NFTA_SET_ELEM_FLAGS]) {
270 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
271 e->flags |= (1 << NFT_SET_ELEM_ATTR_FLAGS);
273 if (tb[NFTA_SET_ELEM_KEY]) {
274 ret = nft_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
275 e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY);
277 if (tb[NFTA_SET_ELEM_DATA]) {
278 ret = nft_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
281 e->flags |= (1 << NFT_SET_ELEM_ATTR_VERDICT);
284 e->flags |= (1 << NFT_SET_ELEM_ATTR_VERDICT) |
285 (1 << NFT_SET_ELEM_ATTR_CHAIN);
288 e->flags |= (1 << NFT_SET_ELEM_ATTR_DATA);
298 list_add_tail(&e->head, &s->element_list);
304 nft_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
306 const struct nlattr **tb = data;
307 int type = mnl_attr_get_type(attr);
309 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
313 case NFTA_SET_ELEM_LIST_TABLE:
314 case NFTA_SET_ELEM_LIST_SET:
315 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
316 perror(
"mnl_attr_validate");
320 case NFTA_SET_ELEM_LIST_ELEMENTS:
321 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
322 perror(
"mnl_attr_validate");
332 static int nft_set_elems_parse(
struct nft_set *s,
const struct nlattr *nest)
337 mnl_attr_for_each_nested(attr, nest) {
338 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
341 ret = nft_set_elems_parse2(s, attr);
346 int nft_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nft_set *s)
348 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
349 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
352 if (mnl_attr_parse(nlh,
sizeof(*nfg),
353 nft_set_elem_list_parse_attr_cb, tb) < 0)
356 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
358 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
359 s->flags |= (1 << NFT_SET_ATTR_TABLE);
361 if (tb[NFTA_SET_ELEM_LIST_SET]) {
363 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
364 s->flags |= (1 << NFT_SET_ATTR_NAME);
366 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
367 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
368 s->flags |= (1 << NFT_SET_ATTR_ID);
370 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS])
371 ret = nft_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
373 s->family = nfg->nfgen_family;
374 s->flags |= (1 << NFT_SET_ATTR_FAMILY);
378 EXPORT_SYMBOL(nft_set_elems_nlmsg_parse);
381 int nft_mxml_set_elem_parse(mxml_node_t *tree,
struct nft_set_elem *e,
382 struct nft_parse_err *err)
385 uint32_t set_elem_flags;
387 if (nft_mxml_num_parse(tree,
"flags", MXML_DESCEND_FIRST, BASE_DEC,
388 &set_elem_flags, NFT_TYPE_U32, NFT_XML_MAND,
390 nft_set_elem_attr_set_u32(e, NFT_SET_ELEM_ATTR_FLAGS, set_elem_flags);
392 if (nft_mxml_data_reg_parse(tree,
"key", &e->key,
393 NFT_XML_MAND, err) == DATA_VALUE)
394 e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY);
397 set_elem_data = nft_mxml_data_reg_parse(tree,
"data",
398 &e->data, NFT_XML_OPT, err);
399 switch (set_elem_data) {
401 e->flags |= (1 << NFT_SET_ELEM_ATTR_DATA);
404 e->flags |= (1 << NFT_SET_ELEM_ATTR_VERDICT);
405 if (e->data.chain != NULL)
406 e->flags |= (1 << NFT_SET_ELEM_ATTR_CHAIN);
415 static int nft_set_elem_xml_parse(
struct nft_set_elem *e,
const void *xml,
416 struct nft_parse_err *err,
417 enum nft_parse_input input)
423 tree = nft_mxml_build_tree(xml,
"set_elem", err, input);
427 ret = nft_mxml_set_elem_parse(tree, e, err);
436 static int nft_set_elem_json_parse(
struct nft_set_elem *e,
const void *json,
437 struct nft_parse_err *err,
438 enum nft_parse_input input)
444 tree = nft_jansson_create_root(json, &error, err, input);
448 return nft_jansson_set_elem_parse(e, tree, err);
456 nft_set_elem_do_parse(
struct nft_set_elem *e,
enum nft_parse_type type,
457 const void *data,
struct nft_parse_err *err,
458 enum nft_parse_input input)
464 ret = nft_set_elem_xml_parse(e, data, err, input);
467 ret = nft_set_elem_json_parse(e, data, err, input);
477 int nft_set_elem_parse(
struct nft_set_elem *e,
enum nft_parse_type type,
478 const char *data,
struct nft_parse_err *err)
480 return nft_set_elem_do_parse(e, type, data, err, NFT_PARSE_BUFFER);
482 EXPORT_SYMBOL(nft_set_elem_parse);
484 int nft_set_elem_parse_file(
struct nft_set_elem *e,
enum nft_parse_type type,
485 FILE *fp,
struct nft_parse_err *err)
487 return nft_set_elem_do_parse(e, type, fp, err, NFT_PARSE_FILE);
489 EXPORT_SYMBOL(nft_set_elem_parse_file);
491 static int nft_set_elem_snprintf_json(
char *buf,
size_t size,
492 struct nft_set_elem *e, uint32_t flags)
494 int ret, len = size, offset = 0, type = -1;
496 if (e->flags & (1 << NFT_SET_ELEM_ATTR_FLAGS)) {
497 ret = snprintf(buf, len,
"\"flags\":%u,", e->set_elem_flags);
498 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
501 ret = snprintf(buf + offset, len,
"\"key\":{");
502 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
504 ret = nft_data_reg_snprintf(buf + offset, len, &e->key,
505 NFT_OUTPUT_JSON, flags, DATA_VALUE);
506 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
508 ret = snprintf(buf + offset, len,
"}");
509 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
511 if (e->flags & (1 << NFT_SET_ELEM_ATTR_DATA))
513 else if (e->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN))
515 else if (e->flags & (1 << NFT_SET_ELEM_ATTR_VERDICT))
519 ret = snprintf(buf + offset, len,
",\"data\":{");
520 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
522 ret = nft_data_reg_snprintf(buf + offset, len, &e->data,
523 NFT_OUTPUT_JSON, flags, type);
524 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
526 ret = snprintf(buf + offset, len,
"}");
527 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
533 static int nft_set_elem_snprintf_default(
char *buf,
size_t size,
534 struct nft_set_elem *e)
536 int ret, len = size, offset = 0, i;
538 ret = snprintf(buf, len,
"element ");
539 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
541 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
542 ret = snprintf(buf+offset, len,
"%.8x ", e->key.val[i]);
543 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
546 ret = snprintf(buf+offset, len,
" : ");
547 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
549 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
550 ret = snprintf(buf+offset, len,
"%.8x ", e->data.val[i]);
551 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
554 ret = snprintf(buf+offset, len,
"%u [end]", e->set_elem_flags);
555 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
560 static int nft_set_elem_snprintf_xml(
char *buf,
size_t size,
561 struct nft_set_elem *e, uint32_t flags)
563 int ret, len = size, offset = 0, type = DATA_NONE;
565 ret = snprintf(buf, size,
"<set_elem>");
566 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
568 if (e->flags & (1 << NFT_SET_ELEM_ATTR_FLAGS)) {
569 ret = snprintf(buf + offset, size,
"<flags>%u</flags>",
571 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
574 if (e->flags & (1 << NFT_SET_ELEM_ATTR_KEY)) {
575 ret = snprintf(buf + offset, len,
"<key>");
576 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
578 ret = nft_data_reg_snprintf(buf + offset, len, &e->key,
579 NFT_OUTPUT_XML, flags, DATA_VALUE);
580 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
582 ret = snprintf(buf + offset, len,
"</key>");
583 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
586 if (e->flags & (1 << NFT_SET_ELEM_ATTR_DATA))
588 else if (e->flags & (1 << NFT_SET_ELEM_ATTR_CHAIN))
590 else if (e->flags & (1 << NFT_SET_ELEM_ATTR_VERDICT))
593 if (type != DATA_NONE) {
594 ret = snprintf(buf + offset, len,
"<data>");
595 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
597 ret = nft_data_reg_snprintf(buf + offset, len, &e->data,
598 NFT_OUTPUT_XML, flags, type);
599 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
601 ret = snprintf(buf + offset, len,
"</data>");
602 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
605 ret = snprintf(buf + offset, len,
"</set_elem>");
606 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
611 int nft_set_elem_snprintf(
char *buf,
size_t size,
struct nft_set_elem *e,
612 uint32_t type, uint32_t flags)
614 int ret, len = size, offset = 0;
616 ret = nft_event_header_snprintf(buf+offset, len, type, flags);
617 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
620 case NFT_OUTPUT_DEFAULT:
621 ret = nft_set_elem_snprintf_default(buf+offset, len, e);
624 ret = nft_set_elem_snprintf_xml(buf+offset, len, e, flags);
626 case NFT_OUTPUT_JSON:
627 ret = nft_set_elem_snprintf_json(buf+offset, len, e, flags);
633 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
635 ret = nft_event_footer_snprintf(buf+offset, len, type, flags);
636 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
640 EXPORT_SYMBOL(nft_set_elem_snprintf);
642 static inline int nft_set_elem_do_snprintf(
char *buf,
size_t size,
void *e,
643 uint32_t type, uint32_t flags)
645 return nft_set_elem_snprintf(buf, size, e, type, flags);
648 int nft_set_elem_fprintf(FILE *fp,
struct nft_set_elem *se, uint32_t type,
651 return nft_fprintf(fp, se, type, flags, nft_set_elem_do_snprintf);
653 EXPORT_SYMBOL(nft_set_elem_fprintf);
655 int nft_set_elem_foreach(
struct nft_set *s,
656 int (*cb)(
struct nft_set_elem *e,
void *data),
659 struct nft_set_elem *elem;
662 list_for_each_entry(elem, &s->element_list, head) {
663 ret = cb(elem, data);
669 EXPORT_SYMBOL(nft_set_elem_foreach);
672 struct list_head *list;
673 struct nft_set_elem *cur;
684 iter->list = &s->element_list;
685 iter->cur = list_entry(s->element_list.next,
struct nft_set_elem, head);
689 EXPORT_SYMBOL(nft_set_elems_iter_create);
695 EXPORT_SYMBOL(nft_set_elems_iter_cur);
699 struct nft_set_elem *s = iter->cur;
701 iter->cur = list_entry(iter->cur->head.next,
struct nft_set_elem, head);
702 if (&iter->cur->head == iter->list->next)
707 EXPORT_SYMBOL(nft_set_elems_iter_next);
713 EXPORT_SYMBOL(nft_set_elems_iter_destroy);