13#include <libmnl/libmnl.h>
14#include <linux/netfilter/nfnetlink.h>
15#include <linux/netfilter/nf_tables.h>
16#include <linux/netfilter.h>
17#include <linux/netfilter_arp.h>
19#include <libnftnl/flowtable.h>
22 struct list_head head;
29 struct nftnl_str_array dev_array;
36EXPORT_SYMBOL(nftnl_flowtable_alloc);
42EXPORT_SYMBOL(nftnl_flowtable_free);
45 if (c->flags & (1 << NFTNL_FLOWTABLE_NAME))
47 if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE))
49 if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES))
50 nftnl_str_array_clear((
struct nftnl_str_array *)&c->dev_array);
54EXPORT_SYMBOL(nftnl_flowtable_is_set);
55bool nftnl_flowtable_is_set(
const struct nftnl_flowtable *c, uint16_t attr)
57 return c->flags & (1 << attr);
60EXPORT_SYMBOL(nftnl_flowtable_unset);
63 if (!(c->flags & (1 << attr)))
67 case NFTNL_FLOWTABLE_NAME:
70 case NFTNL_FLOWTABLE_TABLE:
73 case NFTNL_FLOWTABLE_HOOKNUM:
74 case NFTNL_FLOWTABLE_PRIO:
75 case NFTNL_FLOWTABLE_USE:
76 case NFTNL_FLOWTABLE_FAMILY:
77 case NFTNL_FLOWTABLE_FLAGS:
78 case NFTNL_FLOWTABLE_HANDLE:
80 case NFTNL_FLOWTABLE_DEVICES:
81 nftnl_str_array_clear(&c->dev_array);
87 c->flags &= ~(1 << attr);
90static uint32_t nftnl_flowtable_validate[NFTNL_FLOWTABLE_MAX + 1] = {
91 [NFTNL_FLOWTABLE_HOOKNUM] =
sizeof(uint32_t),
92 [NFTNL_FLOWTABLE_PRIO] =
sizeof(int32_t),
93 [NFTNL_FLOWTABLE_FAMILY] =
sizeof(uint32_t),
94 [NFTNL_FLOWTABLE_SIZE] =
sizeof(uint32_t),
95 [NFTNL_FLOWTABLE_FLAGS] =
sizeof(uint32_t),
96 [NFTNL_FLOWTABLE_HANDLE] =
sizeof(uint64_t),
99EXPORT_SYMBOL(nftnl_flowtable_set_data);
101 const void *data, uint32_t data_len)
103 nftnl_assert_attr_exists(attr, NFTNL_FLOWTABLE_MAX);
104 nftnl_assert_validate(data, nftnl_flowtable_validate, attr, data_len);
107 case NFTNL_FLOWTABLE_NAME:
108 return nftnl_set_str_attr(&c->name, &c->flags,
109 attr, data, data_len);
110 case NFTNL_FLOWTABLE_TABLE:
111 return nftnl_set_str_attr(&c->table, &c->flags,
112 attr, data, data_len);
114 case NFTNL_FLOWTABLE_HOOKNUM:
115 memcpy(&c->hooknum, data,
sizeof(c->hooknum));
117 case NFTNL_FLOWTABLE_PRIO:
118 memcpy(&c->prio, data,
sizeof(c->prio));
120 case NFTNL_FLOWTABLE_FAMILY:
121 memcpy(&c->family, data,
sizeof(c->family));
123 case NFTNL_FLOWTABLE_DEVICES:
124 if (nftnl_str_array_set(&c->dev_array, data) < 0)
127 case NFTNL_FLOWTABLE_SIZE:
128 memcpy(&c->size, data,
sizeof(c->size));
130 case NFTNL_FLOWTABLE_FLAGS:
131 memcpy(&c->ft_flags, data,
sizeof(c->ft_flags));
133 case NFTNL_FLOWTABLE_HANDLE:
134 memcpy(&c->handle, data,
sizeof(c->handle));
137 c->flags |= (1 << attr);
141void nftnl_flowtable_set(
struct nftnl_flowtable *c, uint16_t attr,
const void *data) __visible;
142void nftnl_flowtable_set(
struct nftnl_flowtable *c, uint16_t attr,
const void *data)
144 nftnl_flowtable_set_data(c, attr, data, nftnl_flowtable_validate[attr]);
147EXPORT_SYMBOL(nftnl_flowtable_set_u32);
148void nftnl_flowtable_set_u32(
struct nftnl_flowtable *c, uint16_t attr, uint32_t data)
150 nftnl_flowtable_set_data(c, attr, &data,
sizeof(uint32_t));
153EXPORT_SYMBOL(nftnl_flowtable_set_s32);
154void nftnl_flowtable_set_s32(
struct nftnl_flowtable *c, uint16_t attr, int32_t data)
156 nftnl_flowtable_set_data(c, attr, &data,
sizeof(int32_t));
159EXPORT_SYMBOL(nftnl_flowtable_set_str);
160int nftnl_flowtable_set_str(
struct nftnl_flowtable *c, uint16_t attr,
const char *str)
162 return nftnl_flowtable_set_data(c, attr, str, strlen(str) + 1);
165EXPORT_SYMBOL(nftnl_flowtable_set_u64);
166void nftnl_flowtable_set_u64(
struct nftnl_flowtable *c, uint16_t attr, uint64_t data)
168 nftnl_flowtable_set_data(c, attr, &data,
sizeof(uint64_t));
171EXPORT_SYMBOL(nftnl_flowtable_set_array);
175 return nftnl_flowtable_set_data(c, attr, data, 0);
178EXPORT_SYMBOL(nftnl_flowtable_get_data);
180 uint16_t attr, uint32_t *data_len)
182 if (!(c->flags & (1 << attr)))
186 case NFTNL_FLOWTABLE_NAME:
187 *data_len = strlen(c->name) + 1;
189 case NFTNL_FLOWTABLE_TABLE:
190 *data_len = strlen(c->table) + 1;
192 case NFTNL_FLOWTABLE_HOOKNUM:
193 *data_len =
sizeof(uint32_t);
195 case NFTNL_FLOWTABLE_PRIO:
196 *data_len =
sizeof(int32_t);
198 case NFTNL_FLOWTABLE_FAMILY:
199 *data_len =
sizeof(int32_t);
201 case NFTNL_FLOWTABLE_DEVICES:
203 return c->dev_array.array;
204 case NFTNL_FLOWTABLE_SIZE:
205 *data_len =
sizeof(int32_t);
207 case NFTNL_FLOWTABLE_FLAGS:
208 *data_len =
sizeof(int32_t);
210 case NFTNL_FLOWTABLE_HANDLE:
211 *data_len =
sizeof(uint64_t);
217EXPORT_SYMBOL(nftnl_flowtable_get);
218const void *nftnl_flowtable_get(
const struct nftnl_flowtable *c, uint16_t attr)
221 return nftnl_flowtable_get_data(c, attr, &data_len);
224EXPORT_SYMBOL(nftnl_flowtable_get_str);
225const char *nftnl_flowtable_get_str(
const struct nftnl_flowtable *c, uint16_t attr)
227 return nftnl_flowtable_get(c, attr);
230EXPORT_SYMBOL(nftnl_flowtable_get_u32);
231uint32_t nftnl_flowtable_get_u32(
const struct nftnl_flowtable *c, uint16_t attr)
233 uint32_t data_len = 0;
234 const uint32_t *val = nftnl_flowtable_get_data(c, attr, &data_len);
236 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
238 return val ? *val : 0;
241EXPORT_SYMBOL(nftnl_flowtable_get_u64);
242uint64_t nftnl_flowtable_get_u64(
const struct nftnl_flowtable *c, uint16_t attr)
244 uint32_t data_len = 0;
245 const uint64_t *val = nftnl_flowtable_get_data(c, attr, &data_len);
247 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
249 return val ? *val : 0;
252EXPORT_SYMBOL(nftnl_flowtable_get_s32);
253int32_t nftnl_flowtable_get_s32(
const struct nftnl_flowtable *c, uint16_t attr)
255 uint32_t data_len = 0;
256 const int32_t *val = nftnl_flowtable_get_data(c, attr, &data_len);
258 nftnl_assert(val, attr, data_len ==
sizeof(int32_t));
260 return val ? *val : 0;
263EXPORT_SYMBOL(nftnl_flowtable_get_array);
264const char *
const *nftnl_flowtable_get_array(
const struct nftnl_flowtable *c, uint16_t attr)
267 const char *
const *val = nftnl_flowtable_get_data(c, attr, &data_len);
269 nftnl_assert(val, attr, attr == NFTNL_FLOWTABLE_DEVICES);
274EXPORT_SYMBOL(nftnl_flowtable_nlmsg_build_payload);
275void nftnl_flowtable_nlmsg_build_payload(
struct nlmsghdr *nlh,
278 struct nlattr *nest = NULL;
281 if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE))
282 mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_TABLE, c->table);
283 if (c->flags & (1 << NFTNL_FLOWTABLE_NAME))
284 mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_NAME, c->name);
286 if (c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM) ||
287 c->flags & (1 << NFTNL_FLOWTABLE_PRIO) ||
288 c->flags & (1 << NFTNL_FLOWTABLE_DEVICES))
289 nest = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK);
291 if (c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM))
292 mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_HOOK_NUM, htonl(c->hooknum));
293 if (c->flags & (1 << NFTNL_FLOWTABLE_PRIO))
294 mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(c->prio));
296 if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) {
297 struct nlattr *nest_dev;
300 nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS);
301 nftnl_str_array_foreach(dev, &c->dev_array, i)
302 mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev);
303 mnl_attr_nest_end(nlh, nest_dev);
307 mnl_attr_nest_end(nlh, nest);
309 if (c->flags & (1 << NFTNL_FLOWTABLE_FLAGS))
310 mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_FLAGS, htonl(c->ft_flags));
311 if (c->flags & (1 << NFTNL_FLOWTABLE_USE))
312 mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_USE, htonl(c->use));
313 if (c->flags & (1 << NFTNL_FLOWTABLE_HANDLE))
314 mnl_attr_put_u64(nlh, NFTA_FLOWTABLE_HANDLE, htobe64(c->handle));
317static int nftnl_flowtable_parse_attr_cb(
const struct nlattr *attr,
void *data)
319 const struct nlattr **tb = data;
320 int type = mnl_attr_get_type(attr);
322 if (mnl_attr_type_valid(attr, NFTA_FLOWTABLE_MAX) < 0)
326 case NFTA_FLOWTABLE_NAME:
327 case NFTA_FLOWTABLE_TABLE:
328 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
331 case NFTA_FLOWTABLE_HOOK:
332 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
335 case NFTA_FLOWTABLE_FLAGS:
336 case NFTA_FLOWTABLE_USE:
337 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
340 case NFTA_FLOWTABLE_HANDLE:
341 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
350static int nftnl_flowtable_parse_hook_cb(
const struct nlattr *attr,
void *data)
352 const struct nlattr **tb = data;
353 int type = mnl_attr_get_type(attr);
355 if (mnl_attr_type_valid(attr, NFTA_FLOWTABLE_HOOK_MAX) < 0)
359 case NFTA_FLOWTABLE_HOOK_NUM:
360 case NFTA_FLOWTABLE_HOOK_PRIORITY:
361 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
364 case NFTA_FLOWTABLE_HOOK_DEVS:
365 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
374static int nftnl_flowtable_parse_hook(
struct nlattr *attr,
struct nftnl_flowtable *c)
376 struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1] = {};
379 if (mnl_attr_parse_nested(attr, nftnl_flowtable_parse_hook_cb, tb) < 0)
382 if (tb[NFTA_FLOWTABLE_HOOK_NUM]) {
383 c->hooknum = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
384 c->flags |= (1 << NFTNL_FLOWTABLE_HOOKNUM);
386 if (tb[NFTA_FLOWTABLE_HOOK_PRIORITY]) {
387 c->prio = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY]));
388 c->flags |= (1 << NFTNL_FLOWTABLE_PRIO);
390 if (tb[NFTA_FLOWTABLE_HOOK_DEVS]) {
391 ret = nftnl_parse_devs(&c->dev_array,
392 tb[NFTA_FLOWTABLE_HOOK_DEVS]);
395 c->flags |= (1 << NFTNL_FLOWTABLE_DEVICES);
401EXPORT_SYMBOL(nftnl_flowtable_nlmsg_parse);
402int nftnl_flowtable_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_flowtable *c)
404 struct nlattr *tb[NFTA_FLOWTABLE_MAX + 1] = {};
405 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
408 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_flowtable_parse_attr_cb, tb) < 0)
411 if (tb[NFTA_FLOWTABLE_NAME]) {
412 if (c->flags & (1 << NFTNL_FLOWTABLE_NAME))
414 c->name = strdup(mnl_attr_get_str(tb[NFTA_FLOWTABLE_NAME]));
417 c->flags |= (1 << NFTNL_FLOWTABLE_NAME);
419 if (tb[NFTA_FLOWTABLE_TABLE]) {
420 if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE))
422 c->table = strdup(mnl_attr_get_str(tb[NFTA_FLOWTABLE_TABLE]));
425 c->flags |= (1 << NFTNL_FLOWTABLE_TABLE);
427 if (tb[NFTA_FLOWTABLE_HOOK]) {
428 ret = nftnl_flowtable_parse_hook(tb[NFTA_FLOWTABLE_HOOK], c);
432 if (tb[NFTA_FLOWTABLE_FLAGS]) {
433 c->ft_flags = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_FLAGS]));
434 c->flags |= (1 << NFTNL_FLOWTABLE_FLAGS);
436 if (tb[NFTA_FLOWTABLE_USE]) {
437 c->use = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_USE]));
438 c->flags |= (1 << NFTNL_FLOWTABLE_USE);
440 if (tb[NFTA_FLOWTABLE_HANDLE]) {
441 c->handle = be64toh(mnl_attr_get_u64(tb[NFTA_FLOWTABLE_HANDLE]));
442 c->flags |= (1 << NFTNL_FLOWTABLE_HANDLE);
445 c->family = nfg->nfgen_family;
446 c->flags |= (1 << NFTNL_FLOWTABLE_FAMILY);
451static const char *nftnl_hooknum2str(
int family,
int hooknum)
459 case NF_INET_PRE_ROUTING:
461 case NF_INET_LOCAL_IN:
463 case NF_INET_FORWARD:
465 case NF_INET_LOCAL_OUT:
467 case NF_INET_POST_ROUTING:
468 return "postrouting";
483 case NF_NETDEV_INGRESS:
491EXPORT_SYMBOL(nftnl_flowtable_parse);
492int nftnl_flowtable_parse(
struct nftnl_flowtable *c,
enum nftnl_parse_type type,
493 const char *data,
struct nftnl_parse_err *err)
499EXPORT_SYMBOL(nftnl_flowtable_parse_file);
501 enum nftnl_parse_type type,
502 FILE *fp,
struct nftnl_parse_err *err)
508static int nftnl_flowtable_snprintf_default(
char *buf,
size_t remain,
511 int ret, offset = 0, i;
514 ret = snprintf(buf, remain,
"flow table %s %s use %u size %u flags %x",
515 c->table, c->name, c->use, c->size, c->ft_flags);
516 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
518 if (c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM)) {
519 ret = snprintf(buf + offset, remain,
" hook %s prio %d ",
520 nftnl_hooknum2str(c->family, c->hooknum),
522 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
524 if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) {
525 ret = snprintf(buf + offset, remain,
" dev { ");
526 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
528 nftnl_str_array_foreach(dev, &c->dev_array, i) {
529 ret = snprintf(buf + offset, remain,
" %s ",
531 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
533 ret = snprintf(buf + offset, remain,
" } ");
534 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
541static int nftnl_flowtable_cmd_snprintf(
char *buf,
size_t remain,
543 uint32_t cmd, uint32_t type,
548 if (type != NFTNL_OUTPUT_DEFAULT)
551 ret = nftnl_flowtable_snprintf_default(buf + offset, remain, c);
552 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
556EXPORT_SYMBOL(nftnl_flowtable_snprintf);
557int nftnl_flowtable_snprintf(
char *buf,
size_t size,
const struct nftnl_flowtable *c,
558 uint32_t type, uint32_t flags)
563 return nftnl_flowtable_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
567static int nftnl_flowtable_do_snprintf(
char *buf,
size_t size,
const void *c,
568 uint32_t cmd, uint32_t type, uint32_t flags)
570 return nftnl_flowtable_snprintf(buf, size, c, type, flags);
573EXPORT_SYMBOL(nftnl_flowtable_fprintf);
575 uint32_t type, uint32_t flags)
577 return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
578 nftnl_flowtable_do_snprintf);
582 struct list_head list;
585EXPORT_SYMBOL(nftnl_flowtable_list_alloc);
594 INIT_LIST_HEAD(&list->list);
599EXPORT_SYMBOL(nftnl_flowtable_list_free);
604 list_for_each_entry_safe(s, tmp, &list->list, head) {
606 nftnl_flowtable_free(s);
611EXPORT_SYMBOL(nftnl_flowtable_list_is_empty);
614 return list_empty(&list->list);
617EXPORT_SYMBOL(nftnl_flowtable_list_add);
621 list_add(&s->head, &list->list);
624EXPORT_SYMBOL(nftnl_flowtable_list_add_tail);
628 list_add_tail(&s->head, &list->list);
631EXPORT_SYMBOL(nftnl_flowtable_list_del);
637EXPORT_SYMBOL(nftnl_flowtable_list_foreach);
644 list_for_each_entry_safe(cur, tmp, &flowtable_list->list, head) {