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>
33 struct list_head head;
50 static const char *nftnl_hooknum2str(
int family,
int hooknum)
58 case NF_INET_PRE_ROUTING:
60 case NF_INET_LOCAL_IN:
64 case NF_INET_LOCAL_OUT:
66 case NF_INET_POST_ROUTING:
82 case NF_NETDEV_INGRESS:
90 EXPORT_SYMBOL(nftnl_chain_alloc);
96 EXPORT_SYMBOL(nftnl_chain_free);
99 if (c->flags & (1 << NFTNL_CHAIN_NAME))
101 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
103 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
105 if (c->flags & (1 << NFTNL_CHAIN_DEV))
110 EXPORT_SYMBOL(nftnl_chain_is_set);
111 bool nftnl_chain_is_set(
const struct nftnl_chain *c, uint16_t attr)
113 return c->flags & (1 << attr);
116 EXPORT_SYMBOL(nftnl_chain_unset);
117 void nftnl_chain_unset(
struct nftnl_chain *c, uint16_t attr)
119 if (!(c->flags & (1 << attr)))
123 case NFTNL_CHAIN_NAME:
126 case NFTNL_CHAIN_TABLE:
129 case NFTNL_CHAIN_USE:
131 case NFTNL_CHAIN_TYPE:
134 case NFTNL_CHAIN_HOOKNUM:
135 case NFTNL_CHAIN_PRIO:
136 case NFTNL_CHAIN_POLICY:
137 case NFTNL_CHAIN_BYTES:
138 case NFTNL_CHAIN_PACKETS:
139 case NFTNL_CHAIN_HANDLE:
140 case NFTNL_CHAIN_FAMILY:
142 case NFTNL_CHAIN_DEV:
149 c->flags &= ~(1 << attr);
152 static uint32_t nftnl_chain_validate[NFTNL_CHAIN_MAX + 1] = {
153 [NFTNL_CHAIN_HOOKNUM] =
sizeof(uint32_t),
154 [NFTNL_CHAIN_PRIO] =
sizeof(int32_t),
155 [NFTNL_CHAIN_POLICY] =
sizeof(uint32_t),
156 [NFTNL_CHAIN_BYTES] =
sizeof(uint64_t),
157 [NFTNL_CHAIN_PACKETS] =
sizeof(uint64_t),
158 [NFTNL_CHAIN_HANDLE] =
sizeof(uint64_t),
159 [NFTNL_CHAIN_FAMILY] =
sizeof(uint32_t),
162 EXPORT_SYMBOL(nftnl_chain_set_data);
163 int nftnl_chain_set_data(
struct nftnl_chain *c, uint16_t attr,
164 const void *data, uint32_t data_len)
166 nftnl_assert_attr_exists(attr, NFTNL_CHAIN_MAX);
167 nftnl_assert_validate(data, nftnl_chain_validate, attr, data_len);
170 case NFTNL_CHAIN_NAME:
171 if (c->flags & (1 << NFTNL_CHAIN_NAME))
174 c->name = strdup(data);
178 case NFTNL_CHAIN_TABLE:
179 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
182 c->table = strdup(data);
186 case NFTNL_CHAIN_HOOKNUM:
187 memcpy(&c->hooknum, data,
sizeof(c->hooknum));
189 case NFTNL_CHAIN_PRIO:
190 memcpy(&c->prio, data,
sizeof(c->prio));
192 case NFTNL_CHAIN_POLICY:
193 memcpy(&c->policy, data,
sizeof(c->policy));
195 case NFTNL_CHAIN_USE:
196 memcpy(&c->use, data,
sizeof(c->use));
198 case NFTNL_CHAIN_BYTES:
199 memcpy(&c->bytes, data,
sizeof(c->bytes));
201 case NFTNL_CHAIN_PACKETS:
202 memcpy(&c->packets, data,
sizeof(c->packets));
204 case NFTNL_CHAIN_HANDLE:
205 memcpy(&c->handle, data,
sizeof(c->handle));
207 case NFTNL_CHAIN_FAMILY:
208 memcpy(&c->family, data,
sizeof(c->family));
210 case NFTNL_CHAIN_TYPE:
211 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
214 c->type = strdup(data);
218 case NFTNL_CHAIN_DEV:
219 if (c->flags & (1 << NFTNL_CHAIN_DEV))
222 c->dev = strdup(data);
227 c->flags |= (1 << attr);
231 EXPORT_SYMBOL(nftnl_chain_set);
232 void nftnl_chain_set(
struct nftnl_chain *c, uint16_t attr,
const void *data)
234 nftnl_chain_set_data(c, attr, data, nftnl_chain_validate[attr]);
237 EXPORT_SYMBOL(nftnl_chain_set_u32);
238 void nftnl_chain_set_u32(
struct nftnl_chain *c, uint16_t attr, uint32_t data)
240 nftnl_chain_set_data(c, attr, &data,
sizeof(uint32_t));
243 EXPORT_SYMBOL(nftnl_chain_set_s32);
244 void nftnl_chain_set_s32(
struct nftnl_chain *c, uint16_t attr, int32_t data)
246 nftnl_chain_set_data(c, attr, &data,
sizeof(int32_t));
249 EXPORT_SYMBOL(nftnl_chain_set_u64);
250 void nftnl_chain_set_u64(
struct nftnl_chain *c, uint16_t attr, uint64_t data)
252 nftnl_chain_set_data(c, attr, &data,
sizeof(uint64_t));
255 EXPORT_SYMBOL(nftnl_chain_set_u8);
256 void nftnl_chain_set_u8(
struct nftnl_chain *c, uint16_t attr, uint8_t data)
258 nftnl_chain_set_data(c, attr, &data,
sizeof(uint8_t));
261 EXPORT_SYMBOL(nftnl_chain_set_str);
262 int nftnl_chain_set_str(
struct nftnl_chain *c, uint16_t attr,
const char *str)
264 return nftnl_chain_set_data(c, attr, str, strlen(str) + 1);
267 EXPORT_SYMBOL(nftnl_chain_get_data);
268 const void *nftnl_chain_get_data(
const struct nftnl_chain *c, uint16_t attr,
271 if (!(c->flags & (1 << attr)))
275 case NFTNL_CHAIN_NAME:
276 *data_len = strlen(c->name) + 1;
278 case NFTNL_CHAIN_TABLE:
279 *data_len = strlen(c->table) + 1;
281 case NFTNL_CHAIN_HOOKNUM:
282 *data_len =
sizeof(uint32_t);
284 case NFTNL_CHAIN_PRIO:
285 *data_len =
sizeof(int32_t);
287 case NFTNL_CHAIN_POLICY:
288 *data_len =
sizeof(uint32_t);
290 case NFTNL_CHAIN_USE:
291 *data_len =
sizeof(uint32_t);
293 case NFTNL_CHAIN_BYTES:
294 *data_len =
sizeof(uint64_t);
296 case NFTNL_CHAIN_PACKETS:
297 *data_len =
sizeof(uint64_t);
299 case NFTNL_CHAIN_HANDLE:
300 *data_len =
sizeof(uint64_t);
302 case NFTNL_CHAIN_FAMILY:
303 *data_len =
sizeof(uint32_t);
305 case NFTNL_CHAIN_TYPE:
306 *data_len =
sizeof(uint32_t);
308 case NFTNL_CHAIN_DEV:
309 *data_len = strlen(c->dev) + 1;
315 EXPORT_SYMBOL(nftnl_chain_get);
316 const void *nftnl_chain_get(
const struct nftnl_chain *c, uint16_t attr)
319 return nftnl_chain_get_data(c, attr, &data_len);
322 EXPORT_SYMBOL(nftnl_chain_get_str);
323 const char *nftnl_chain_get_str(
const struct nftnl_chain *c, uint16_t attr)
325 return nftnl_chain_get(c, attr);
328 EXPORT_SYMBOL(nftnl_chain_get_u32);
329 uint32_t nftnl_chain_get_u32(
const struct nftnl_chain *c, uint16_t attr)
332 const uint32_t *val = nftnl_chain_get_data(c, attr, &data_len);
334 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
336 return val ? *val : 0;
339 EXPORT_SYMBOL(nftnl_chain_get_s32);
340 int32_t nftnl_chain_get_s32(
const struct nftnl_chain *c, uint16_t attr)
343 const int32_t *val = nftnl_chain_get_data(c, attr, &data_len);
345 nftnl_assert(val, attr, data_len ==
sizeof(int32_t));
347 return val ? *val : 0;
350 EXPORT_SYMBOL(nftnl_chain_get_u64);
351 uint64_t nftnl_chain_get_u64(
const struct nftnl_chain *c, uint16_t attr)
354 const uint64_t *val = nftnl_chain_get_data(c, attr, &data_len);
356 nftnl_assert(val, attr, data_len ==
sizeof(int64_t));
358 return val ? *val : 0;
361 EXPORT_SYMBOL(nftnl_chain_get_u8);
362 uint8_t nftnl_chain_get_u8(
const struct nftnl_chain *c, uint16_t attr)
365 const uint8_t *val = nftnl_chain_get_data(c, attr, &data_len);
367 nftnl_assert(val, attr, data_len ==
sizeof(int8_t));
369 return val ? *val : 0;
372 EXPORT_SYMBOL(nftnl_chain_nlmsg_build_payload);
373 void nftnl_chain_nlmsg_build_payload(
struct nlmsghdr *nlh,
const struct nftnl_chain *c)
375 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
376 mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, c->table);
377 if (c->flags & (1 << NFTNL_CHAIN_NAME))
378 mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, c->name);
379 if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) &&
380 (c->flags & (1 << NFTNL_CHAIN_PRIO))) {
383 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
384 mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(c->hooknum));
385 mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio));
386 if (c->flags & (1 << NFTNL_CHAIN_DEV))
387 mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev);
388 mnl_attr_nest_end(nlh, nest);
390 if (c->flags & (1 << NFTNL_CHAIN_POLICY))
391 mnl_attr_put_u32(nlh, NFTA_CHAIN_POLICY, htonl(c->policy));
392 if (c->flags & (1 << NFTNL_CHAIN_USE))
393 mnl_attr_put_u32(nlh, NFTA_CHAIN_USE, htonl(c->use));
394 if ((c->flags & (1 << NFTNL_CHAIN_PACKETS)) &&
395 (c->flags & (1 << NFTNL_CHAIN_BYTES))) {
398 nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_COUNTERS);
399 mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, be64toh(c->packets));
400 mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, be64toh(c->bytes));
401 mnl_attr_nest_end(nlh, nest);
403 if (c->flags & (1 << NFTNL_CHAIN_HANDLE))
404 mnl_attr_put_u64(nlh, NFTA_CHAIN_HANDLE, be64toh(c->handle));
405 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
406 mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, c->type);
409 static int nftnl_chain_parse_attr_cb(
const struct nlattr *attr,
void *data)
411 const struct nlattr **tb = data;
412 int type = mnl_attr_get_type(attr);
414 if (mnl_attr_type_valid(attr, NFTA_CHAIN_MAX) < 0)
418 case NFTA_CHAIN_NAME:
419 case NFTA_CHAIN_TABLE:
420 case NFTA_CHAIN_TYPE:
421 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
424 case NFTA_CHAIN_HOOK:
425 case NFTA_CHAIN_COUNTERS:
426 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
429 case NFTA_CHAIN_POLICY:
431 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
434 case NFTA_CHAIN_HANDLE:
435 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
444 static int nftnl_chain_parse_counters_cb(
const struct nlattr *attr,
void *data)
446 const struct nlattr **tb = data;
447 int type = mnl_attr_get_type(attr);
449 if (mnl_attr_type_valid(attr, NFTA_COUNTER_MAX) < 0)
453 case NFTA_COUNTER_BYTES:
454 case NFTA_COUNTER_PACKETS:
455 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
464 static int nftnl_chain_parse_counters(
struct nlattr *attr,
struct nftnl_chain *c)
466 struct nlattr *tb[NFTA_COUNTER_MAX+1] = {};
468 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_counters_cb, tb) < 0)
471 if (tb[NFTA_COUNTER_PACKETS]) {
472 c->packets = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_PACKETS]));
473 c->flags |= (1 << NFTNL_CHAIN_PACKETS);
475 if (tb[NFTA_COUNTER_BYTES]) {
476 c->bytes = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_BYTES]));
477 c->flags |= (1 << NFTNL_CHAIN_BYTES);
483 static int nftnl_chain_parse_hook_cb(
const struct nlattr *attr,
void *data)
485 const struct nlattr **tb = data;
486 int type = mnl_attr_get_type(attr);
488 if (mnl_attr_type_valid(attr, NFTA_HOOK_MAX) < 0)
492 case NFTA_HOOK_HOOKNUM:
493 case NFTA_HOOK_PRIORITY:
494 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
498 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
507 static int nftnl_chain_parse_hook(
struct nlattr *attr,
struct nftnl_chain *c)
509 struct nlattr *tb[NFTA_HOOK_MAX+1] = {};
511 if (mnl_attr_parse_nested(attr, nftnl_chain_parse_hook_cb, tb) < 0)
514 if (tb[NFTA_HOOK_HOOKNUM]) {
515 c->hooknum = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_HOOKNUM]));
516 c->flags |= (1 << NFTNL_CHAIN_HOOKNUM);
518 if (tb[NFTA_HOOK_PRIORITY]) {
519 c->prio = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_PRIORITY]));
520 c->flags |= (1 << NFTNL_CHAIN_PRIO);
522 if (tb[NFTA_HOOK_DEV]) {
523 c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV]));
526 c->flags |= (1 << NFTNL_CHAIN_DEV);
532 EXPORT_SYMBOL(nftnl_chain_nlmsg_parse);
533 int nftnl_chain_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_chain *c)
535 struct nlattr *tb[NFTA_CHAIN_MAX+1] = {};
536 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
539 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_chain_parse_attr_cb, tb) < 0)
542 if (tb[NFTA_CHAIN_NAME]) {
543 if (c->flags & (1 << NFTNL_CHAIN_NAME))
545 c->name = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_NAME]));
548 c->flags |= (1 << NFTNL_CHAIN_NAME);
550 if (tb[NFTA_CHAIN_TABLE]) {
551 if (c->flags & (1 << NFTNL_CHAIN_TABLE))
553 c->table = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TABLE]));
556 c->flags |= (1 << NFTNL_CHAIN_TABLE);
558 if (tb[NFTA_CHAIN_HOOK]) {
559 ret = nftnl_chain_parse_hook(tb[NFTA_CHAIN_HOOK], c);
563 if (tb[NFTA_CHAIN_POLICY]) {
564 c->policy = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_POLICY]));
565 c->flags |= (1 << NFTNL_CHAIN_POLICY);
567 if (tb[NFTA_CHAIN_USE]) {
568 c->use = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_USE]));
569 c->flags |= (1 << NFTNL_CHAIN_USE);
571 if (tb[NFTA_CHAIN_COUNTERS]) {
572 ret = nftnl_chain_parse_counters(tb[NFTA_CHAIN_COUNTERS], c);
576 if (tb[NFTA_CHAIN_HANDLE]) {
577 c->handle = be64toh(mnl_attr_get_u64(tb[NFTA_CHAIN_HANDLE]));
578 c->flags |= (1 << NFTNL_CHAIN_HANDLE);
580 if (tb[NFTA_CHAIN_TYPE]) {
581 if (c->flags & (1 << NFTNL_CHAIN_TYPE))
583 c->type = strdup(mnl_attr_get_str(tb[NFTA_CHAIN_TYPE]));
586 c->flags |= (1 << NFTNL_CHAIN_TYPE);
589 c->family = nfg->nfgen_family;
590 c->flags |= (1 << NFTNL_CHAIN_FAMILY);
595 static inline int nftnl_str2hooknum(
int family,
const char *hook)
599 for (hooknum = 0; hooknum < NF_INET_NUMHOOKS; hooknum++) {
600 if (strcmp(hook, nftnl_hooknum2str(family, hooknum)) == 0)
606 static int nftnl_chain_snprintf_default(
char *buf,
size_t size,
609 int ret, remain = size, offset = 0;
611 ret = snprintf(buf, remain,
"%s %s %s use %u",
612 nftnl_family2str(c->family), c->table, c->name, c->use);
613 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
615 if (c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) {
616 ret = snprintf(buf + offset, remain,
" type %s hook %s prio %d",
617 c->type, nftnl_hooknum2str(c->family, c->hooknum),
619 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
621 if (c->flags & (1 << NFTNL_CHAIN_POLICY)) {
622 ret = snprintf(buf + offset, remain,
" policy %s",
623 nftnl_verdict2str(c->policy));
624 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
627 ret = snprintf(buf + offset, remain,
628 " packets %"PRIu64
" bytes %"PRIu64
"",
629 c->packets, c->bytes);
630 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
632 if (c->flags & (1 << NFTNL_CHAIN_DEV)) {
633 ret = snprintf(buf + offset, remain,
" dev %s ",
635 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
642 static int nftnl_chain_cmd_snprintf(
char *buf,
size_t size,
644 uint32_t type, uint32_t flags)
646 int ret, remain = size, offset = 0;
649 case NFTNL_OUTPUT_DEFAULT:
650 ret = nftnl_chain_snprintf_default(buf + offset, remain, c);
651 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
653 case NFTNL_OUTPUT_XML:
654 case NFTNL_OUTPUT_JSON:
662 EXPORT_SYMBOL(nftnl_chain_snprintf);
663 int nftnl_chain_snprintf(
char *buf,
size_t size,
const struct nftnl_chain *c,
664 uint32_t type, uint32_t flags)
669 return nftnl_chain_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
673 static int nftnl_chain_do_snprintf(
char *buf,
size_t size,
const void *c,
674 uint32_t cmd, uint32_t type, uint32_t flags)
676 return nftnl_chain_snprintf(buf, size, c, type, flags);
679 EXPORT_SYMBOL(nftnl_chain_fprintf);
680 int nftnl_chain_fprintf(FILE *fp,
const struct nftnl_chain *c, uint32_t type,
683 return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
684 nftnl_chain_do_snprintf);
688 struct list_head list;
691 EXPORT_SYMBOL(nftnl_chain_list_alloc);
700 INIT_LIST_HEAD(&list->list);
705 EXPORT_SYMBOL(nftnl_chain_list_free);
710 list_for_each_entry_safe(r, tmp, &list->list, head) {
717 EXPORT_SYMBOL(nftnl_chain_list_is_empty);
720 return list_empty(&list->list);
723 EXPORT_SYMBOL(nftnl_chain_list_add);
726 list_add(&r->head, &list->list);
729 EXPORT_SYMBOL(nftnl_chain_list_add_tail);
732 list_add_tail(&r->head, &list->list);
735 EXPORT_SYMBOL(nftnl_chain_list_del);
741 EXPORT_SYMBOL(nftnl_chain_list_foreach);
749 list_for_each_entry_safe(cur, tmp, &chain_list->list, head) {
762 EXPORT_SYMBOL(nftnl_chain_list_iter_create);
773 if (nftnl_chain_list_is_empty(l))
776 iter->cur = list_entry(l->list.next,
struct nftnl_chain, head);
781 EXPORT_SYMBOL(nftnl_chain_list_iter_next);
790 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_chain, head);
791 if (&iter->cur->head == iter->list->list.next)
797 EXPORT_SYMBOL(nftnl_chain_list_iter_destroy);