19#include <netinet/in.h>
23#include <libmnl/libmnl.h>
24#include <linux/netfilter/nfnetlink.h>
25#include <linux/netfilter/nf_tables.h>
26#include <linux/netfilter.h>
27#include <linux/netfilter_arp.h>
29#include <libnftnl/chain.h>
30#include <libnftnl/rule.h>
33 struct list_head head;
34 struct hlist_node hnode;
40 const char **dev_array;
59 struct list_head rule_list;
62static const char *nftnl_hooknum2str(
int family,
int hooknum)
70 case NF_INET_PRE_ROUTING:
72 case NF_INET_LOCAL_IN:
76 case NF_INET_LOCAL_OUT:
78 case NF_INET_POST_ROUTING:
94 case NF_NETDEV_INGRESS:
102EXPORT_SYMBOL(nftnl_chain_alloc);
111 INIT_LIST_HEAD(&c->rule_list);
116EXPORT_SYMBOL(nftnl_chain_free);
119 struct nftnl_rule *r, *tmp;
122 list_for_each_entry_safe(r, tmp, &c->rule_list, head)
125 if (c->flags & (1 << NFTNL_CHAIN_NAME))
127 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
129 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
131 if (c->flags & (1 << NFTNL_CHAIN_DEV))
133 if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
135 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
136 for (i = 0; i < c->dev_array_len; i++)
137 xfree(c->dev_array[i]);
144EXPORT_SYMBOL(nftnl_chain_is_set);
145bool nftnl_chain_is_set(
const struct nftnl_chain *c, uint16_t attr)
147 return c->flags & (1 << attr);
150EXPORT_SYMBOL(nftnl_chain_unset);
151void nftnl_chain_unset(
struct nftnl_chain *c, uint16_t attr)
155 if (!(c->flags & (1 << attr)))
159 case NFTNL_CHAIN_NAME:
162 case NFTNL_CHAIN_TABLE:
165 case NFTNL_CHAIN_USE:
167 case NFTNL_CHAIN_TYPE:
170 case NFTNL_CHAIN_HOOKNUM:
171 case NFTNL_CHAIN_PRIO:
172 case NFTNL_CHAIN_POLICY:
173 case NFTNL_CHAIN_BYTES:
174 case NFTNL_CHAIN_PACKETS:
175 case NFTNL_CHAIN_HANDLE:
176 case NFTNL_CHAIN_FAMILY:
177 case NFTNL_CHAIN_FLAGS:
180 case NFTNL_CHAIN_DEV:
183 case NFTNL_CHAIN_DEVICES:
184 for (i = 0; i < c->dev_array_len; i++)
185 xfree(c->dev_array[i]);
188 case NFTNL_CHAIN_USERDATA:
195 c->flags &= ~(1 << attr);
198static uint32_t nftnl_chain_validate[NFTNL_CHAIN_MAX + 1] = {
199 [NFTNL_CHAIN_HOOKNUM] =
sizeof(uint32_t),
200 [NFTNL_CHAIN_PRIO] =
sizeof(int32_t),
201 [NFTNL_CHAIN_POLICY] =
sizeof(uint32_t),
202 [NFTNL_CHAIN_USE] =
sizeof(uint32_t),
203 [NFTNL_CHAIN_BYTES] =
sizeof(uint64_t),
204 [NFTNL_CHAIN_PACKETS] =
sizeof(uint64_t),
205 [NFTNL_CHAIN_HANDLE] =
sizeof(uint64_t),
206 [NFTNL_CHAIN_FAMILY] =
sizeof(uint32_t),
207 [NFTNL_CHAIN_FLAGS] =
sizeof(uint32_t),
208 [NFTNL_CHAIN_ID] =
sizeof(uint32_t),
211EXPORT_SYMBOL(nftnl_chain_set_data);
212int nftnl_chain_set_data(
struct nftnl_chain *c, uint16_t attr,
213 const void *data, uint32_t data_len)
215 const char **dev_array;
218 nftnl_assert_attr_exists(attr, NFTNL_CHAIN_MAX);
219 nftnl_assert_validate(data, nftnl_chain_validate, attr, data_len);
222 case NFTNL_CHAIN_NAME:
223 return nftnl_set_str_attr(&c->name, &c->flags,
224 attr, data, data_len);
225 case NFTNL_CHAIN_TABLE:
226 return nftnl_set_str_attr(&c->table, &c->flags,
227 attr, data, data_len);
228 case NFTNL_CHAIN_HOOKNUM:
229 memcpy(&c->hooknum, data,
sizeof(c->hooknum));
231 case NFTNL_CHAIN_PRIO:
232 memcpy(&c->prio, data,
sizeof(c->prio));
234 case NFTNL_CHAIN_POLICY:
235 memcpy(&c->policy, data,
sizeof(c->policy));
237 case NFTNL_CHAIN_USE:
238 memcpy(&c->use, data,
sizeof(c->use));
240 case NFTNL_CHAIN_BYTES:
241 memcpy(&c->bytes, data,
sizeof(c->bytes));
243 case NFTNL_CHAIN_PACKETS:
244 memcpy(&c->packets, data,
sizeof(c->packets));
246 case NFTNL_CHAIN_HANDLE:
247 memcpy(&c->handle, data,
sizeof(c->handle));
249 case NFTNL_CHAIN_FAMILY:
250 memcpy(&c->family, data,
sizeof(c->family));
252 case NFTNL_CHAIN_TYPE:
253 return nftnl_set_str_attr(&c->type, &c->flags,
254 attr, data, data_len);
255 case NFTNL_CHAIN_DEV:
256 return nftnl_set_str_attr(&c->dev, &c->flags,
257 attr, data, data_len);
258 case NFTNL_CHAIN_DEVICES:
259 dev_array = (
const char **)data;
260 while (dev_array[len] != NULL)
263 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
264 for (i = 0; i < c->dev_array_len; i++)
265 xfree(c->dev_array[i]);
269 c->dev_array = calloc(len + 1,
sizeof(
char *));
273 for (i = 0; i < len; i++)
274 c->dev_array[i] = strdup(dev_array[i]);
276 c->dev_array_len = len;
278 case NFTNL_CHAIN_FLAGS:
279 memcpy(&c->chain_flags, data,
sizeof(c->chain_flags));
282 memcpy(&c->chain_id, data,
sizeof(c->chain_id));
284 case NFTNL_CHAIN_USERDATA:
285 if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
288 c->user.data = malloc(data_len);
291 memcpy(c->user.data, data, data_len);
292 c->user.len = data_len;
295 c->flags |= (1 << attr);
299void nftnl_chain_set(
struct nftnl_chain *c, uint16_t attr,
const void *data) __visible;
300void nftnl_chain_set(
struct nftnl_chain *c, uint16_t attr,
const void *data)
302 nftnl_chain_set_data(c, attr, data, nftnl_chain_validate[attr]);
305EXPORT_SYMBOL(nftnl_chain_set_u32);
306void nftnl_chain_set_u32(
struct nftnl_chain *c, uint16_t attr, uint32_t data)
308 nftnl_chain_set_data(c, attr, &data,
sizeof(uint32_t));
311EXPORT_SYMBOL(nftnl_chain_set_s32);
312void nftnl_chain_set_s32(
struct nftnl_chain *c, uint16_t attr, int32_t data)
314 nftnl_chain_set_data(c, attr, &data,
sizeof(int32_t));
317EXPORT_SYMBOL(nftnl_chain_set_u64);
318void nftnl_chain_set_u64(
struct nftnl_chain *c, uint16_t attr, uint64_t data)
320 nftnl_chain_set_data(c, attr, &data,
sizeof(uint64_t));
323EXPORT_SYMBOL(nftnl_chain_set_u8);
324void nftnl_chain_set_u8(
struct nftnl_chain *c, uint16_t attr, uint8_t data)
326 nftnl_chain_set_data(c, attr, &data,
sizeof(uint8_t));
329EXPORT_SYMBOL(nftnl_chain_set_str);
330int nftnl_chain_set_str(
struct nftnl_chain *c, uint16_t attr,
const char *str)
332 return nftnl_chain_set_data(c, attr, str, strlen(str) + 1);
335EXPORT_SYMBOL(nftnl_chain_set_array);
336int nftnl_chain_set_array(
struct nftnl_chain *c, uint16_t attr,
339 return nftnl_chain_set_data(c, attr, data, 0);
342EXPORT_SYMBOL(nftnl_chain_get_data);
343const void *nftnl_chain_get_data(
const struct nftnl_chain *c, uint16_t attr,
346 if (!(c->flags & (1 << attr)))
350 case NFTNL_CHAIN_NAME:
351 *data_len = strlen(c->name) + 1;
353 case NFTNL_CHAIN_TABLE:
354 *data_len = strlen(c->table) + 1;
356 case NFTNL_CHAIN_HOOKNUM:
357 *data_len =
sizeof(uint32_t);
359 case NFTNL_CHAIN_PRIO:
360 *data_len =
sizeof(int32_t);
362 case NFTNL_CHAIN_POLICY:
363 *data_len =
sizeof(uint32_t);
365 case NFTNL_CHAIN_USE:
366 *data_len =
sizeof(uint32_t);
368 case NFTNL_CHAIN_BYTES:
369 *data_len =
sizeof(uint64_t);
371 case NFTNL_CHAIN_PACKETS:
372 *data_len =
sizeof(uint64_t);
374 case NFTNL_CHAIN_HANDLE:
375 *data_len =
sizeof(uint64_t);
377 case NFTNL_CHAIN_FAMILY:
378 *data_len =
sizeof(uint32_t);
380 case NFTNL_CHAIN_TYPE:
381 *data_len =
sizeof(uint32_t);
383 case NFTNL_CHAIN_DEV:
384 *data_len = strlen(c->dev) + 1;
386 case NFTNL_CHAIN_DEVICES:
388 return &c->dev_array[0];
389 case NFTNL_CHAIN_FLAGS:
390 *data_len =
sizeof(uint32_t);
391 return &c->chain_flags;
393 *data_len =
sizeof(uint32_t);
395 case NFTNL_CHAIN_USERDATA:
396 *data_len = c->user.len;
402EXPORT_SYMBOL(nftnl_chain_get);
403const void *nftnl_chain_get(
const struct nftnl_chain *c, uint16_t attr)
406 return nftnl_chain_get_data(c, attr, &data_len);
409EXPORT_SYMBOL(nftnl_chain_get_str);
410const char *nftnl_chain_get_str(
const struct nftnl_chain *c, uint16_t attr)
412 return nftnl_chain_get(c, attr);
415EXPORT_SYMBOL(nftnl_chain_get_u32);
416uint32_t nftnl_chain_get_u32(
const struct nftnl_chain *c, uint16_t attr)
419 const uint32_t *val = nftnl_chain_get_data(c, attr, &data_len);
421 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
423 return val ? *val : 0;
426EXPORT_SYMBOL(nftnl_chain_get_s32);
427int32_t nftnl_chain_get_s32(
const struct nftnl_chain *c, uint16_t attr)
430 const int32_t *val = nftnl_chain_get_data(c, attr, &data_len);
432 nftnl_assert(val, attr, data_len ==
sizeof(int32_t));
434 return val ? *val : 0;
437EXPORT_SYMBOL(nftnl_chain_get_u64);
438uint64_t nftnl_chain_get_u64(
const struct nftnl_chain *c, uint16_t attr)
441 const uint64_t *val = nftnl_chain_get_data(c, attr, &data_len);
443 nftnl_assert(val, attr, data_len ==
sizeof(int64_t));
445 return val ? *val : 0;
448EXPORT_SYMBOL(nftnl_chain_get_u8);
449uint8_t nftnl_chain_get_u8(
const struct nftnl_chain *c, uint16_t attr)
452 const uint8_t *val = nftnl_chain_get_data(c, attr, &data_len);
454 nftnl_assert(val, attr, data_len ==
sizeof(int8_t));
456 return val ? *val : 0;
459EXPORT_SYMBOL(nftnl_chain_get_array);
460const char *
const *nftnl_chain_get_array(
const struct nftnl_chain *c, uint16_t attr)
463 const char *
const *val = nftnl_chain_get_data(c, attr, &data_len);
465 nftnl_assert(val, attr, attr == NFTNL_CHAIN_DEVICES);
470EXPORT_SYMBOL(nftnl_chain_nlmsg_build_payload);
471void nftnl_chain_nlmsg_build_payload(
struct nlmsghdr *nlh,
const struct nftnl_chain *c)
473 struct nlattr *nest = NULL;
476 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
477 mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, c->table);
478 if (c->flags & (1 << NFTNL_CHAIN_NAME))
479 mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, c->name);
481 if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) ||
482 (c->flags & (1 << NFTNL_CHAIN_PRIO)) ||
483 (c->flags & (1 << NFTNL_CHAIN_DEV)) ||
484 (c->flags & (1 << NFTNL_CHAIN_DEVICES)))
485 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
487 if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)))
488 mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(c->hooknum));
489 if ((c->flags & (1 << NFTNL_CHAIN_PRIO)))
490 mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio));
492 if (c->flags & (1 << NFTNL_CHAIN_DEV))
493 mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev);
494 else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
495 struct nlattr *nest_dev;
497 nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS);
498 for (i = 0; i < c->dev_array_len; i++)
499 mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME,
501 mnl_attr_nest_end(nlh, nest_dev);
504 if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) ||
505 (c->flags & (1 << NFTNL_CHAIN_PRIO)) ||
506 (c->flags & (1 << NFTNL_CHAIN_DEV)) ||
507 (c->flags & (1 << NFTNL_CHAIN_DEVICES)))
508 mnl_attr_nest_end(nlh, nest);
510 if (c->flags & (1 << NFTNL_CHAIN_POLICY))
511 mnl_attr_put_u32(nlh, NFTA_CHAIN_POLICY, htonl(c->policy));
512 if (c->flags & (1 << NFTNL_CHAIN_USE))
513 mnl_attr_put_u32(nlh, NFTA_CHAIN_USE, htonl(c->use));
514 if ((c->flags & (1 << NFTNL_CHAIN_PACKETS)) &&
515 (c->flags & (1 << NFTNL_CHAIN_BYTES))) {
516 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_COUNTERS);
517 mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, be64toh(c->packets));
518 mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, be64toh(c->bytes));
519 mnl_attr_nest_end(nlh, nest);
521 if (c->flags & (1 << NFTNL_CHAIN_HANDLE))
522 mnl_attr_put_u64(nlh, NFTA_CHAIN_HANDLE, be64toh(c->handle));
523 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
524 mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, c->type);
525 if (c->flags & (1 << NFTNL_CHAIN_FLAGS))
526 mnl_attr_put_u32(nlh, NFTA_CHAIN_FLAGS, htonl(c->chain_flags));
527 if (c->flags & (1 << NFTNL_CHAIN_ID))
528 mnl_attr_put_u32(nlh, NFTA_CHAIN_ID, htonl(c->chain_id));
529 if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
530 mnl_attr_put(nlh, NFTA_CHAIN_USERDATA, c->user.len, c->user.data);
533EXPORT_SYMBOL(nftnl_chain_rule_add);
534void nftnl_chain_rule_add(
struct nftnl_rule *rule,
struct nftnl_chain *c)
536 list_add(&rule->head, &c->rule_list);
539EXPORT_SYMBOL(nftnl_chain_rule_del);
540void nftnl_chain_rule_del(
struct nftnl_rule *r)
545EXPORT_SYMBOL(nftnl_chain_rule_add_tail);
546void nftnl_chain_rule_add_tail(
struct nftnl_rule *rule,
struct nftnl_chain *c)
548 list_add_tail(&rule->head, &c->rule_list);
551EXPORT_SYMBOL(nftnl_chain_rule_insert_at);
552void nftnl_chain_rule_insert_at(
struct nftnl_rule *rule,
struct nftnl_rule *pos)
554 list_add_tail(&rule->head, &pos->head);
557EXPORT_SYMBOL(nftnl_chain_rule_append_at);
558void nftnl_chain_rule_append_at(
struct nftnl_rule *rule,
struct nftnl_rule *pos)
560 list_add(&rule->head, &pos->head);
563static int nftnl_chain_parse_attr_cb(
const struct nlattr *attr,
void *data)
565 const struct nlattr **tb = data;
566 int type = mnl_attr_get_type(attr);
568 if (mnl_attr_type_valid(attr, NFTA_CHAIN_MAX) < 0)
572 case NFTA_CHAIN_NAME:
573 case NFTA_CHAIN_TABLE:
574 case NFTA_CHAIN_TYPE:
575 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
578 case NFTA_CHAIN_HOOK:
579 case NFTA_CHAIN_COUNTERS:
580 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
583 case NFTA_CHAIN_POLICY:
585 case NFTA_CHAIN_FLAGS:
587 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
590 case NFTA_CHAIN_HANDLE:
591 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
594 case NFTA_CHAIN_USERDATA:
595 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
604static int nftnl_chain_parse_counters_cb(
const struct nlattr *attr,
void *data)
606 const struct nlattr **tb = data;
607 int type = mnl_attr_get_type(attr);
609 if (mnl_attr_type_valid(attr, NFTA_COUNTER_MAX) < 0)
613 case NFTA_COUNTER_BYTES:
614 case NFTA_COUNTER_PACKETS:
615 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
624static int nftnl_chain_parse_counters(
struct nlattr *attr,
struct nftnl_chain *c)
626 struct nlattr *tb[NFTA_COUNTER_MAX+1] = {};
628 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_counters_cb, tb) < 0)
631 if (tb[NFTA_COUNTER_PACKETS]) {
632 c->packets = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_PACKETS]));
633 c->flags |= (1 << NFTNL_CHAIN_PACKETS);
635 if (tb[NFTA_COUNTER_BYTES]) {
636 c->bytes = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_BYTES]));
637 c->flags |= (1 << NFTNL_CHAIN_BYTES);
643static int nftnl_chain_parse_hook_cb(
const struct nlattr *attr,
void *data)
645 const struct nlattr **tb = data;
646 int type = mnl_attr_get_type(attr);
648 if (mnl_attr_type_valid(attr, NFTA_HOOK_MAX) < 0)
652 case NFTA_HOOK_HOOKNUM:
653 case NFTA_HOOK_PRIORITY:
654 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
658 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
667static int nftnl_chain_parse_devs(
struct nlattr *nest,
struct nftnl_chain *c)
669 const char **dev_array, **tmp;
670 int len = 0, size = 8;
673 dev_array = calloc(8,
sizeof(
char *));
677 mnl_attr_for_each_nested(attr, nest) {
678 if (mnl_attr_get_type(attr) != NFTA_DEVICE_NAME)
680 dev_array[len++] = strdup(mnl_attr_get_str(attr));
682 tmp = realloc(dev_array, size * 2 *
sizeof(
char *));
687 memset(&tmp[len], 0, (size - len) *
sizeof(
char *));
692 c->dev_array = dev_array;
693 c->dev_array_len = len;
698 xfree(dev_array[len]);
703static int nftnl_chain_parse_hook(
struct nlattr *attr,
struct nftnl_chain *c)
705 struct nlattr *tb[NFTA_HOOK_MAX+1] = {};
708 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_hook_cb, tb) < 0)
711 if (tb[NFTA_HOOK_HOOKNUM]) {
712 c->hooknum = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_HOOKNUM]));
713 c->flags |= (1 << NFTNL_CHAIN_HOOKNUM);
715 if (tb[NFTA_HOOK_PRIORITY]) {
716 c->prio = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_PRIORITY]));
717 c->flags |= (1 << NFTNL_CHAIN_PRIO);
719 if (tb[NFTA_HOOK_DEV]) {
720 c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV]));
723 c->flags |= (1 << NFTNL_CHAIN_DEV);
725 if (tb[NFTA_HOOK_DEVS]) {
726 ret = nftnl_chain_parse_devs(tb[NFTA_HOOK_DEVS], c);
729 c->flags |= (1 << NFTNL_CHAIN_DEVICES);
735EXPORT_SYMBOL(nftnl_chain_nlmsg_parse);
736int nftnl_chain_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_chain *c)
738 struct nlattr *tb[NFTA_CHAIN_MAX+1] = {};
739 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
742 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_chain_parse_attr_cb, tb) < 0)
745 if (tb[NFTA_CHAIN_NAME]) {
746 if (c->flags & (1 << NFTNL_CHAIN_NAME))
748 c->name = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_NAME]));
751 c->flags |= (1 << NFTNL_CHAIN_NAME);
753 if (tb[NFTA_CHAIN_TABLE]) {
754 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
756 c->table = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TABLE]));
759 c->flags |= (1 << NFTNL_CHAIN_TABLE);
761 if (tb[NFTA_CHAIN_HOOK]) {
762 ret = nftnl_chain_parse_hook(tb[NFTA_CHAIN_HOOK], c);
766 if (tb[NFTA_CHAIN_POLICY]) {
767 c->policy = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_POLICY]));
768 c->flags |= (1 << NFTNL_CHAIN_POLICY);
770 if (tb[NFTA_CHAIN_USE]) {
771 c->use = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_USE]));
772 c->flags |= (1 << NFTNL_CHAIN_USE);
774 if (tb[NFTA_CHAIN_COUNTERS]) {
775 ret = nftnl_chain_parse_counters(tb[NFTA_CHAIN_COUNTERS], c);
779 if (tb[NFTA_CHAIN_HANDLE]) {
780 c->handle = be64toh(mnl_attr_get_u64(tb[NFTA_CHAIN_HANDLE]));
781 c->flags |= (1 << NFTNL_CHAIN_HANDLE);
783 if (tb[NFTA_CHAIN_TYPE]) {
784 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
786 c->type = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TYPE]));
789 c->flags |= (1 << NFTNL_CHAIN_TYPE);
791 if (tb[NFTA_CHAIN_FLAGS]) {
792 c->chain_flags = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_FLAGS]));
793 c->flags |= (1 << NFTNL_CHAIN_FLAGS);
795 if (tb[NFTA_CHAIN_ID]) {
796 c->chain_id = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_ID]));
797 c->flags |= (1 << NFTNL_CHAIN_ID);
799 if (tb[NFTA_CHAIN_USERDATA]) {
800 nftnl_chain_set_data(c, NFTNL_CHAIN_USERDATA,
801 mnl_attr_get_payload(tb[NFTA_CHAIN_USERDATA]),
802 mnl_attr_get_payload_len(tb[NFTA_CHAIN_USERDATA]));
805 c->family = nfg->nfgen_family;
806 c->flags |= (1 << NFTNL_CHAIN_FAMILY);
811static inline int nftnl_str2hooknum(
int family,
const char *hook)
815 for (hooknum = 0; hooknum < NF_INET_NUMHOOKS; hooknum++) {
816 if (strcmp(hook, nftnl_hooknum2str(family, hooknum)) == 0)
822static int nftnl_chain_snprintf_default(
char *buf,
size_t remain,
825 int ret, offset = 0, i;
827 ret = snprintf(buf, remain,
"%s %s %s use %u",
828 nftnl_family2str(c->family), c->table, c->name, c->use);
829 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
831 if (c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) {
832 ret = snprintf(buf + offset, remain,
" type %s hook %s prio %d",
833 c->type, nftnl_hooknum2str(c->family, c->hooknum),
835 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
837 if (c->flags & (1 << NFTNL_CHAIN_POLICY)) {
838 ret = snprintf(buf + offset, remain,
" policy %s",
839 nftnl_verdict2str(c->policy));
840 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
843 ret = snprintf(buf + offset, remain,
844 " packets %"PRIu64
" bytes %"PRIu64
"",
845 c->packets, c->bytes);
846 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
848 if (c->flags & (1 << NFTNL_CHAIN_DEV)) {
849 ret = snprintf(buf + offset, remain,
" dev %s ",
851 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
853 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
854 ret = snprintf(buf + offset, remain,
" dev { ");
855 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
857 for (i = 0; i < c->dev_array_len; i++) {
858 ret = snprintf(buf + offset, remain,
" %s ",
860 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
862 ret = snprintf(buf + offset, remain,
" } ");
863 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
865 if (c->flags & (1 << NFTNL_CHAIN_FLAGS)) {
866 ret = snprintf(buf + offset, remain,
" flags %x",
868 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
870 if (c->flags & (1 << NFTNL_CHAIN_ID)) {
871 ret = snprintf(buf + offset, remain,
" id %x",
873 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
880static int nftnl_chain_cmd_snprintf(
char *buf,
size_t remain,
882 uint32_t type, uint32_t flags)
886 if (type != NFTNL_OUTPUT_DEFAULT)
889 ret = nftnl_chain_snprintf_default(buf + offset, remain, c);
890 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
894EXPORT_SYMBOL(nftnl_chain_snprintf);
895int nftnl_chain_snprintf(
char *buf,
size_t size,
const struct nftnl_chain *c,
896 uint32_t type, uint32_t flags)
901 return nftnl_chain_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
905static int nftnl_chain_do_snprintf(
char *buf,
size_t size,
const void *c,
906 uint32_t cmd, uint32_t type, uint32_t flags)
908 return nftnl_chain_snprintf(buf, size, c, type, flags);
911EXPORT_SYMBOL(nftnl_chain_fprintf);
912int nftnl_chain_fprintf(FILE *fp,
const struct nftnl_chain *c, uint32_t type,
915 return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
916 nftnl_chain_do_snprintf);
919EXPORT_SYMBOL(nftnl_rule_foreach);
921 int (*cb)(
struct nftnl_rule *r,
void *data),
924 struct nftnl_rule *cur, *tmp;
927 list_for_each_entry_safe(cur, tmp, &c->rule_list, head) {
935EXPORT_SYMBOL(nftnl_rule_lookup_byindex);
937nftnl_rule_lookup_byindex(
struct nftnl_chain *c, uint32_t index)
939 struct nftnl_rule *r;
941 list_for_each_entry(r, &c->rule_list, head) {
951 struct nftnl_rule *cur;
954static void nftnl_rule_iter_init(
const struct nftnl_chain *c,
958 if (list_empty(&c->rule_list))
961 iter->cur = list_entry(c->rule_list.next,
struct nftnl_rule,
965EXPORT_SYMBOL(nftnl_rule_iter_create);
974 nftnl_rule_iter_init(c, iter);
979EXPORT_SYMBOL(nftnl_rule_iter_next);
982 struct nftnl_rule *rule = iter->cur;
988 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_rule, head);
989 if (&iter->cur->head == iter->c->rule_list.next)
995EXPORT_SYMBOL(nftnl_rule_iter_destroy);
1001#define CHAIN_NAME_HSIZE 512
1005 struct list_head list;
1006 struct hlist_head name_hash[CHAIN_NAME_HSIZE];
1009EXPORT_SYMBOL(nftnl_chain_list_alloc);
1019 INIT_LIST_HEAD(&list->list);
1020 for (i = 0; i < CHAIN_NAME_HSIZE; i++)
1021 INIT_HLIST_HEAD(&list->name_hash[i]);
1026EXPORT_SYMBOL(nftnl_chain_list_free);
1031 list_for_each_entry_safe(r, tmp, &list->list, head) {
1033 hlist_del(&r->hnode);
1034 nftnl_chain_free(r);
1039EXPORT_SYMBOL(nftnl_chain_list_is_empty);
1042 return list_empty(&list->list);
1045static uint32_t djb_hash(
const char *key)
1047 uint32_t i, hash = 5381;
1049 for (i = 0; i < strlen(key); i++)
1050 hash = ((hash << 5) + hash) + key[i];
1055EXPORT_SYMBOL(nftnl_chain_list_add);
1058 int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
1060 hlist_add_head(&r->hnode, &list->name_hash[key]);
1061 list_add(&r->head, &list->list);
1064EXPORT_SYMBOL(nftnl_chain_list_add_tail);
1067 int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
1069 hlist_add_head(&r->hnode, &list->name_hash[key]);
1070 list_add_tail(&r->head, &list->list);
1073EXPORT_SYMBOL(nftnl_chain_list_del);
1077 hlist_del(&r->hnode);
1080EXPORT_SYMBOL(nftnl_chain_list_foreach);
1088 list_for_each_entry_safe(cur, tmp, &chain_list->list, head) {
1089 ret = cb(cur, data);
1096EXPORT_SYMBOL(nftnl_chain_list_lookup_byname);
1101 int key = djb_hash(chain) % CHAIN_NAME_HSIZE;
1103 struct hlist_node *n;
1105 hlist_for_each_entry(c, n, &chain_list->name_hash[key], hnode) {
1106 if (!strcmp(chain, c->name))
1117EXPORT_SYMBOL(nftnl_chain_list_iter_create);
1128 if (nftnl_chain_list_is_empty(l))
1131 iter->cur = list_entry(l->list.next,
struct nftnl_chain, head);
1136EXPORT_SYMBOL(nftnl_chain_list_iter_next);
1145 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_chain, head);
1146 if (&iter->cur->head == iter->list->list.next)
1152EXPORT_SYMBOL(nftnl_chain_list_iter_destroy);