19 #include <netinet/in.h>
24 #include <libmnl/libmnl.h>
25 #include <linux/netfilter/nfnetlink.h>
26 #include <linux/netfilter/nf_tables.h>
28 #include <libnftnl/rule.h>
29 #include <libnftnl/expr.h>
31 #include "linux_list.h"
35 struct list_head head;
52 struct list_head expr_list;
55 struct nft_rule *nft_rule_alloc(
void)
59 r = calloc(1,
sizeof(
struct nft_rule));
63 INIT_LIST_HEAD(&r->expr_list);
67 EXPORT_SYMBOL(nft_rule_alloc);
69 void nft_rule_free(
struct nft_rule *r)
71 struct nft_rule_expr *e, *tmp;
73 list_for_each_entry_safe(e, tmp, &r->expr_list, head)
74 nft_rule_expr_free(e);
83 EXPORT_SYMBOL(nft_rule_free);
85 bool nft_rule_attr_is_set(const struct
nft_rule *r, uint16_t attr)
87 return r->flags & (1 << attr);
89 EXPORT_SYMBOL(nft_rule_attr_is_set);
91 void nft_rule_attr_unset(
struct nft_rule *r, uint16_t attr)
93 if (!(r->flags & (1 << attr)))
97 case NFT_RULE_ATTR_TABLE:
103 case NFT_RULE_ATTR_CHAIN:
109 case NFT_RULE_ATTR_HANDLE:
110 case NFT_RULE_ATTR_COMPAT_PROTO:
111 case NFT_RULE_ATTR_COMPAT_FLAGS:
112 case NFT_RULE_ATTR_POSITION:
113 case NFT_RULE_ATTR_FAMILY:
114 case NFT_RULE_ATTR_USERDATA:
118 r->flags &= ~(1 << attr);
120 EXPORT_SYMBOL(nft_rule_attr_unset);
122 static uint32_t nft_rule_attr_validate[NFT_RULE_ATTR_MAX + 1] = {
123 [NFT_RULE_ATTR_HANDLE] =
sizeof(uint64_t),
124 [NFT_RULE_ATTR_COMPAT_PROTO] =
sizeof(uint32_t),
125 [NFT_RULE_ATTR_COMPAT_FLAGS] =
sizeof(uint32_t),
126 [NFT_RULE_ATTR_FAMILY] =
sizeof(uint32_t),
127 [NFT_RULE_ATTR_POSITION] =
sizeof(uint64_t),
130 void nft_rule_attr_set_data(
struct nft_rule *r, uint16_t attr,
131 const void *data, uint32_t data_len)
133 if (attr > NFT_RULE_ATTR_MAX)
136 nft_assert_validate(data, nft_rule_attr_validate, attr, data_len);
139 case NFT_RULE_ATTR_TABLE:
143 r->table = strdup(data);
145 case NFT_RULE_ATTR_CHAIN:
149 r->chain = strdup(data);
151 case NFT_RULE_ATTR_HANDLE:
152 r->handle = *((uint64_t *)data);
154 case NFT_RULE_ATTR_COMPAT_PROTO:
155 r->compat.proto = *((uint32_t *)data);
157 case NFT_RULE_ATTR_COMPAT_FLAGS:
158 r->compat.flags = *((uint32_t *)data);
160 case NFT_RULE_ATTR_FAMILY:
161 r->family = *((uint32_t *)data);
163 case NFT_RULE_ATTR_POSITION:
164 r->position = *((uint64_t *)data);
166 case NFT_RULE_ATTR_USERDATA:
167 r->user.data = (
void *)data;
168 r->user.len = data_len;
171 r->flags |= (1 << attr);
173 EXPORT_SYMBOL(nft_rule_attr_set_data);
175 void nft_rule_attr_set(
struct nft_rule *r, uint16_t attr,
const void *data)
177 nft_rule_attr_set_data(r, attr, data, nft_rule_attr_validate[attr]);
179 EXPORT_SYMBOL(nft_rule_attr_set);
181 void nft_rule_attr_set_u32(
struct nft_rule *r, uint16_t attr, uint32_t val)
183 nft_rule_attr_set_data(r, attr, &val,
sizeof(uint32_t));
185 EXPORT_SYMBOL(nft_rule_attr_set_u32);
187 void nft_rule_attr_set_u64(
struct nft_rule *r, uint16_t attr, uint64_t val)
189 nft_rule_attr_set_data(r, attr, &val,
sizeof(uint64_t));
191 EXPORT_SYMBOL(nft_rule_attr_set_u64);
193 void nft_rule_attr_set_str(
struct nft_rule *r, uint16_t attr,
const char *str)
195 nft_rule_attr_set_data(r, attr, str, strlen(str));
197 EXPORT_SYMBOL(nft_rule_attr_set_str);
199 const void *nft_rule_attr_get_data(
const struct nft_rule *r, uint16_t attr,
202 if (!(r->flags & (1 << attr)))
206 case NFT_RULE_ATTR_FAMILY:
207 *data_len =
sizeof(uint32_t);
209 case NFT_RULE_ATTR_TABLE:
211 case NFT_RULE_ATTR_CHAIN:
213 case NFT_RULE_ATTR_HANDLE:
214 *data_len =
sizeof(uint64_t);
216 case NFT_RULE_ATTR_COMPAT_PROTO:
217 *data_len =
sizeof(uint32_t);
218 return &r->compat.proto;
219 case NFT_RULE_ATTR_COMPAT_FLAGS:
220 *data_len =
sizeof(uint32_t);
221 return &r->compat.flags;
222 case NFT_RULE_ATTR_POSITION:
223 *data_len =
sizeof(uint64_t);
225 case NFT_RULE_ATTR_USERDATA:
226 *data_len = r->user.len;
231 EXPORT_SYMBOL(nft_rule_attr_get_data);
233 const void *nft_rule_attr_get(
const struct nft_rule *r, uint16_t attr)
236 return nft_rule_attr_get_data(r, attr, &data_len);
238 EXPORT_SYMBOL(nft_rule_attr_get);
240 const char *nft_rule_attr_get_str(
const struct nft_rule *r, uint16_t attr)
242 return nft_rule_attr_get(r, attr);
244 EXPORT_SYMBOL(nft_rule_attr_get_str);
246 uint32_t nft_rule_attr_get_u32(
const struct nft_rule *r, uint16_t attr)
249 const uint32_t *val = nft_rule_attr_get_data(r, attr, &data_len);
251 nft_assert(val, attr, data_len ==
sizeof(uint32_t));
253 return val ? *val : 0;
255 EXPORT_SYMBOL(nft_rule_attr_get_u32);
257 uint64_t nft_rule_attr_get_u64(
const struct nft_rule *r, uint16_t attr)
260 const uint64_t *val = nft_rule_attr_get_data(r, attr, &data_len);
262 nft_assert(val, attr, data_len ==
sizeof(uint64_t));
264 return val ? *val : 0;
266 EXPORT_SYMBOL(nft_rule_attr_get_u64);
268 uint8_t nft_rule_attr_get_u8(
const struct nft_rule *r, uint16_t attr)
271 const uint8_t *val = nft_rule_attr_get_data(r, attr, &data_len);
273 nft_assert(val, attr, data_len ==
sizeof(uint8_t));
275 return val ? *val : 0;
277 EXPORT_SYMBOL(nft_rule_attr_get_u8);
279 void nft_rule_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nft_rule *r)
281 struct nft_rule_expr *expr;
284 if (r->flags & (1 << NFT_RULE_ATTR_TABLE))
285 mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, r->table);
286 if (r->flags & (1 << NFT_RULE_ATTR_CHAIN))
287 mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, r->chain);
288 if (r->flags & (1 << NFT_RULE_ATTR_HANDLE))
289 mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(r->handle));
290 if (r->flags & (1 << NFT_RULE_ATTR_POSITION))
291 mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
292 if (r->flags & (1 << NFT_RULE_ATTR_USERDATA)) {
293 mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
297 if (!list_empty(&r->expr_list)) {
298 nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
299 list_for_each_entry(expr, &r->expr_list, head) {
300 nft_rule_expr_build_payload(nlh, expr);
302 mnl_attr_nest_end(nlh, nest);
305 if (r->flags & (1 << NFT_RULE_ATTR_COMPAT_PROTO) &&
306 r->flags & (1 << NFT_RULE_ATTR_COMPAT_FLAGS)) {
308 nest = mnl_attr_nest_start(nlh, NFTA_RULE_COMPAT);
309 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_PROTO,
310 htonl(r->compat.proto));
311 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_FLAGS,
312 htonl(r->compat.flags));
313 mnl_attr_nest_end(nlh, nest);
316 EXPORT_SYMBOL(nft_rule_nlmsg_build_payload);
318 void nft_rule_add_expr(
struct nft_rule *r,
struct nft_rule_expr *expr)
320 list_add_tail(&expr->head, &r->expr_list);
322 EXPORT_SYMBOL(nft_rule_add_expr);
324 static int nft_rule_parse_attr_cb(
const struct nlattr *attr,
void *data)
326 const struct nlattr **tb = data;
327 int type = mnl_attr_get_type(attr);
329 if (mnl_attr_type_valid(attr, NFTA_RULE_MAX) < 0)
333 case NFTA_RULE_TABLE:
334 case NFTA_RULE_CHAIN:
335 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
336 perror(
"mnl_attr_validate");
340 case NFTA_RULE_HANDLE:
341 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
342 perror(
"mnl_attr_validate");
346 case NFTA_RULE_COMPAT:
347 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
348 perror(
"mnl_attr_validate");
352 case NFTA_RULE_POSITION:
353 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
354 perror(
"mnl_attr_validate");
358 case NFTA_RULE_USERDATA:
359 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
360 perror(
"mnl_attr_validate");
370 static int nft_rule_parse_expr_cb(
const struct nlattr *attr,
void *data)
372 const struct nlattr **tb = data;
373 int type = mnl_attr_get_type(attr);
375 if (mnl_attr_type_valid(attr, NFTA_EXPR_MAX) < 0)
380 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
381 perror(
"mnl_attr_validate");
386 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
387 perror(
"mnl_attr_validate");
397 static int nft_rule_parse_expr2(
struct nlattr *attr,
struct nft_rule *r)
399 struct nlattr *tb[NFTA_EXPR_MAX+1] = {};
400 struct nft_rule_expr *expr;
402 if (mnl_attr_parse_nested(attr, nft_rule_parse_expr_cb, tb) < 0)
405 expr = nft_rule_expr_alloc(mnl_attr_get_str(tb[NFTA_EXPR_NAME]));
409 if (tb[NFTA_EXPR_DATA]) {
410 if (expr->ops->parse(expr, tb[NFTA_EXPR_DATA]) < 0) {
415 list_add_tail(&expr->head, &r->expr_list);
420 static int nft_rule_parse_expr(
struct nlattr *nest,
struct nft_rule *r)
424 mnl_attr_for_each_nested(attr, nest) {
425 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
428 nft_rule_parse_expr2(attr, r);
433 static int nft_rule_parse_compat_cb(
const struct nlattr *attr,
void *data)
435 const struct nlattr **tb = data;
436 int type = mnl_attr_get_type(attr);
438 if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0)
442 case NFTA_RULE_COMPAT_PROTO:
443 case NFTA_RULE_COMPAT_FLAGS:
444 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
445 perror(
"mnl_attr_validate");
455 static int nft_rule_parse_compat(
struct nlattr *nest,
struct nft_rule *r)
457 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {};
459 if (mnl_attr_parse_nested(nest, nft_rule_parse_compat_cb, tb) < 0)
462 if (tb[NFTA_RULE_COMPAT_PROTO]) {
464 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO]));
465 r->flags |= (1 << NFT_RULE_ATTR_COMPAT_PROTO);
467 if (tb[NFTA_RULE_COMPAT_FLAGS]) {
469 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS]));
470 r->flags |= (1 << NFT_RULE_ATTR_COMPAT_FLAGS);
475 int nft_rule_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nft_rule *r)
477 struct nlattr *tb[NFTA_RULE_MAX+1] = {};
478 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
481 if (mnl_attr_parse(nlh,
sizeof(*nfg), nft_rule_parse_attr_cb, tb) < 0)
484 if (tb[NFTA_RULE_TABLE]) {
485 r->table = strdup(mnl_attr_get_str(tb[NFTA_RULE_TABLE]));
486 r->flags |= (1 << NFT_RULE_ATTR_TABLE);
488 if (tb[NFTA_RULE_CHAIN]) {
489 r->chain = strdup(mnl_attr_get_str(tb[NFTA_RULE_CHAIN]));
490 r->flags |= (1 << NFT_RULE_ATTR_CHAIN);
492 if (tb[NFTA_RULE_HANDLE]) {
493 r->handle = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_HANDLE]));
494 r->flags |= (1 << NFT_RULE_ATTR_HANDLE);
496 if (tb[NFTA_RULE_EXPRESSIONS])
497 ret = nft_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r);
498 if (tb[NFTA_RULE_COMPAT])
499 ret = nft_rule_parse_compat(tb[NFTA_RULE_COMPAT], r);
500 if (tb[NFTA_RULE_POSITION]) {
501 r->position = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_POSITION]));
502 r->flags |= (1 << NFT_RULE_ATTR_POSITION);
504 if (tb[NFTA_RULE_USERDATA]) {
506 mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
511 r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
513 r->user.data = malloc(r->user.len);
514 if (r->user.data == NULL)
517 memcpy(r->user.data, udata, r->user.len);
518 r->flags |= (1 << NFT_RULE_ATTR_USERDATA);
521 r->family = nfg->nfgen_family;
522 r->flags |= (1 << NFT_RULE_ATTR_FAMILY);
526 EXPORT_SYMBOL(nft_rule_nlmsg_parse);
529 int nft_jansson_parse_rule(
struct nft_rule *r, json_t *tree,
530 struct nft_parse_err *err)
532 json_t *root, *array;
533 struct nft_rule_expr *e;
534 const char *str = NULL;
539 root = nft_jansson_get_node(tree,
"rule", err);
543 if (nft_jansson_node_exist(root,
"family")) {
544 if (nft_jansson_parse_family(root, &family, err) != 0)
547 nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family);
550 if (nft_jansson_node_exist(root,
"table")) {
551 str = nft_jansson_parse_str(root,
"table", err);
555 nft_rule_attr_set_str(r, NFT_RULE_ATTR_TABLE, str);
558 if (nft_jansson_node_exist(root,
"chain")) {
559 str = nft_jansson_parse_str(root,
"chain", err);
563 nft_rule_attr_set_str(r, NFT_RULE_ATTR_CHAIN, str);
566 if (nft_jansson_node_exist(root,
"handle")) {
567 if (nft_jansson_parse_val(root,
"handle", NFT_TYPE_U64, &uval64,
571 nft_rule_attr_set_u64(r, NFT_RULE_ATTR_HANDLE, uval64);
574 if (nft_jansson_node_exist(root,
"compat_proto") ||
575 nft_jansson_node_exist(root,
"compat_flags")) {
576 if (nft_jansson_parse_val(root,
"compat_proto", NFT_TYPE_U32,
580 nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_PROTO, uval32);
582 if (nft_jansson_parse_val(root,
"compat_flags", NFT_TYPE_U32,
586 nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_FLAGS, uval32);
589 if (nft_jansson_node_exist(root,
"position")) {
590 if (nft_jansson_parse_val(root,
"position", NFT_TYPE_U64,
594 nft_rule_attr_set_u64(r, NFT_RULE_ATTR_POSITION, uval64);
597 array = json_object_get(root,
"expr");
599 err->error = NFT_PARSE_EMISSINGNODE;
600 err->node_name =
"expr";
604 for (i = 0; i < json_array_size(array); ++i) {
606 e = nft_jansson_expr_parse(json_array_get(array, i), err);
610 nft_rule_add_expr(r, e);
613 nft_jansson_free_root(tree);
616 nft_jansson_free_root(tree);
621 static int nft_rule_json_parse(
struct nft_rule *r,
const void *json,
622 struct nft_parse_err *err,
623 enum nft_parse_input input)
629 tree = nft_jansson_create_root(json, &error, err, input);
633 return nft_jansson_parse_rule(r, tree, err);
641 int nft_mxml_rule_parse(mxml_node_t *tree,
struct nft_rule *r,
642 struct nft_parse_err *err)
645 struct nft_rule_expr *e;
646 const char *table, *chain;
649 family = nft_mxml_family_parse(tree,
"family", MXML_DESCEND_FIRST,
652 nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family);
654 table = nft_mxml_str_parse(tree,
"table", MXML_DESCEND_FIRST,
657 nft_rule_attr_set_str(r, NFT_RULE_ATTR_TABLE, table);
659 chain = nft_mxml_str_parse(tree,
"chain", MXML_DESCEND_FIRST,
662 nft_rule_attr_set_str(r, NFT_RULE_ATTR_CHAIN, chain);
664 if (nft_mxml_num_parse(tree,
"handle", MXML_DESCEND_FIRST, BASE_DEC,
665 &r->handle, NFT_TYPE_U64, NFT_XML_MAND, err) >= 0)
666 r->flags |= (1 << NFT_RULE_ATTR_HANDLE);
668 if (nft_mxml_num_parse(tree,
"compat_proto", MXML_DESCEND_FIRST,
669 BASE_DEC, &r->compat.proto, NFT_TYPE_U32,
670 NFT_XML_OPT, err) >= 0)
671 r->flags |= (1 << NFT_RULE_ATTR_COMPAT_PROTO);
673 if (nft_mxml_num_parse(tree,
"compat_flags", MXML_DESCEND_FIRST,
674 BASE_DEC, &r->compat.flags, NFT_TYPE_U32,
675 NFT_XML_OPT, err) >= 0)
676 r->flags |= (1 << NFT_RULE_ATTR_COMPAT_FLAGS);
678 if (nft_rule_attr_is_set(r, NFT_RULE_ATTR_COMPAT_PROTO) !=
679 nft_rule_attr_is_set(r, NFT_RULE_ATTR_COMPAT_FLAGS)) {
683 if (nft_mxml_num_parse(tree,
"position", MXML_DESCEND_FIRST,
684 BASE_DEC, &r->position, NFT_TYPE_U64,
685 NFT_XML_OPT, err) >= 0)
686 r->flags |= (1 << NFT_RULE_ATTR_POSITION);
689 for (node = mxmlFindElement(tree, tree,
"expr",
"type",
692 node = mxmlFindElement(node, tree,
"expr",
"type",
693 NULL, MXML_DESCEND)) {
694 e = nft_mxml_expr_parse(node, err);
698 nft_rule_add_expr(r, e);
705 static int nft_rule_xml_parse(
struct nft_rule *r,
const void *xml,
706 struct nft_parse_err *err,
707 enum nft_parse_input input)
711 mxml_node_t *tree = nft_mxml_build_tree(xml,
"rule", err, input);
715 ret = nft_mxml_rule_parse(tree, r, err);
724 static int nft_rule_do_parse(
struct nft_rule *r,
enum nft_parse_type type,
725 const void *data,
struct nft_parse_err *err,
726 enum nft_parse_input input)
729 struct nft_parse_err perr;
733 ret = nft_rule_xml_parse(r, data, &perr, input);
736 ret = nft_rule_json_parse(r, data, &perr, input);
748 int nft_rule_parse(
struct nft_rule *r,
enum nft_parse_type type,
749 const char *data,
struct nft_parse_err *err)
751 return nft_rule_do_parse(r, type, data, err, NFT_PARSE_BUFFER);
753 EXPORT_SYMBOL(nft_rule_parse);
755 int nft_rule_parse_file(
struct nft_rule *r,
enum nft_parse_type type,
756 FILE *fp,
struct nft_parse_err *err)
758 return nft_rule_do_parse(r, type, fp, err, NFT_PARSE_FILE);
760 EXPORT_SYMBOL(nft_rule_parse_file);
762 static int nft_rule_snprintf_json(
char *buf,
size_t size,
struct nft_rule *r,
763 uint32_t type, uint32_t flags)
765 int ret, len = size, offset = 0;
766 struct nft_rule_expr *expr;
768 ret = snprintf(buf, len,
"{\"rule\":{");
769 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
771 if (r->flags & (1 << NFT_RULE_ATTR_FAMILY)) {
772 ret = snprintf(buf+offset, len,
"\"family\":\"%s\",",
773 nft_family2str(r->family));
774 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
777 if (r->flags & (1 << NFT_RULE_ATTR_TABLE)) {
778 ret = snprintf(buf+offset, len,
"\"table\":\"%s\",",
780 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
783 if (r->flags & (1 << NFT_RULE_ATTR_CHAIN)) {
784 ret = snprintf(buf+offset, len,
"\"chain\":\"%s\",",
786 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
788 if (r->flags & (1 << NFT_RULE_ATTR_HANDLE)) {
789 ret = snprintf(buf+offset, len,
"\"handle\":%llu,",
790 (
unsigned long long)r->handle);
791 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
794 if (r->flags & (1 << NFT_RULE_ATTR_COMPAT_PROTO) ||
795 r->flags & (1 << NFT_RULE_ATTR_COMPAT_FLAGS)) {
796 ret = snprintf(buf+offset, len,
"\"compat_flags\":%u,"
797 "\"compat_proto\":%u,",
798 r->compat.flags, r->compat.proto);
799 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
802 if (r->flags & (1 << NFT_RULE_ATTR_POSITION)) {
803 ret = snprintf(buf+offset, len,
"\"position\":%"PRIu64
",",
805 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
808 ret = snprintf(buf+offset, len,
"\"expr\":[");
809 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
811 list_for_each_entry(expr, &r->expr_list, head) {
812 ret = snprintf(buf+offset, len,
813 "{\"type\":\"%s\",", expr->ops->name);
814 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
816 ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
817 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
828 ret = snprintf(buf+offset, len,
"},");
829 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
834 ret = snprintf(buf+offset, len,
"]}}");
835 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
840 static int nft_rule_snprintf_xml(
char *buf,
size_t size,
struct nft_rule *r,
841 uint32_t type, uint32_t flags)
843 int ret, len = size, offset = 0;
844 struct nft_rule_expr *expr;
846 ret = snprintf(buf, len,
"<rule>");
847 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
849 if (r->flags & (1 << NFT_RULE_ATTR_FAMILY)) {
850 ret = snprintf(buf+offset, len,
"<family>%s</family>",
851 nft_family2str(r->family));
852 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
855 if (r->flags & (1 << NFT_RULE_ATTR_TABLE)) {
856 ret = snprintf(buf+offset, len,
"<table>%s</table>",
858 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
861 if (r->flags & (1 << NFT_RULE_ATTR_CHAIN)) {
862 ret = snprintf(buf+offset, len,
"<chain>%s</chain>",
864 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
866 if (r->flags & (1 << NFT_RULE_ATTR_HANDLE)) {
867 ret = snprintf(buf+offset, len,
"<handle>%llu</handle>",
868 (
unsigned long long)r->handle);
869 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
872 if (r->compat.flags != 0 || r->compat.proto != 0) {
873 ret = snprintf(buf+offset, len,
874 "<compat_flags>%u</compat_flags>"
875 "<compat_proto>%u</compat_proto>",
876 r->compat.flags, r->compat.proto);
877 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
880 if (r->flags & (1 << NFT_RULE_ATTR_POSITION)) {
881 ret = snprintf(buf+offset, len,
882 "<position>%"PRIu64
"</position>",
884 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
887 list_for_each_entry(expr, &r->expr_list, head) {
888 ret = snprintf(buf+offset, len,
889 "<expr type=\"%s\">", expr->ops->name);
890 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
892 ret = nft_rule_expr_snprintf(buf+offset, len, expr,
894 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
896 ret = snprintf(buf+offset, len,
"</expr>");
897 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
900 ret = snprintf(buf+offset, len,
"</rule>");
901 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
906 static int nft_rule_snprintf_default(
char *buf,
size_t size,
struct nft_rule *r,
907 uint32_t type, uint32_t flags)
909 struct nft_rule_expr *expr;
910 int ret, len = size, offset = 0, i;
912 if (r->flags & (1 << NFT_RULE_ATTR_FAMILY)) {
913 ret = snprintf(buf+offset, len,
"%s ",
914 nft_family2str(r->family));
915 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
918 if (r->flags & (1 << NFT_RULE_ATTR_TABLE)) {
919 ret = snprintf(buf+offset, len,
"%s ",
921 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
924 if (r->flags & (1 << NFT_RULE_ATTR_CHAIN)) {
925 ret = snprintf(buf+offset, len,
"%s ",
927 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
929 if (r->flags & (1 << NFT_RULE_ATTR_HANDLE)) {
930 ret = snprintf(buf+offset, len,
"%llu ",
931 (
unsigned long long)r->handle);
932 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
935 if (r->flags & (1 << NFT_RULE_ATTR_POSITION)) {
936 ret = snprintf(buf+offset, len,
"%llu ",
937 (
unsigned long long)r->position);
938 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
941 ret = snprintf(buf+offset, len,
"\n");
942 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
944 list_for_each_entry(expr, &r->expr_list, head) {
945 ret = snprintf(buf+offset, len,
" [ %s ", expr->ops->name);
946 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
948 ret = nft_rule_expr_snprintf(buf+offset, len, expr,
950 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
952 ret = snprintf(buf+offset, len,
"]\n");
953 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
957 ret = snprintf(buf+offset, len,
" userdata = { ");
958 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
960 for (i = 0; i < r->user.len; i++) {
961 char *c = r->user.data;
963 ret = snprintf(buf+offset, len,
"%c",
964 isalnum(c[i]) ? c[i] : 0);
965 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
968 ret = snprintf(buf+offset, len,
" }\n");
969 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
976 int nft_rule_snprintf(
char *buf,
size_t size,
struct nft_rule *r,
977 uint32_t type, uint32_t flags)
979 int ret, len = size, offset = 0;
980 uint32_t inner_flags = flags;
982 inner_flags &= ~NFT_OF_EVENT_ANY;
984 ret = nft_event_header_snprintf(buf+offset, len, type, flags);
985 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
988 case NFT_OUTPUT_DEFAULT:
989 ret = nft_rule_snprintf_default(buf+offset, len, r, type,
993 ret = nft_rule_snprintf_xml(buf+offset, len, r, type,
996 case NFT_OUTPUT_JSON:
997 ret = nft_rule_snprintf_json(buf+offset, len, r, type,
1004 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
1006 ret = nft_event_footer_snprintf(buf+offset, len, type, flags);
1007 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
1011 EXPORT_SYMBOL(nft_rule_snprintf);
1013 static inline int nft_rule_do_snprintf(
char *buf,
size_t size,
void *r,
1014 uint32_t type, uint32_t flags)
1016 return nft_rule_snprintf(buf, size, r, type, flags);
1019 int nft_rule_fprintf(FILE *fp,
struct nft_rule *r, uint32_t type,
1022 return nft_fprintf(fp, r, type, flags, nft_rule_do_snprintf);
1024 EXPORT_SYMBOL(nft_rule_fprintf);
1026 int nft_rule_expr_foreach(
struct nft_rule *r,
1027 int (*cb)(
struct nft_rule_expr *e,
void *data),
1030 struct nft_rule_expr *cur, *tmp;
1033 list_for_each_entry_safe(cur, tmp, &r->expr_list, head) {
1034 ret = cb(cur, data);
1040 EXPORT_SYMBOL(nft_rule_expr_foreach);
1044 struct nft_rule_expr *cur;
1056 iter->cur = list_entry(r->expr_list.next,
struct nft_rule_expr, head);
1060 EXPORT_SYMBOL(nft_rule_expr_iter_create);
1064 struct nft_rule_expr *expr = iter->cur;
1067 iter->cur = list_entry(iter->cur->head.next,
struct nft_rule_expr, head);
1068 if (&iter->cur->head == iter->r->expr_list.next)
1073 EXPORT_SYMBOL(nft_rule_expr_iter_next);
1079 EXPORT_SYMBOL(nft_rule_expr_iter_destroy);
1082 struct list_head list;
1093 INIT_LIST_HEAD(&list->list);
1097 EXPORT_SYMBOL(nft_rule_list_alloc);
1103 list_for_each_entry_safe(r, tmp, &list->list, head) {
1109 EXPORT_SYMBOL(nft_rule_list_free);
1113 return list_empty(&list->list);
1115 EXPORT_SYMBOL(nft_rule_list_is_empty);
1119 list_add(&r->head, &list->list);
1121 EXPORT_SYMBOL(nft_rule_list_add);
1125 list_add_tail(&r->head, &list->list);
1127 EXPORT_SYMBOL(nft_rule_list_add_tail);
1129 void nft_rule_list_del(
struct nft_rule *r)
1133 EXPORT_SYMBOL(nft_rule_list_del);
1136 int (*cb)(
struct nft_rule *r,
void *data),
1142 list_for_each_entry_safe(cur, tmp, &rule_list->list, head) {
1143 ret = cb(cur, data);
1149 EXPORT_SYMBOL(nft_rule_list_foreach);
1165 iter->cur = list_entry(l->list.next,
struct nft_rule, head);
1169 EXPORT_SYMBOL(nft_rule_list_iter_create);
1175 EXPORT_SYMBOL(nft_rule_list_iter_cur);
1182 iter->cur = list_entry(iter->cur->head.next,
struct nft_rule, head);
1183 if (&iter->cur->head == iter->list->list.next)
1188 EXPORT_SYMBOL(nft_rule_list_iter_next);
1194 EXPORT_SYMBOL(nft_rule_list_iter_destroy);