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));
42 EXPORT_SYMBOL(nftnl_set_elem_free);
43 void nftnl_set_elem_free(
struct nftnl_set_elem *s)
45 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
48 if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
49 nftnl_expr_free(s->expr);
51 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
54 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
60 EXPORT_SYMBOL(nftnl_set_elem_is_set);
61 bool nftnl_set_elem_is_set(
const struct nftnl_set_elem *s, uint16_t attr)
63 return s->flags & (1 << attr);
66 EXPORT_SYMBOL(nftnl_set_elem_unset);
67 void nftnl_set_elem_unset(
struct nftnl_set_elem *s, uint16_t attr)
69 if (!(s->flags & (1 << attr)))
73 case NFTNL_SET_ELEM_CHAIN:
76 case NFTNL_SET_ELEM_FLAGS:
77 case NFTNL_SET_ELEM_KEY:
78 case NFTNL_SET_ELEM_VERDICT:
79 case NFTNL_SET_ELEM_DATA:
80 case NFTNL_SET_ELEM_TIMEOUT:
81 case NFTNL_SET_ELEM_EXPIRATION:
83 case NFTNL_SET_ELEM_USERDATA:
86 case NFTNL_SET_ELEM_EXPR:
87 nftnl_expr_free(s->expr);
89 case NFTNL_SET_ELEM_OBJREF:
96 s->flags &= ~(1 << attr);
99 EXPORT_SYMBOL(nftnl_set_elem_set);
100 int 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 memcpy(&s->set_elem_flags, data,
sizeof(s->set_elem_flags));
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 memcpy(&s->data.verdict, data,
sizeof(s->data.verdict));
114 case NFTNL_SET_ELEM_CHAIN:
115 if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
116 xfree(s->data.chain);
118 s->data.chain = strdup(data);
122 case NFTNL_SET_ELEM_DATA:
123 memcpy(s->data.val, data, data_len);
124 s->data.len = data_len;
126 case NFTNL_SET_ELEM_TIMEOUT:
127 memcpy(&s->timeout, data,
sizeof(s->timeout));
129 case NFTNL_SET_ELEM_USERDATA:
130 if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
133 s->user.data = malloc(data_len);
136 memcpy(s->user.data, data, data_len);
137 s->user.len = data_len;
139 case NFTNL_SET_ELEM_OBJREF:
140 if (s->flags & (1 << NFTNL_SET_ELEM_OBJREF))
143 s->objref = strdup(data);
148 s->flags |= (1 << attr);
152 EXPORT_SYMBOL(nftnl_set_elem_set_u32);
153 void nftnl_set_elem_set_u32(
struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
155 nftnl_set_elem_set(s, attr, &val,
sizeof(uint32_t));
158 EXPORT_SYMBOL(nftnl_set_elem_set_u64);
159 void nftnl_set_elem_set_u64(
struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
161 nftnl_set_elem_set(s, attr, &val,
sizeof(uint64_t));
164 EXPORT_SYMBOL(nftnl_set_elem_set_str);
165 int nftnl_set_elem_set_str(
struct nftnl_set_elem *s, uint16_t attr,
const char *str)
167 return nftnl_set_elem_set(s, attr, str, strlen(str) + 1);
170 EXPORT_SYMBOL(nftnl_set_elem_get);
171 const void *nftnl_set_elem_get(
struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
173 if (!(s->flags & (1 << attr)))
177 case NFTNL_SET_ELEM_FLAGS:
178 *data_len =
sizeof(s->set_elem_flags);
179 return &s->set_elem_flags;
180 case NFTNL_SET_ELEM_KEY:
181 *data_len = s->key.len;
183 case NFTNL_SET_ELEM_VERDICT:
184 *data_len =
sizeof(s->data.verdict);
185 return &s->data.verdict;
186 case NFTNL_SET_ELEM_CHAIN:
187 *data_len = strlen(s->data.chain) + 1;
188 return s->data.chain;
189 case NFTNL_SET_ELEM_DATA:
190 *data_len = s->data.len;
192 case NFTNL_SET_ELEM_TIMEOUT:
193 *data_len =
sizeof(s->timeout);
195 case NFTNL_SET_ELEM_EXPIRATION:
196 *data_len =
sizeof(s->expiration);
197 return &s->expiration;
198 case NFTNL_SET_ELEM_USERDATA:
199 *data_len = s->user.len;
201 case NFTNL_SET_ELEM_EXPR:
203 case NFTNL_SET_ELEM_OBJREF:
204 *data_len = strlen(s->objref) + 1;
210 EXPORT_SYMBOL(nftnl_set_elem_get_str);
211 const char *nftnl_set_elem_get_str(
struct nftnl_set_elem *s, uint16_t attr)
215 return nftnl_set_elem_get(s, attr, &size);
218 EXPORT_SYMBOL(nftnl_set_elem_get_u32);
219 uint32_t nftnl_set_elem_get_u32(
struct nftnl_set_elem *s, uint16_t attr)
223 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
228 EXPORT_SYMBOL(nftnl_set_elem_get_u64);
229 uint64_t nftnl_set_elem_get_u64(
struct nftnl_set_elem *s, uint16_t attr)
234 memcpy(&val, nftnl_set_elem_get(s, attr, &size),
sizeof(val));
239 struct nftnl_set_elem *nftnl_set_elem_clone(
struct nftnl_set_elem *elem)
241 struct nftnl_set_elem *newelem;
243 newelem = nftnl_set_elem_alloc();
247 memcpy(newelem, elem,
sizeof(*elem));
249 if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
250 newelem->data.chain = strdup(elem->data.chain);
251 if (!newelem->data.chain)
257 nftnl_set_elem_free(newelem);
261 void nftnl_set_elem_nlmsg_build_payload(
struct nlmsghdr *nlh,
262 struct nftnl_set_elem *e)
264 if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
265 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
266 if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
267 mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
268 if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
269 struct nlattr *nest1;
271 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
272 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
273 mnl_attr_nest_end(nlh, nest1);
275 if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
276 struct nlattr *nest1, *nest2;
278 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
279 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
280 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
281 if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
282 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
284 mnl_attr_nest_end(nlh, nest1);
285 mnl_attr_nest_end(nlh, nest2);
287 if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
288 struct nlattr *nest1;
290 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
291 mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
292 mnl_attr_nest_end(nlh, nest1);
294 if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
295 mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
296 if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
297 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
300 static void nftnl_set_elem_nlmsg_build_def(
struct nlmsghdr *nlh,
301 const struct nftnl_set *s)
303 if (s->flags & (1 << NFTNL_SET_NAME))
304 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
305 if (s->flags & (1 << NFTNL_SET_ID))
306 mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
307 if (s->flags & (1 << NFTNL_SET_TABLE))
308 mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
311 static struct nlattr *nftnl_set_elem_build(
struct nlmsghdr *nlh,
312 struct nftnl_set_elem *elem,
int i)
314 struct nlattr *nest2;
316 nest2 = mnl_attr_nest_start(nlh, i);
317 nftnl_set_elem_nlmsg_build_payload(nlh, elem);
318 mnl_attr_nest_end(nlh, nest2);
323 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload);
324 void nftnl_set_elems_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_set *s)
326 struct nftnl_set_elem *elem;
327 struct nlattr *nest1;
330 nftnl_set_elem_nlmsg_build_def(nlh, s);
332 if (list_empty(&s->element_list))
335 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
336 list_for_each_entry(elem, &s->element_list, head)
337 nftnl_set_elem_build(nlh, elem, ++i);
339 mnl_attr_nest_end(nlh, nest1);
342 static
int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr,
void *data)
344 const struct nlattr **tb = data;
345 int type = mnl_attr_get_type(attr);
347 if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
351 case NFTA_SET_ELEM_FLAGS:
352 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
355 case NFTA_SET_ELEM_TIMEOUT:
356 case NFTA_SET_ELEM_EXPIRATION:
357 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
360 case NFTA_SET_ELEM_KEY:
361 case NFTA_SET_ELEM_DATA:
362 case NFTA_SET_ELEM_EXPR:
363 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
366 case NFTA_SET_ELEM_USERDATA:
367 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
376 static int nftnl_set_elems_parse2(
struct nftnl_set *s,
const struct nlattr *nest)
378 struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
379 struct nftnl_set_elem *e;
382 e = nftnl_set_elem_alloc();
386 ret = mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb);
390 if (tb[NFTA_SET_ELEM_FLAGS]) {
392 ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
393 e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
395 if (tb[NFTA_SET_ELEM_TIMEOUT]) {
396 e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
397 e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
399 if (tb[NFTA_SET_ELEM_EXPIRATION]) {
400 e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
401 e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
403 if (tb[NFTA_SET_ELEM_KEY]) {
404 ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
407 e->flags |= (1 << NFTNL_SET_ELEM_KEY);
409 if (tb[NFTA_SET_ELEM_DATA]) {
410 ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
415 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
418 e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
419 (1 << NFTNL_SET_ELEM_CHAIN);
422 e->flags |= (1 << NFTNL_SET_ELEM_DATA);
426 if (tb[NFTA_SET_ELEM_EXPR]) {
427 e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
428 if (e->expr == NULL) {
432 e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
434 if (tb[NFTA_SET_ELEM_USERDATA]) {
436 mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
438 if (e->flags & (1 << NFTNL_RULE_USERDATA))
441 e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
442 e->user.data = malloc(e->user.len);
443 if (e->user.data == NULL) {
447 memcpy(e->user.data, udata, e->user.len);
448 e->flags |= (1 << NFTNL_RULE_USERDATA);
450 if (tb[NFTA_SET_ELEM_OBJREF]) {
451 e->objref = strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_OBJREF]));
452 if (e->objref == NULL) {
456 e->flags |= (1 << NFTNL_SET_ELEM_OBJREF);
460 list_add_tail(&e->head, &s->element_list);
464 nftnl_expr_free(e->expr);
466 nftnl_set_elem_free(e);
471 nftnl_set_elem_list_parse_attr_cb(
const struct nlattr *attr,
void *data)
473 const struct nlattr **tb = data;
474 int type = mnl_attr_get_type(attr);
476 if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
480 case NFTA_SET_ELEM_LIST_TABLE:
481 case NFTA_SET_ELEM_LIST_SET:
482 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
485 case NFTA_SET_ELEM_LIST_ELEMENTS:
486 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
495 static int nftnl_set_elems_parse(
struct nftnl_set *s,
const struct nlattr *nest)
500 mnl_attr_for_each_nested(attr, nest) {
501 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
504 ret = nftnl_set_elems_parse2(s, attr);
511 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_parse);
512 int nftnl_set_elems_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_set *s)
514 struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
515 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
518 if (mnl_attr_parse(nlh,
sizeof(*nfg),
519 nftnl_set_elem_list_parse_attr_cb, tb) < 0)
522 if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
523 if (s->flags & (1 << NFTNL_SET_TABLE))
526 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
529 s->flags |= (1 << NFTNL_SET_TABLE);
531 if (tb[NFTA_SET_ELEM_LIST_SET]) {
532 if (s->flags & (1 << NFTNL_SET_NAME))
535 strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
538 s->flags |= (1 << NFTNL_SET_NAME);
540 if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
541 s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
542 s->flags |= (1 << NFTNL_SET_ID);
544 if (tb[NFTA_SET_ELEM_LIST_ELEMENTS]) {
545 ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
550 s->family = nfg->nfgen_family;
551 s->flags |= (1 << NFTNL_SET_FAMILY);
556 EXPORT_SYMBOL(nftnl_set_elem_parse);
557 int nftnl_set_elem_parse(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
558 const char *data,
struct nftnl_parse_err *err)
564 EXPORT_SYMBOL(nftnl_set_elem_parse_file);
565 int nftnl_set_elem_parse_file(
struct nftnl_set_elem *e,
enum nftnl_parse_type type,
566 FILE *fp,
struct nftnl_parse_err *err)
572 static int nftnl_set_elem_snprintf_default(
char *buf,
size_t size,
573 const struct nftnl_set_elem *e)
575 int ret, remain = size, offset = 0, i;
577 ret = snprintf(buf, remain,
"element ");
578 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
580 for (i = 0; i < div_round_up(e->key.len,
sizeof(uint32_t)); i++) {
581 ret = snprintf(buf + offset, remain,
"%.8x ", e->key.val[i]);
582 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
585 ret = snprintf(buf + offset, remain,
" : ");
586 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
588 for (i = 0; i < div_round_up(e->data.len,
sizeof(uint32_t)); i++) {
589 ret = snprintf(buf + offset, remain,
"%.8x ", e->data.val[i]);
590 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
593 ret = snprintf(buf + offset, remain,
"%u [end]", e->set_elem_flags);
594 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
597 ret = snprintf(buf + offset, remain,
" userdata = {");
598 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
600 for (i = 0; i < e->user.len; i++) {
601 char *c = e->user.data;
603 ret = snprintf(buf + offset, remain,
"%c",
604 isalnum(c[i]) ? c[i] : 0);
605 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
608 ret = snprintf(buf + offset, remain,
" }\n");
609 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
615 static int nftnl_set_elem_cmd_snprintf(
char *buf,
size_t size,
616 const struct nftnl_set_elem *e,
617 uint32_t cmd, uint32_t type,
620 int ret, remain = size, offset = 0;
623 case NFTNL_OUTPUT_DEFAULT:
624 ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e);
625 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
627 case NFTNL_OUTPUT_XML:
628 case NFTNL_OUTPUT_JSON:
637 EXPORT_SYMBOL(nftnl_set_elem_snprintf);
638 int nftnl_set_elem_snprintf(
char *buf,
size_t size,
639 const struct nftnl_set_elem *e,
640 uint32_t type, uint32_t flags)
645 return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
649 static int nftnl_set_elem_do_snprintf(
char *buf,
size_t size,
const void *e,
650 uint32_t cmd, uint32_t type,
653 return nftnl_set_elem_snprintf(buf, size, e, type, flags);
656 EXPORT_SYMBOL(nftnl_set_elem_fprintf);
657 int nftnl_set_elem_fprintf(FILE *fp,
struct nftnl_set_elem *se, uint32_t type,
660 return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
661 nftnl_set_elem_do_snprintf);
664 EXPORT_SYMBOL(nftnl_set_elem_foreach);
665 int nftnl_set_elem_foreach(
struct nftnl_set *s,
666 int (*cb)(
struct nftnl_set_elem *e,
void *data),
669 struct nftnl_set_elem *elem;
672 list_for_each_entry(elem, &s->element_list, head) {
673 ret = cb(elem, data);
681 const struct nftnl_set *set;
682 const struct list_head *list;
683 struct nftnl_set_elem *cur;
686 EXPORT_SYMBOL(nftnl_set_elems_iter_create);
688 nftnl_set_elems_iter_create(
const struct nftnl_set *s)
697 iter->list = &s->element_list;
698 if (list_empty(&s->element_list))
701 iter->cur = list_entry(s->element_list.next,
702 struct nftnl_set_elem, head);
707 EXPORT_SYMBOL(nftnl_set_elems_iter_cur);
708 struct nftnl_set_elem *
714 EXPORT_SYMBOL(nftnl_set_elems_iter_next);
717 struct nftnl_set_elem *s = iter->cur;
722 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_set_elem, head);
723 if (&iter->cur->head == iter->list->next)
729 EXPORT_SYMBOL(nftnl_set_elems_iter_destroy);
735 static bool nftnl_attr_nest_overflow(
struct nlmsghdr *nlh,
736 const struct nlattr *from,
737 const struct nlattr *to)
739 int len = (
void *)to + to->nla_len - (
void *)from;
745 if (len > UINT16_MAX) {
746 nlh->nlmsg_len -= to->nla_len;
752 EXPORT_SYMBOL(nftnl_set_elems_nlmsg_build_payload_iter);
753 int nftnl_set_elems_nlmsg_build_payload_iter(
struct nlmsghdr *nlh,
756 struct nftnl_set_elem *elem;
757 struct nlattr *nest1, *nest2;
760 nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
763 if (list_empty(&iter->set->element_list))
766 nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
767 elem = nftnl_set_elems_iter_next(iter);
768 while (elem != NULL) {
769 nest2 = nftnl_set_elem_build(nlh, elem, ++i);
770 if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
772 iter->cur = list_entry(iter->cur->head.prev,
773 struct nftnl_set_elem, head);
777 elem = nftnl_set_elems_iter_next(iter);
779 mnl_attr_nest_end(nlh, nest1);