19 #include <netinet/in.h>
25 #include <libmnl/libmnl.h>
26 #include <linux/netfilter/nfnetlink.h>
27 #include <linux/netfilter/nf_tables.h>
29 #include <libnftnl/rule.h>
30 #include <libnftnl/set.h>
31 #include <libnftnl/expr.h>
34 struct list_head head;
52 struct list_head expr_list;
55 EXPORT_SYMBOL(nftnl_rule_alloc);
64 INIT_LIST_HEAD(&r->expr_list);
69 EXPORT_SYMBOL(nftnl_rule_free);
70 void nftnl_rule_free(
const struct nftnl_rule *r)
72 struct nftnl_expr *e, *tmp;
74 list_for_each_entry_safe(e, tmp, &r->expr_list, head)
77 if (r->flags & (1 << (NFTNL_RULE_TABLE)))
79 if (r->flags & (1 << (NFTNL_RULE_CHAIN)))
81 if (r->flags & (1 << (NFTNL_RULE_USERDATA)))
87 EXPORT_SYMBOL(nftnl_rule_is_set);
88 bool nftnl_rule_is_set(const struct
nftnl_rule *r, uint16_t attr)
90 return r->flags & (1 << attr);
93 EXPORT_SYMBOL(nftnl_rule_unset);
94 void nftnl_rule_unset(
struct nftnl_rule *r, uint16_t attr)
96 if (!(r->flags & (1 << attr)))
100 case NFTNL_RULE_TABLE:
103 case NFTNL_RULE_CHAIN:
106 case NFTNL_RULE_HANDLE:
107 case NFTNL_RULE_COMPAT_PROTO:
108 case NFTNL_RULE_COMPAT_FLAGS:
109 case NFTNL_RULE_POSITION:
110 case NFTNL_RULE_FAMILY:
113 case NFTNL_RULE_USERDATA:
118 r->flags &= ~(1 << attr);
121 static uint32_t nftnl_rule_validate[NFTNL_RULE_MAX + 1] = {
122 [NFTNL_RULE_HANDLE] =
sizeof(uint64_t),
123 [NFTNL_RULE_COMPAT_PROTO] =
sizeof(uint32_t),
124 [NFTNL_RULE_COMPAT_FLAGS] =
sizeof(uint32_t),
125 [NFTNL_RULE_FAMILY] =
sizeof(uint32_t),
126 [NFTNL_RULE_POSITION] =
sizeof(uint64_t),
127 [NFTNL_RULE_ID] =
sizeof(uint32_t),
130 EXPORT_SYMBOL(nftnl_rule_set_data);
131 int nftnl_rule_set_data(
struct nftnl_rule *r, uint16_t attr,
132 const void *data, uint32_t data_len)
134 nftnl_assert_attr_exists(attr, NFTNL_RULE_MAX);
135 nftnl_assert_validate(data, nftnl_rule_validate, attr, data_len);
138 case NFTNL_RULE_TABLE:
139 if (r->flags & (1 << NFTNL_RULE_TABLE))
142 r->table = strdup(data);
146 case NFTNL_RULE_CHAIN:
147 if (r->flags & (1 << NFTNL_RULE_CHAIN))
150 r->chain = strdup(data);
154 case NFTNL_RULE_HANDLE:
155 memcpy(&r->handle, data,
sizeof(r->handle));
157 case NFTNL_RULE_COMPAT_PROTO:
158 memcpy(&r->compat.proto, data,
sizeof(r->compat.proto));
160 case NFTNL_RULE_COMPAT_FLAGS:
161 memcpy(&r->compat.flags, data,
sizeof(r->compat.flags));
163 case NFTNL_RULE_FAMILY:
164 memcpy(&r->family, data,
sizeof(r->family));
166 case NFTNL_RULE_POSITION:
167 memcpy(&r->position, data,
sizeof(r->position));
169 case NFTNL_RULE_USERDATA:
170 if (r->flags & (1 << NFTNL_RULE_USERDATA))
173 r->user.data = malloc(data_len);
177 memcpy(r->user.data, data, data_len);
178 r->user.len = data_len;
181 memcpy(&r->id, data,
sizeof(r->id));
184 r->flags |= (1 << attr);
188 EXPORT_SYMBOL(nftnl_rule_set);
189 int nftnl_rule_set(
struct nftnl_rule *r, uint16_t attr,
const void *data)
191 return nftnl_rule_set_data(r, attr, data, nftnl_rule_validate[attr]);
194 EXPORT_SYMBOL(nftnl_rule_set_u32);
195 void nftnl_rule_set_u32(
struct nftnl_rule *r, uint16_t attr, uint32_t val)
197 nftnl_rule_set_data(r, attr, &val,
sizeof(uint32_t));
200 EXPORT_SYMBOL(nftnl_rule_set_u64);
201 void nftnl_rule_set_u64(
struct nftnl_rule *r, uint16_t attr, uint64_t val)
203 nftnl_rule_set_data(r, attr, &val,
sizeof(uint64_t));
206 EXPORT_SYMBOL(nftnl_rule_set_str);
207 int nftnl_rule_set_str(
struct nftnl_rule *r, uint16_t attr,
const char *str)
209 return nftnl_rule_set_data(r, attr, str, strlen(str) + 1);
212 EXPORT_SYMBOL(nftnl_rule_get_data);
213 const void *nftnl_rule_get_data(
const struct nftnl_rule *r, uint16_t attr,
216 if (!(r->flags & (1 << attr)))
220 case NFTNL_RULE_FAMILY:
221 *data_len =
sizeof(uint32_t);
223 case NFTNL_RULE_TABLE:
224 *data_len = strlen(r->table) + 1;
226 case NFTNL_RULE_CHAIN:
227 *data_len = strlen(r->chain) + 1;
229 case NFTNL_RULE_HANDLE:
230 *data_len =
sizeof(uint64_t);
232 case NFTNL_RULE_COMPAT_PROTO:
233 *data_len =
sizeof(uint32_t);
234 return &r->compat.proto;
235 case NFTNL_RULE_COMPAT_FLAGS:
236 *data_len =
sizeof(uint32_t);
237 return &r->compat.flags;
238 case NFTNL_RULE_POSITION:
239 *data_len =
sizeof(uint64_t);
241 case NFTNL_RULE_USERDATA:
242 *data_len = r->user.len;
245 *data_len =
sizeof(uint32_t);
251 EXPORT_SYMBOL(nftnl_rule_get);
252 const void *nftnl_rule_get(
const struct nftnl_rule *r, uint16_t attr)
255 return nftnl_rule_get_data(r, attr, &data_len);
258 EXPORT_SYMBOL(nftnl_rule_get_str);
259 const char *nftnl_rule_get_str(
const struct nftnl_rule *r, uint16_t attr)
261 return nftnl_rule_get(r, attr);
264 EXPORT_SYMBOL(nftnl_rule_get_u32);
265 uint32_t nftnl_rule_get_u32(
const struct nftnl_rule *r, uint16_t attr)
268 const uint32_t *val = nftnl_rule_get_data(r, attr, &data_len);
270 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
272 return val ? *val : 0;
275 EXPORT_SYMBOL(nftnl_rule_get_u64);
276 uint64_t nftnl_rule_get_u64(
const struct nftnl_rule *r, uint16_t attr)
279 const uint64_t *val = nftnl_rule_get_data(r, attr, &data_len);
281 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
283 return val ? *val : 0;
286 EXPORT_SYMBOL(nftnl_rule_get_u8);
287 uint8_t nftnl_rule_get_u8(
const struct nftnl_rule *r, uint16_t attr)
290 const uint8_t *val = nftnl_rule_get_data(r, attr, &data_len);
292 nftnl_assert(val, attr, data_len ==
sizeof(uint8_t));
294 return val ? *val : 0;
297 EXPORT_SYMBOL(nftnl_rule_nlmsg_build_payload);
298 void nftnl_rule_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_rule *r)
300 struct nftnl_expr *expr;
301 struct nlattr *nest, *nest2;
303 if (r->flags & (1 << NFTNL_RULE_TABLE))
304 mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, r->table);
305 if (r->flags & (1 << NFTNL_RULE_CHAIN))
306 mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, r->chain);
307 if (r->flags & (1 << NFTNL_RULE_HANDLE))
308 mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(r->handle));
309 if (r->flags & (1 << NFTNL_RULE_POSITION))
310 mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
311 if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
312 mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
316 if (!list_empty(&r->expr_list)) {
317 nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
318 list_for_each_entry(expr, &r->expr_list, head) {
319 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
320 nftnl_expr_build_payload(nlh, expr);
321 mnl_attr_nest_end(nlh, nest2);
323 mnl_attr_nest_end(nlh, nest);
326 if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) &&
327 r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
329 nest = mnl_attr_nest_start(nlh, NFTA_RULE_COMPAT);
330 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_PROTO,
331 htonl(r->compat.proto));
332 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_FLAGS,
333 htonl(r->compat.flags));
334 mnl_attr_nest_end(nlh, nest);
336 if (r->flags & (1 << NFTNL_RULE_ID))
337 mnl_attr_put_u32(nlh, NFTA_RULE_ID, htonl(r->id));
340 EXPORT_SYMBOL(nftnl_rule_add_expr);
341 void nftnl_rule_add_expr(
struct nftnl_rule *r,
struct nftnl_expr *expr)
343 list_add_tail(&expr->head, &r->expr_list);
346 static int nftnl_rule_parse_attr_cb(
const struct nlattr *attr,
void *data)
348 const struct nlattr **tb = data;
349 int type = mnl_attr_get_type(attr);
351 if (mnl_attr_type_valid(attr, NFTA_RULE_MAX) < 0)
355 case NFTA_RULE_TABLE:
356 case NFTA_RULE_CHAIN:
357 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
360 case NFTA_RULE_HANDLE:
361 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
364 case NFTA_RULE_COMPAT:
365 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
368 case NFTA_RULE_POSITION:
369 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
372 case NFTA_RULE_USERDATA:
373 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
377 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
386 static int nftnl_rule_parse_expr(
struct nlattr *nest,
struct nftnl_rule *r)
388 struct nftnl_expr *expr;
391 mnl_attr_for_each_nested(attr, nest) {
392 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
395 expr = nftnl_expr_parse(attr);
399 list_add_tail(&expr->head, &r->expr_list);
404 static int nftnl_rule_parse_compat_cb(
const struct nlattr *attr,
void *data)
406 const struct nlattr **tb = data;
407 int type = mnl_attr_get_type(attr);
409 if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0)
413 case NFTA_RULE_COMPAT_PROTO:
414 case NFTA_RULE_COMPAT_FLAGS:
415 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
424 static int nftnl_rule_parse_compat(
struct nlattr *nest,
struct nftnl_rule *r)
426 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {};
428 if (mnl_attr_parse_nested(nest, nftnl_rule_parse_compat_cb, tb) < 0)
431 if (tb[NFTA_RULE_COMPAT_PROTO]) {
433 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO]));
434 r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
436 if (tb[NFTA_RULE_COMPAT_FLAGS]) {
438 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS]));
439 r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
444 EXPORT_SYMBOL(nftnl_rule_nlmsg_parse);
445 int nftnl_rule_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_rule *r)
447 struct nlattr *tb[NFTA_RULE_MAX+1] = {};
448 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
451 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_rule_parse_attr_cb, tb) < 0)
454 if (tb[NFTA_RULE_TABLE]) {
455 if (r->flags & (1 << NFTNL_RULE_TABLE))
457 r->table = strdup(mnl_attr_get_str(tb[NFTA_RULE_TABLE]));
460 r->flags |= (1 << NFTNL_RULE_TABLE);
462 if (tb[NFTA_RULE_CHAIN]) {
463 if (r->flags & (1 << NFTNL_RULE_CHAIN))
465 r->chain = strdup(mnl_attr_get_str(tb[NFTA_RULE_CHAIN]));
468 r->flags |= (1 << NFTNL_RULE_CHAIN);
470 if (tb[NFTA_RULE_HANDLE]) {
471 r->handle = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_HANDLE]));
472 r->flags |= (1 << NFTNL_RULE_HANDLE);
474 if (tb[NFTA_RULE_EXPRESSIONS]) {
475 ret = nftnl_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r);
479 if (tb[NFTA_RULE_COMPAT]) {
480 ret = nftnl_rule_parse_compat(tb[NFTA_RULE_COMPAT], r);
484 if (tb[NFTA_RULE_POSITION]) {
485 r->position = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_POSITION]));
486 r->flags |= (1 << NFTNL_RULE_POSITION);
488 if (tb[NFTA_RULE_USERDATA]) {
490 mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
492 if (r->flags & (1 << NFTNL_RULE_USERDATA))
495 r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
497 r->user.data = malloc(r->user.len);
498 if (r->user.data == NULL)
501 memcpy(r->user.data, udata, r->user.len);
502 r->flags |= (1 << NFTNL_RULE_USERDATA);
504 if (tb[NFTA_RULE_ID]) {
505 r->id = ntohl(mnl_attr_get_u32(tb[NFTA_RULE_ID]));
506 r->flags |= (1 << NFTNL_RULE_ID);
509 r->family = nfg->nfgen_family;
510 r->flags |= (1 << NFTNL_RULE_FAMILY);
515 static int nftnl_rule_do_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
516 const void *data,
struct nftnl_parse_err *err,
517 enum nftnl_parse_input input)
520 struct nftnl_parse_err perr = {};
523 case NFTNL_PARSE_JSON:
524 case NFTNL_PARSE_XML:
536 EXPORT_SYMBOL(nftnl_rule_parse);
537 int nftnl_rule_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
538 const char *data,
struct nftnl_parse_err *err)
540 return nftnl_rule_do_parse(r, type, data, err, NFTNL_PARSE_BUFFER);
543 EXPORT_SYMBOL(nftnl_rule_parse_file);
544 int nftnl_rule_parse_file(
struct nftnl_rule *r,
enum nftnl_parse_type type,
545 FILE *fp,
struct nftnl_parse_err *err)
547 return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE);
550 static int nftnl_rule_snprintf_default(
char *buf,
size_t size,
552 uint32_t type, uint32_t flags)
554 struct nftnl_expr *expr;
555 int ret, remain = size, offset = 0, i;
557 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
558 ret = snprintf(buf + offset, remain,
"%s ",
559 nftnl_family2str(r->family));
560 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
563 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
564 ret = snprintf(buf + offset, remain,
"%s ",
566 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
569 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
570 ret = snprintf(buf + offset, remain,
"%s ",
572 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
574 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
575 ret = snprintf(buf + offset, remain,
"%llu ",
576 (
unsigned long long)r->handle);
577 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
580 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
581 ret = snprintf(buf + offset, remain,
"%llu ",
582 (
unsigned long long)r->position);
583 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
586 if (r->flags & (1 << NFTNL_RULE_ID)) {
587 ret = snprintf(buf + offset, remain,
"%u ", r->id);
588 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
591 ret = snprintf(buf + offset, remain,
"\n");
592 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
594 list_for_each_entry(expr, &r->expr_list, head) {
595 ret = snprintf(buf + offset, remain,
" [ %s ", expr->ops->name);
596 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
598 ret = nftnl_expr_snprintf(buf + offset, remain, expr,
600 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
602 ret = snprintf(buf + offset, remain,
"]\n");
603 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
607 ret = snprintf(buf + offset, remain,
" userdata = { ");
608 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
610 for (i = 0; i < r->user.len; i++) {
611 char *c = r->user.data;
613 ret = snprintf(buf + offset, remain,
"%c",
614 isalnum(c[i]) ? c[i] : 0);
615 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
618 ret = snprintf(buf + offset, remain,
" }\n");
619 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
626 static int nftnl_rule_cmd_snprintf(
char *buf,
size_t size,
628 uint32_t type, uint32_t flags)
630 int ret, remain = size, offset = 0;
631 uint32_t inner_flags = flags;
633 inner_flags &= ~NFTNL_OF_EVENT_ANY;
636 case NFTNL_OUTPUT_DEFAULT:
637 ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type,
639 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
641 case NFTNL_OUTPUT_JSON:
642 case NFTNL_OUTPUT_XML:
650 EXPORT_SYMBOL(nftnl_rule_snprintf);
651 int nftnl_rule_snprintf(
char *buf,
size_t size,
const struct nftnl_rule *r,
652 uint32_t type, uint32_t flags)
657 return nftnl_rule_cmd_snprintf(buf, size, r, nftnl_flag2cmd(flags), type,
661 static int nftnl_rule_do_snprintf(
char *buf,
size_t size,
const void *r,
662 uint32_t cmd, uint32_t type, uint32_t flags)
664 return nftnl_rule_snprintf(buf, size, r, type, flags);
667 EXPORT_SYMBOL(nftnl_rule_fprintf);
668 int nftnl_rule_fprintf(FILE *fp,
const struct nftnl_rule *r, uint32_t type,
671 return nftnl_fprintf(fp, r, NFTNL_CMD_UNSPEC, type, flags,
672 nftnl_rule_do_snprintf);
675 EXPORT_SYMBOL(nftnl_expr_foreach);
677 int (*cb)(
struct nftnl_expr *e,
void *data),
680 struct nftnl_expr *cur, *tmp;
683 list_for_each_entry_safe(cur, tmp, &r->expr_list, head) {
693 struct nftnl_expr *cur;
696 static void nftnl_expr_iter_init(
const struct nftnl_rule *r,
700 if (list_empty(&r->expr_list))
703 iter->cur = list_entry(r->expr_list.next,
struct nftnl_expr,
707 EXPORT_SYMBOL(nftnl_expr_iter_create);
716 nftnl_expr_iter_init(r, iter);
721 EXPORT_SYMBOL(nftnl_expr_iter_next);
724 struct nftnl_expr *expr = iter->cur;
730 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_expr, head);
731 if (&iter->cur->head == iter->r->expr_list.next)
737 EXPORT_SYMBOL(nftnl_expr_iter_destroy);
744 struct list_head list;
747 EXPORT_SYMBOL(nftnl_rule_list_alloc);
756 INIT_LIST_HEAD(&list->list);
761 EXPORT_SYMBOL(nftnl_rule_list_free);
766 list_for_each_entry_safe(r, tmp, &list->list, head) {
773 EXPORT_SYMBOL(nftnl_rule_list_is_empty);
776 return list_empty(&list->list);
779 EXPORT_SYMBOL(nftnl_rule_list_add);
782 list_add(&r->head, &list->list);
785 EXPORT_SYMBOL(nftnl_rule_list_insert_at);
788 list_add(&r->head, &pos->head);
791 EXPORT_SYMBOL(nftnl_rule_list_add_tail);
794 list_add_tail(&r->head, &list->list);
797 EXPORT_SYMBOL(nftnl_rule_list_del);
798 void nftnl_rule_list_del(
struct nftnl_rule *r)
803 EXPORT_SYMBOL(nftnl_rule_list_foreach);
811 list_for_each_entry_safe(cur, tmp, &rule_list->list, head) {
824 EXPORT_SYMBOL(nftnl_rule_list_iter_create);
835 if (nftnl_rule_list_is_empty(l))
838 iter->cur = list_entry(l->list.next,
struct nftnl_rule, head);
843 EXPORT_SYMBOL(nftnl_rule_list_iter_cur);
849 EXPORT_SYMBOL(nftnl_rule_list_iter_next);
858 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_rule, head);
859 if (&iter->cur->head == iter->list->list.next)
865 EXPORT_SYMBOL(nftnl_rule_list_iter_destroy);