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>
34 struct list_head head;
35 struct hlist_node hnode;
41 const char **dev_array;
53 struct list_head rule_list;
56 static const char *nftnl_hooknum2str(
int family,
int hooknum)
64 case NF_INET_PRE_ROUTING:
66 case NF_INET_LOCAL_IN:
70 case NF_INET_LOCAL_OUT:
72 case NF_INET_POST_ROUTING:
88 case NF_NETDEV_INGRESS:
96 EXPORT_SYMBOL(nftnl_chain_alloc);
105 INIT_LIST_HEAD(&c->rule_list);
110 EXPORT_SYMBOL(nftnl_chain_free);
113 struct nftnl_rule *r, *tmp;
116 list_for_each_entry_safe(r, tmp, &c->rule_list, head)
119 if (c->flags & (1 << NFTNL_CHAIN_NAME))
121 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
123 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
125 if (c->flags & (1 << NFTNL_CHAIN_DEV))
127 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
128 for (i = 0; i < c->dev_array_len; i++)
129 xfree(c->dev_array[i]);
136 EXPORT_SYMBOL(nftnl_chain_is_set);
137 bool nftnl_chain_is_set(
const struct nftnl_chain *c, uint16_t attr)
139 return c->flags & (1 << attr);
142 EXPORT_SYMBOL(nftnl_chain_unset);
143 void nftnl_chain_unset(
struct nftnl_chain *c, uint16_t attr)
147 if (!(c->flags & (1 << attr)))
151 case NFTNL_CHAIN_NAME:
154 case NFTNL_CHAIN_TABLE:
157 case NFTNL_CHAIN_USE:
159 case NFTNL_CHAIN_TYPE:
162 case NFTNL_CHAIN_HOOKNUM:
163 case NFTNL_CHAIN_PRIO:
164 case NFTNL_CHAIN_POLICY:
165 case NFTNL_CHAIN_BYTES:
166 case NFTNL_CHAIN_PACKETS:
167 case NFTNL_CHAIN_HANDLE:
168 case NFTNL_CHAIN_FAMILY:
170 case NFTNL_CHAIN_DEV:
173 case NFTNL_CHAIN_DEVICES:
174 for (i = 0; i < c->dev_array_len; i++)
175 xfree(c->dev_array[i]);
182 c->flags &= ~(1 << attr);
185 static uint32_t nftnl_chain_validate[NFTNL_CHAIN_MAX + 1] = {
186 [NFTNL_CHAIN_HOOKNUM] =
sizeof(uint32_t),
187 [NFTNL_CHAIN_PRIO] =
sizeof(int32_t),
188 [NFTNL_CHAIN_POLICY] =
sizeof(uint32_t),
189 [NFTNL_CHAIN_BYTES] =
sizeof(uint64_t),
190 [NFTNL_CHAIN_PACKETS] =
sizeof(uint64_t),
191 [NFTNL_CHAIN_HANDLE] =
sizeof(uint64_t),
192 [NFTNL_CHAIN_FAMILY] =
sizeof(uint32_t),
195 EXPORT_SYMBOL(nftnl_chain_set_data);
196 int nftnl_chain_set_data(
struct nftnl_chain *c, uint16_t attr,
197 const void *data, uint32_t data_len)
199 const char **dev_array;
202 nftnl_assert_attr_exists(attr, NFTNL_CHAIN_MAX);
203 nftnl_assert_validate(data, nftnl_chain_validate, attr, data_len);
206 case NFTNL_CHAIN_NAME:
207 if (c->flags & (1 << NFTNL_CHAIN_NAME))
210 c->name = strdup(data);
214 case NFTNL_CHAIN_TABLE:
215 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
218 c->table = strdup(data);
222 case NFTNL_CHAIN_HOOKNUM:
223 memcpy(&c->hooknum, data,
sizeof(c->hooknum));
225 case NFTNL_CHAIN_PRIO:
226 memcpy(&c->prio, data,
sizeof(c->prio));
228 case NFTNL_CHAIN_POLICY:
229 memcpy(&c->policy, data,
sizeof(c->policy));
231 case NFTNL_CHAIN_USE:
232 memcpy(&c->use, data,
sizeof(c->use));
234 case NFTNL_CHAIN_BYTES:
235 memcpy(&c->bytes, data,
sizeof(c->bytes));
237 case NFTNL_CHAIN_PACKETS:
238 memcpy(&c->packets, data,
sizeof(c->packets));
240 case NFTNL_CHAIN_HANDLE:
241 memcpy(&c->handle, data,
sizeof(c->handle));
243 case NFTNL_CHAIN_FAMILY:
244 memcpy(&c->family, data,
sizeof(c->family));
246 case NFTNL_CHAIN_TYPE:
247 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
250 c->type = strdup(data);
254 case NFTNL_CHAIN_DEV:
255 if (c->flags & (1 << NFTNL_CHAIN_DEV))
258 c->dev = strdup(data);
262 case NFTNL_CHAIN_DEVICES:
263 dev_array = (
const char **)data;
264 while (dev_array[len] != NULL)
267 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
268 for (i = 0; i < c->dev_array_len; i++)
269 xfree(c->dev_array[i]);
273 c->dev_array = calloc(len + 1,
sizeof(
char *));
277 for (i = 0; i < len; i++)
278 c->dev_array[i] = strdup(dev_array[i]);
280 c->dev_array_len = len;
283 c->flags |= (1 << attr);
287 void nftnl_chain_set(
struct nftnl_chain *c, uint16_t attr,
const void *data) __visible;
288 void nftnl_chain_set(
struct nftnl_chain *c, uint16_t attr,
const void *data)
290 nftnl_chain_set_data(c, attr, data, nftnl_chain_validate[attr]);
293 EXPORT_SYMBOL(nftnl_chain_set_u32);
294 void nftnl_chain_set_u32(
struct nftnl_chain *c, uint16_t attr, uint32_t data)
296 nftnl_chain_set_data(c, attr, &data,
sizeof(uint32_t));
299 EXPORT_SYMBOL(nftnl_chain_set_s32);
300 void nftnl_chain_set_s32(
struct nftnl_chain *c, uint16_t attr, int32_t data)
302 nftnl_chain_set_data(c, attr, &data,
sizeof(int32_t));
305 EXPORT_SYMBOL(nftnl_chain_set_u64);
306 void nftnl_chain_set_u64(
struct nftnl_chain *c, uint16_t attr, uint64_t data)
308 nftnl_chain_set_data(c, attr, &data,
sizeof(uint64_t));
311 EXPORT_SYMBOL(nftnl_chain_set_u8);
312 void nftnl_chain_set_u8(
struct nftnl_chain *c, uint16_t attr, uint8_t data)
314 nftnl_chain_set_data(c, attr, &data,
sizeof(uint8_t));
317 EXPORT_SYMBOL(nftnl_chain_set_str);
318 int nftnl_chain_set_str(
struct nftnl_chain *c, uint16_t attr,
const char *str)
320 return nftnl_chain_set_data(c, attr, str, strlen(str) + 1);
323 EXPORT_SYMBOL(nftnl_chain_get_data);
324 const void *nftnl_chain_get_data(
const struct nftnl_chain *c, uint16_t attr,
327 if (!(c->flags & (1 << attr)))
331 case NFTNL_CHAIN_NAME:
332 *data_len = strlen(c->name) + 1;
334 case NFTNL_CHAIN_TABLE:
335 *data_len = strlen(c->table) + 1;
337 case NFTNL_CHAIN_HOOKNUM:
338 *data_len =
sizeof(uint32_t);
340 case NFTNL_CHAIN_PRIO:
341 *data_len =
sizeof(int32_t);
343 case NFTNL_CHAIN_POLICY:
344 *data_len =
sizeof(uint32_t);
346 case NFTNL_CHAIN_USE:
347 *data_len =
sizeof(uint32_t);
349 case NFTNL_CHAIN_BYTES:
350 *data_len =
sizeof(uint64_t);
352 case NFTNL_CHAIN_PACKETS:
353 *data_len =
sizeof(uint64_t);
355 case NFTNL_CHAIN_HANDLE:
356 *data_len =
sizeof(uint64_t);
358 case NFTNL_CHAIN_FAMILY:
359 *data_len =
sizeof(uint32_t);
361 case NFTNL_CHAIN_TYPE:
362 *data_len =
sizeof(uint32_t);
364 case NFTNL_CHAIN_DEV:
365 *data_len = strlen(c->dev) + 1;
367 case NFTNL_CHAIN_DEVICES:
368 return &c->dev_array[0];
373 EXPORT_SYMBOL(nftnl_chain_get);
374 const void *nftnl_chain_get(
const struct nftnl_chain *c, uint16_t attr)
377 return nftnl_chain_get_data(c, attr, &data_len);
380 EXPORT_SYMBOL(nftnl_chain_get_str);
381 const char *nftnl_chain_get_str(
const struct nftnl_chain *c, uint16_t attr)
383 return nftnl_chain_get(c, attr);
386 EXPORT_SYMBOL(nftnl_chain_get_u32);
387 uint32_t nftnl_chain_get_u32(
const struct nftnl_chain *c, uint16_t attr)
390 const uint32_t *val = nftnl_chain_get_data(c, attr, &data_len);
392 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
394 return val ? *val : 0;
397 EXPORT_SYMBOL(nftnl_chain_get_s32);
398 int32_t nftnl_chain_get_s32(
const struct nftnl_chain *c, uint16_t attr)
401 const int32_t *val = nftnl_chain_get_data(c, attr, &data_len);
403 nftnl_assert(val, attr, data_len ==
sizeof(int32_t));
405 return val ? *val : 0;
408 EXPORT_SYMBOL(nftnl_chain_get_u64);
409 uint64_t nftnl_chain_get_u64(
const struct nftnl_chain *c, uint16_t attr)
412 const uint64_t *val = nftnl_chain_get_data(c, attr, &data_len);
414 nftnl_assert(val, attr, data_len ==
sizeof(int64_t));
416 return val ? *val : 0;
419 EXPORT_SYMBOL(nftnl_chain_get_u8);
420 uint8_t nftnl_chain_get_u8(
const struct nftnl_chain *c, uint16_t attr)
423 const uint8_t *val = nftnl_chain_get_data(c, attr, &data_len);
425 nftnl_assert(val, attr, data_len ==
sizeof(int8_t));
427 return val ? *val : 0;
430 EXPORT_SYMBOL(nftnl_chain_nlmsg_build_payload);
431 void nftnl_chain_nlmsg_build_payload(
struct nlmsghdr *nlh,
const struct nftnl_chain *c)
435 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
436 mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, c->table);
437 if (c->flags & (1 << NFTNL_CHAIN_NAME))
438 mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, c->name);
439 if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) &&
440 (c->flags & (1 << NFTNL_CHAIN_PRIO))) {
443 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
444 mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(c->hooknum));
445 mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio));
446 if (c->flags & (1 << NFTNL_CHAIN_DEV))
447 mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev);
448 else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
449 struct nlattr *nest_dev;
451 nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS);
452 for (i = 0; i < c->dev_array_len; i++)
453 mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME,
455 mnl_attr_nest_end(nlh, nest_dev);
457 mnl_attr_nest_end(nlh, nest);
459 if (c->flags & (1 << NFTNL_CHAIN_POLICY))
460 mnl_attr_put_u32(nlh, NFTA_CHAIN_POLICY, htonl(c->policy));
461 if (c->flags & (1 << NFTNL_CHAIN_USE))
462 mnl_attr_put_u32(nlh, NFTA_CHAIN_USE, htonl(c->use));
463 if ((c->flags & (1 << NFTNL_CHAIN_PACKETS)) &&
464 (c->flags & (1 << NFTNL_CHAIN_BYTES))) {
467 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_COUNTERS);
468 mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, be64toh(c->packets));
469 mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, be64toh(c->bytes));
470 mnl_attr_nest_end(nlh, nest);
472 if (c->flags & (1 << NFTNL_CHAIN_HANDLE))
473 mnl_attr_put_u64(nlh, NFTA_CHAIN_HANDLE, be64toh(c->handle));
474 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
475 mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, c->type);
478 EXPORT_SYMBOL(nftnl_chain_rule_add);
479 void nftnl_chain_rule_add(
struct nftnl_rule *rule,
struct nftnl_chain *c)
481 list_add(&rule->head, &c->rule_list);
484 EXPORT_SYMBOL(nftnl_chain_rule_del);
485 void nftnl_chain_rule_del(
struct nftnl_rule *r)
490 EXPORT_SYMBOL(nftnl_chain_rule_add_tail);
491 void nftnl_chain_rule_add_tail(
struct nftnl_rule *rule,
struct nftnl_chain *c)
493 list_add_tail(&rule->head, &c->rule_list);
496 EXPORT_SYMBOL(nftnl_chain_rule_insert_at);
497 void nftnl_chain_rule_insert_at(
struct nftnl_rule *rule,
struct nftnl_rule *pos)
499 list_add_tail(&rule->head, &pos->head);
502 EXPORT_SYMBOL(nftnl_chain_rule_append_at);
503 void nftnl_chain_rule_append_at(
struct nftnl_rule *rule,
struct nftnl_rule *pos)
505 list_add(&rule->head, &pos->head);
508 static int nftnl_chain_parse_attr_cb(
const struct nlattr *attr,
void *data)
510 const struct nlattr **tb = data;
511 int type = mnl_attr_get_type(attr);
513 if (mnl_attr_type_valid(attr, NFTA_CHAIN_MAX) < 0)
517 case NFTA_CHAIN_NAME:
518 case NFTA_CHAIN_TABLE:
519 case NFTA_CHAIN_TYPE:
520 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
523 case NFTA_CHAIN_HOOK:
524 case NFTA_CHAIN_COUNTERS:
525 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
528 case NFTA_CHAIN_POLICY:
530 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
533 case NFTA_CHAIN_HANDLE:
534 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
543 static int nftnl_chain_parse_counters_cb(
const struct nlattr *attr,
void *data)
545 const struct nlattr **tb = data;
546 int type = mnl_attr_get_type(attr);
548 if (mnl_attr_type_valid(attr, NFTA_COUNTER_MAX) < 0)
552 case NFTA_COUNTER_BYTES:
553 case NFTA_COUNTER_PACKETS:
554 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
563 static int nftnl_chain_parse_counters(
struct nlattr *attr,
struct nftnl_chain *c)
565 struct nlattr *tb[NFTA_COUNTER_MAX+1] = {};
567 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_counters_cb, tb) < 0)
570 if (tb[NFTA_COUNTER_PACKETS]) {
571 c->packets = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_PACKETS]));
572 c->flags |= (1 << NFTNL_CHAIN_PACKETS);
574 if (tb[NFTA_COUNTER_BYTES]) {
575 c->bytes = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_BYTES]));
576 c->flags |= (1 << NFTNL_CHAIN_BYTES);
582 static int nftnl_chain_parse_hook_cb(
const struct nlattr *attr,
void *data)
584 const struct nlattr **tb = data;
585 int type = mnl_attr_get_type(attr);
587 if (mnl_attr_type_valid(attr, NFTA_HOOK_MAX) < 0)
591 case NFTA_HOOK_HOOKNUM:
592 case NFTA_HOOK_PRIORITY:
593 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
597 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
606 static int nftnl_chain_parse_devs(
struct nlattr *nest,
struct nftnl_chain *c)
608 const char **dev_array;
609 int len = 0, size = 8;
612 dev_array = calloc(8,
sizeof(
char *));
616 mnl_attr_for_each_nested(attr, nest) {
617 if (mnl_attr_get_type(attr) != NFTA_DEVICE_NAME)
619 dev_array[len++] = strdup(mnl_attr_get_str(attr));
621 dev_array = realloc(dev_array,
622 size * 2 *
sizeof(
char *));
627 memset(&dev_array[len], 0,
628 (size - len) *
sizeof(
char *));
632 c->dev_array = dev_array;
633 c->dev_array_len = len;
638 xfree(dev_array[len]);
642 static int nftnl_chain_parse_hook(
struct nlattr *attr,
struct nftnl_chain *c)
644 struct nlattr *tb[NFTA_HOOK_MAX+1] = {};
647 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_hook_cb, tb) < 0)
650 if (tb[NFTA_HOOK_HOOKNUM]) {
651 c->hooknum = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_HOOKNUM]));
652 c->flags |= (1 << NFTNL_CHAIN_HOOKNUM);
654 if (tb[NFTA_HOOK_PRIORITY]) {
655 c->prio = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_PRIORITY]));
656 c->flags |= (1 << NFTNL_CHAIN_PRIO);
658 if (tb[NFTA_HOOK_DEV]) {
659 c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV]));
662 c->flags |= (1 << NFTNL_CHAIN_DEV);
664 if (tb[NFTA_HOOK_DEVS]) {
665 ret = nftnl_chain_parse_devs(tb[NFTA_HOOK_DEVS], c);
668 c->flags |= (1 << NFTNL_CHAIN_DEVICES);
674 EXPORT_SYMBOL(nftnl_chain_nlmsg_parse);
675 int nftnl_chain_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_chain *c)
677 struct nlattr *tb[NFTA_CHAIN_MAX+1] = {};
678 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
681 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_chain_parse_attr_cb, tb) < 0)
684 if (tb[NFTA_CHAIN_NAME]) {
685 if (c->flags & (1 << NFTNL_CHAIN_NAME))
687 c->name = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_NAME]));
690 c->flags |= (1 << NFTNL_CHAIN_NAME);
692 if (tb[NFTA_CHAIN_TABLE]) {
693 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
695 c->table = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TABLE]));
698 c->flags |= (1 << NFTNL_CHAIN_TABLE);
700 if (tb[NFTA_CHAIN_HOOK]) {
701 ret = nftnl_chain_parse_hook(tb[NFTA_CHAIN_HOOK], c);
705 if (tb[NFTA_CHAIN_POLICY]) {
706 c->policy = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_POLICY]));
707 c->flags |= (1 << NFTNL_CHAIN_POLICY);
709 if (tb[NFTA_CHAIN_USE]) {
710 c->use = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_USE]));
711 c->flags |= (1 << NFTNL_CHAIN_USE);
713 if (tb[NFTA_CHAIN_COUNTERS]) {
714 ret = nftnl_chain_parse_counters(tb[NFTA_CHAIN_COUNTERS], c);
718 if (tb[NFTA_CHAIN_HANDLE]) {
719 c->handle = be64toh(mnl_attr_get_u64(tb[NFTA_CHAIN_HANDLE]));
720 c->flags |= (1 << NFTNL_CHAIN_HANDLE);
722 if (tb[NFTA_CHAIN_TYPE]) {
723 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
725 c->type = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TYPE]));
728 c->flags |= (1 << NFTNL_CHAIN_TYPE);
731 c->family = nfg->nfgen_family;
732 c->flags |= (1 << NFTNL_CHAIN_FAMILY);
737 static inline int nftnl_str2hooknum(
int family,
const char *hook)
741 for (hooknum = 0; hooknum < NF_INET_NUMHOOKS; hooknum++) {
742 if (strcmp(hook, nftnl_hooknum2str(family, hooknum)) == 0)
748 static int nftnl_chain_snprintf_default(
char *buf,
size_t size,
751 int ret, remain = size, offset = 0, i;
753 ret = snprintf(buf, remain,
"%s %s %s use %u",
754 nftnl_family2str(c->family), c->table, c->name, c->use);
755 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
757 if (c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) {
758 ret = snprintf(buf + offset, remain,
" type %s hook %s prio %d",
759 c->type, nftnl_hooknum2str(c->family, c->hooknum),
761 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
763 if (c->flags & (1 << NFTNL_CHAIN_POLICY)) {
764 ret = snprintf(buf + offset, remain,
" policy %s",
765 nftnl_verdict2str(c->policy));
766 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
769 ret = snprintf(buf + offset, remain,
770 " packets %"PRIu64
" bytes %"PRIu64
"",
771 c->packets, c->bytes);
772 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
774 if (c->flags & (1 << NFTNL_CHAIN_DEV)) {
775 ret = snprintf(buf + offset, remain,
" dev %s ",
777 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
779 if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
780 ret = snprintf(buf + offset, remain,
" dev { ");
781 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
783 for (i = 0; i < c->dev_array_len; i++) {
784 ret = snprintf(buf + offset, remain,
" %s ",
786 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
788 ret = snprintf(buf + offset, remain,
" } ");
789 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
796 static int nftnl_chain_cmd_snprintf(
char *buf,
size_t size,
798 uint32_t type, uint32_t flags)
800 int ret, remain = size, offset = 0;
803 case NFTNL_OUTPUT_DEFAULT:
804 ret = nftnl_chain_snprintf_default(buf + offset, remain, c);
805 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
807 case NFTNL_OUTPUT_XML:
808 case NFTNL_OUTPUT_JSON:
816 EXPORT_SYMBOL(nftnl_chain_snprintf);
817 int nftnl_chain_snprintf(
char *buf,
size_t size,
const struct nftnl_chain *c,
818 uint32_t type, uint32_t flags)
823 return nftnl_chain_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
827 static int nftnl_chain_do_snprintf(
char *buf,
size_t size,
const void *c,
828 uint32_t cmd, uint32_t type, uint32_t flags)
830 return nftnl_chain_snprintf(buf, size, c, type, flags);
833 EXPORT_SYMBOL(nftnl_chain_fprintf);
834 int nftnl_chain_fprintf(FILE *fp,
const struct nftnl_chain *c, uint32_t type,
837 return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
838 nftnl_chain_do_snprintf);
841 EXPORT_SYMBOL(nftnl_rule_foreach);
843 int (*cb)(
struct nftnl_rule *r,
void *data),
846 struct nftnl_rule *cur, *tmp;
849 list_for_each_entry_safe(cur, tmp, &c->rule_list, head) {
857 EXPORT_SYMBOL(nftnl_rule_lookup_byindex);
859 nftnl_rule_lookup_byindex(
struct nftnl_chain *c, uint32_t index)
861 struct nftnl_rule *r;
863 list_for_each_entry(r, &c->rule_list, head) {
873 struct nftnl_rule *cur;
876 static void nftnl_rule_iter_init(
const struct nftnl_chain *c,
880 if (list_empty(&c->rule_list))
883 iter->cur = list_entry(c->rule_list.next,
struct nftnl_rule,
887 EXPORT_SYMBOL(nftnl_rule_iter_create);
896 nftnl_rule_iter_init(c, iter);
901 EXPORT_SYMBOL(nftnl_rule_iter_next);
904 struct nftnl_rule *rule = iter->cur;
910 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_rule, head);
911 if (&iter->cur->head == iter->c->rule_list.next)
917 EXPORT_SYMBOL(nftnl_rule_iter_destroy);
923 #define CHAIN_NAME_HSIZE 512
927 struct list_head list;
928 struct hlist_head name_hash[CHAIN_NAME_HSIZE];
931 EXPORT_SYMBOL(nftnl_chain_list_alloc);
941 INIT_LIST_HEAD(&list->list);
942 for (i = 0; i < CHAIN_NAME_HSIZE; i++)
943 INIT_HLIST_HEAD(&list->name_hash[i]);
948 EXPORT_SYMBOL(nftnl_chain_list_free);
953 list_for_each_entry_safe(r, tmp, &list->list, head) {
955 hlist_del(&r->hnode);
961 EXPORT_SYMBOL(nftnl_chain_list_is_empty);
964 return list_empty(&list->list);
967 static uint32_t djb_hash(
const char *key)
969 uint32_t i, hash = 5381;
971 for (i = 0; i < strlen(key); i++)
972 hash = ((hash << 5) + hash) + key[i];
977 EXPORT_SYMBOL(nftnl_chain_list_add);
980 int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
982 hlist_add_head(&r->hnode, &list->name_hash[key]);
983 list_add(&r->head, &list->list);
986 EXPORT_SYMBOL(nftnl_chain_list_add_tail);
989 int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
991 hlist_add_head(&r->hnode, &list->name_hash[key]);
992 list_add_tail(&r->head, &list->list);
995 EXPORT_SYMBOL(nftnl_chain_list_del);
999 hlist_del(&r->hnode);
1002 EXPORT_SYMBOL(nftnl_chain_list_foreach);
1010 list_for_each_entry_safe(cur, tmp, &chain_list->list, head) {
1011 ret = cb(cur, data);
1018 EXPORT_SYMBOL(nftnl_chain_list_lookup_byname);
1023 int key = djb_hash(chain) % CHAIN_NAME_HSIZE;
1025 struct hlist_node *n;
1027 hlist_for_each_entry(c, n, &chain_list->name_hash[key], hnode) {
1028 if (!strcmp(chain, c->name))
1039 EXPORT_SYMBOL(nftnl_chain_list_iter_create);
1050 if (nftnl_chain_list_is_empty(l))
1053 iter->cur = list_entry(l->list.next,
struct nftnl_chain, head);
1058 EXPORT_SYMBOL(nftnl_chain_list_iter_next);
1067 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_chain, head);
1068 if (&iter->cur->head == iter->list->list.next)
1074 EXPORT_SYMBOL(nftnl_chain_list_iter_destroy);