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/set.h>
30 #include <libnftnl/expr.h>
33 struct list_head head;
50 struct list_head expr_list;
61 INIT_LIST_HEAD(&r->expr_list);
65 EXPORT_SYMBOL(nftnl_rule_alloc, nft_rule_alloc);
69 struct nftnl_expr *e, *tmp;
71 list_for_each_entry_safe(e, tmp, &r->expr_list, head)
81 EXPORT_SYMBOL(nftnl_rule_free, nft_rule_free);
83 bool nftnl_rule_is_set(const struct
nftnl_rule *r, uint16_t attr)
85 return r->flags & (1 << attr);
87 EXPORT_SYMBOL(nftnl_rule_is_set, nft_rule_attr_is_set);
89 void nftnl_rule_unset(
struct nftnl_rule *r, uint16_t attr)
91 if (!(r->flags & (1 << attr)))
95 case NFTNL_RULE_TABLE:
101 case NFTNL_RULE_CHAIN:
107 case NFTNL_RULE_HANDLE:
108 case NFTNL_RULE_COMPAT_PROTO:
109 case NFTNL_RULE_COMPAT_FLAGS:
110 case NFTNL_RULE_POSITION:
111 case NFTNL_RULE_FAMILY:
112 case NFTNL_RULE_USERDATA:
116 r->flags &= ~(1 << attr);
118 EXPORT_SYMBOL(nftnl_rule_unset, nft_rule_attr_unset);
120 static uint32_t nftnl_rule_validate[NFTNL_RULE_MAX + 1] = {
121 [NFTNL_RULE_HANDLE] =
sizeof(uint64_t),
122 [NFTNL_RULE_COMPAT_PROTO] =
sizeof(uint32_t),
123 [NFTNL_RULE_COMPAT_FLAGS] =
sizeof(uint32_t),
124 [NFTNL_RULE_FAMILY] =
sizeof(uint32_t),
125 [NFTNL_RULE_POSITION] =
sizeof(uint64_t),
128 void nftnl_rule_set_data(
struct nftnl_rule *r, uint16_t attr,
129 const void *data, uint32_t data_len)
131 if (attr > NFTNL_RULE_MAX)
134 nftnl_assert_validate(data, nftnl_rule_validate, attr, data_len);
137 case NFTNL_RULE_TABLE:
141 r->table = strdup(data);
143 case NFTNL_RULE_CHAIN:
147 r->chain = strdup(data);
149 case NFTNL_RULE_HANDLE:
150 r->handle = *((uint64_t *)data);
152 case NFTNL_RULE_COMPAT_PROTO:
153 r->compat.proto = *((uint32_t *)data);
155 case NFTNL_RULE_COMPAT_FLAGS:
156 r->compat.flags = *((uint32_t *)data);
158 case NFTNL_RULE_FAMILY:
159 r->family = *((uint32_t *)data);
161 case NFTNL_RULE_POSITION:
162 r->position = *((uint64_t *)data);
164 case NFTNL_RULE_USERDATA:
165 r->user.data = (
void *)data;
166 r->user.len = data_len;
169 r->flags |= (1 << attr);
171 EXPORT_SYMBOL(nftnl_rule_set_data, nft_rule_attr_set_data);
173 void nftnl_rule_set(
struct nftnl_rule *r, uint16_t attr,
const void *data)
175 nftnl_rule_set_data(r, attr, data, nftnl_rule_validate[attr]);
177 EXPORT_SYMBOL(nftnl_rule_set, nft_rule_attr_set);
179 void nftnl_rule_set_u32(
struct nftnl_rule *r, uint16_t attr, uint32_t val)
181 nftnl_rule_set_data(r, attr, &val,
sizeof(uint32_t));
183 EXPORT_SYMBOL(nftnl_rule_set_u32, nft_rule_attr_set_u32);
185 void nftnl_rule_set_u64(
struct nftnl_rule *r, uint16_t attr, uint64_t val)
187 nftnl_rule_set_data(r, attr, &val,
sizeof(uint64_t));
189 EXPORT_SYMBOL(nftnl_rule_set_u64, nft_rule_attr_set_u64);
191 void nftnl_rule_set_str(
struct nftnl_rule *r, uint16_t attr,
const char *str)
193 nftnl_rule_set_data(r, attr, str, strlen(str));
195 EXPORT_SYMBOL(nftnl_rule_set_str, nft_rule_attr_set_str);
197 const void *nftnl_rule_get_data(
const struct nftnl_rule *r, uint16_t attr,
200 if (!(r->flags & (1 << attr)))
204 case NFTNL_RULE_FAMILY:
205 *data_len =
sizeof(uint32_t);
207 case NFTNL_RULE_TABLE:
209 case NFTNL_RULE_CHAIN:
211 case NFTNL_RULE_HANDLE:
212 *data_len =
sizeof(uint64_t);
214 case NFTNL_RULE_COMPAT_PROTO:
215 *data_len =
sizeof(uint32_t);
216 return &r->compat.proto;
217 case NFTNL_RULE_COMPAT_FLAGS:
218 *data_len =
sizeof(uint32_t);
219 return &r->compat.flags;
220 case NFTNL_RULE_POSITION:
221 *data_len =
sizeof(uint64_t);
223 case NFTNL_RULE_USERDATA:
224 *data_len = r->user.len;
229 EXPORT_SYMBOL(nftnl_rule_get_data, nft_rule_attr_get_data);
231 const void *nftnl_rule_get(
const struct nftnl_rule *r, uint16_t attr)
234 return nftnl_rule_get_data(r, attr, &data_len);
236 EXPORT_SYMBOL(nftnl_rule_get, nft_rule_attr_get);
238 const char *nftnl_rule_get_str(
const struct nftnl_rule *r, uint16_t attr)
240 return nftnl_rule_get(r, attr);
242 EXPORT_SYMBOL(nftnl_rule_get_str, nft_rule_attr_get_str);
244 uint32_t nftnl_rule_get_u32(
const struct nftnl_rule *r, uint16_t attr)
247 const uint32_t *val = nftnl_rule_get_data(r, attr, &data_len);
249 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
251 return val ? *val : 0;
253 EXPORT_SYMBOL(nftnl_rule_get_u32, nft_rule_attr_get_u32);
255 uint64_t nftnl_rule_get_u64(
const struct nftnl_rule *r, uint16_t attr)
258 const uint64_t *val = nftnl_rule_get_data(r, attr, &data_len);
260 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
262 return val ? *val : 0;
264 EXPORT_SYMBOL(nftnl_rule_get_u64, nft_rule_attr_get_u64);
266 uint8_t nftnl_rule_get_u8(
const struct nftnl_rule *r, uint16_t attr)
269 const uint8_t *val = nftnl_rule_get_data(r, attr, &data_len);
271 nftnl_assert(val, attr, data_len ==
sizeof(uint8_t));
273 return val ? *val : 0;
275 EXPORT_SYMBOL(nftnl_rule_get_u8, nft_rule_attr_get_u8);
277 void nftnl_rule_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_rule *r)
279 struct nftnl_expr *expr;
280 struct nlattr *nest, *nest2;
282 if (r->flags & (1 << NFTNL_RULE_TABLE))
283 mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, r->table);
284 if (r->flags & (1 << NFTNL_RULE_CHAIN))
285 mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, r->chain);
286 if (r->flags & (1 << NFTNL_RULE_HANDLE))
287 mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(r->handle));
288 if (r->flags & (1 << NFTNL_RULE_POSITION))
289 mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
290 if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
291 mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
295 if (!list_empty(&r->expr_list)) {
296 nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
297 list_for_each_entry(expr, &r->expr_list, head) {
298 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
299 nftnl_expr_build_payload(nlh, expr);
300 mnl_attr_nest_end(nlh, nest2);
302 mnl_attr_nest_end(nlh, nest);
305 if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) &&
306 r->flags & (1 << NFTNL_RULE_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(nftnl_rule_nlmsg_build_payload, nft_rule_nlmsg_build_payload);
318 void nftnl_rule_add_expr(
struct nftnl_rule *r,
struct nftnl_expr *expr)
320 list_add_tail(&expr->head, &r->expr_list);
322 EXPORT_SYMBOL(nftnl_rule_add_expr, nft_rule_add_expr);
324 static int nftnl_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)
338 case NFTA_RULE_HANDLE:
339 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
342 case NFTA_RULE_COMPAT:
343 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
346 case NFTA_RULE_POSITION:
347 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
350 case NFTA_RULE_USERDATA:
351 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
360 static int nftnl_rule_parse_expr(
struct nlattr *nest,
struct nftnl_rule *r)
362 struct nftnl_expr *expr;
365 mnl_attr_for_each_nested(attr, nest) {
366 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
369 expr = nftnl_expr_parse(attr);
373 list_add_tail(&expr->head, &r->expr_list);
378 static int nftnl_rule_parse_compat_cb(
const struct nlattr *attr,
void *data)
380 const struct nlattr **tb = data;
381 int type = mnl_attr_get_type(attr);
383 if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0)
387 case NFTA_RULE_COMPAT_PROTO:
388 case NFTA_RULE_COMPAT_FLAGS:
389 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
398 static int nftnl_rule_parse_compat(
struct nlattr *nest,
struct nftnl_rule *r)
400 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {};
402 if (mnl_attr_parse_nested(nest, nftnl_rule_parse_compat_cb, tb) < 0)
405 if (tb[NFTA_RULE_COMPAT_PROTO]) {
407 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO]));
408 r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
410 if (tb[NFTA_RULE_COMPAT_FLAGS]) {
412 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS]));
413 r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
418 int nftnl_rule_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_rule *r)
420 struct nlattr *tb[NFTA_RULE_MAX+1] = {};
421 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
424 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_rule_parse_attr_cb, tb) < 0)
427 if (tb[NFTA_RULE_TABLE]) {
429 r->table = strdup(mnl_attr_get_str(tb[NFTA_RULE_TABLE]));
430 r->flags |= (1 << NFTNL_RULE_TABLE);
432 if (tb[NFTA_RULE_CHAIN]) {
434 r->chain = strdup(mnl_attr_get_str(tb[NFTA_RULE_CHAIN]));
435 r->flags |= (1 << NFTNL_RULE_CHAIN);
437 if (tb[NFTA_RULE_HANDLE]) {
438 r->handle = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_HANDLE]));
439 r->flags |= (1 << NFTNL_RULE_HANDLE);
441 if (tb[NFTA_RULE_EXPRESSIONS])
442 ret = nftnl_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r);
443 if (tb[NFTA_RULE_COMPAT])
444 ret = nftnl_rule_parse_compat(tb[NFTA_RULE_COMPAT], r);
445 if (tb[NFTA_RULE_POSITION]) {
446 r->position = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_POSITION]));
447 r->flags |= (1 << NFTNL_RULE_POSITION);
449 if (tb[NFTA_RULE_USERDATA]) {
451 mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
456 r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
458 r->user.data = malloc(r->user.len);
459 if (r->user.data == NULL)
462 memcpy(r->user.data, udata, r->user.len);
463 r->flags |= (1 << NFTNL_RULE_USERDATA);
466 r->family = nfg->nfgen_family;
467 r->flags |= (1 << NFTNL_RULE_FAMILY);
471 EXPORT_SYMBOL(nftnl_rule_nlmsg_parse, nft_rule_nlmsg_parse);
474 int nftnl_jansson_parse_rule(
struct nftnl_rule *r, json_t *tree,
475 struct nftnl_parse_err *err,
478 json_t *root, *array;
479 struct nftnl_expr *e;
480 const char *str = NULL;
485 root = nftnl_jansson_get_node(tree,
"rule", err);
489 if (nftnl_jansson_node_exist(root,
"family")) {
490 if (nftnl_jansson_parse_family(root, &family, err) != 0)
493 nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
496 if (nftnl_jansson_node_exist(root,
"table")) {
497 str = nftnl_jansson_parse_str(root,
"table", err);
501 nftnl_rule_set_str(r, NFTNL_RULE_TABLE, str);
504 if (nftnl_jansson_node_exist(root,
"chain")) {
505 str = nftnl_jansson_parse_str(root,
"chain", err);
509 nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, str);
512 if (nftnl_jansson_node_exist(root,
"handle")) {
513 if (nftnl_jansson_parse_val(root,
"handle", NFTNL_TYPE_U64, &uval64,
517 nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE, uval64);
520 if (nftnl_jansson_node_exist(root,
"compat_proto") ||
521 nftnl_jansson_node_exist(root,
"compat_flags")) {
522 if (nftnl_jansson_parse_val(root,
"compat_proto", NFTNL_TYPE_U32,
526 nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_PROTO, uval32);
528 if (nftnl_jansson_parse_val(root,
"compat_flags", NFTNL_TYPE_U32,
532 nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_FLAGS, uval32);
535 if (nftnl_jansson_node_exist(root,
"position")) {
536 if (nftnl_jansson_parse_val(root,
"position", NFTNL_TYPE_U64,
540 nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, uval64);
543 array = json_object_get(root,
"expr");
545 err->error = NFTNL_PARSE_EMISSINGNODE;
546 err->node_name =
"expr";
550 for (i = 0; i < json_array_size(array); ++i) {
552 e = nftnl_jansson_expr_parse(json_array_get(array, i), err,
557 nftnl_rule_add_expr(r, e);
566 static int nftnl_rule_json_parse(
struct nftnl_rule *r,
const void *json,
567 struct nftnl_parse_err *err,
568 enum nftnl_parse_input input,
576 tree = nftnl_jansson_create_root(json, &error, err, input);
580 ret = nftnl_jansson_parse_rule(r, tree, err, set_list);
582 nftnl_jansson_free_root(tree);
591 int nftnl_mxml_rule_parse(mxml_node_t *tree,
struct nftnl_rule *r,
592 struct nftnl_parse_err *err,
596 struct nftnl_expr *e;
597 const char *table, *chain;
600 family = nftnl_mxml_family_parse(tree,
"family", MXML_DESCEND_FIRST,
601 NFTNL_XML_MAND, err);
603 nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
605 table = nftnl_mxml_str_parse(tree,
"table", MXML_DESCEND_FIRST,
606 NFTNL_XML_MAND, err);
608 nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
610 chain = nftnl_mxml_str_parse(tree,
"chain", MXML_DESCEND_FIRST,
611 NFTNL_XML_MAND, err);
613 nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
615 if (nftnl_mxml_num_parse(tree,
"handle", MXML_DESCEND_FIRST, BASE_DEC,
616 &r->handle, NFTNL_TYPE_U64, NFTNL_XML_MAND, err) >= 0)
617 r->flags |= (1 << NFTNL_RULE_HANDLE);
619 if (nftnl_mxml_num_parse(tree,
"compat_proto", MXML_DESCEND_FIRST,
620 BASE_DEC, &r->compat.proto, NFTNL_TYPE_U32,
621 NFTNL_XML_OPT, err) >= 0)
622 r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
624 if (nftnl_mxml_num_parse(tree,
"compat_flags", MXML_DESCEND_FIRST,
625 BASE_DEC, &r->compat.flags, NFTNL_TYPE_U32,
626 NFTNL_XML_OPT, err) >= 0)
627 r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
629 if (nftnl_rule_is_set(r, NFTNL_RULE_COMPAT_PROTO) !=
630 nftnl_rule_is_set(r, NFTNL_RULE_COMPAT_FLAGS)) {
634 if (nftnl_mxml_num_parse(tree,
"position", MXML_DESCEND_FIRST,
635 BASE_DEC, &r->position, NFTNL_TYPE_U64,
636 NFTNL_XML_OPT, err) >= 0)
637 r->flags |= (1 << NFTNL_RULE_POSITION);
640 for (node = mxmlFindElement(tree, tree,
"expr",
"type",
643 node = mxmlFindElement(node, tree,
"expr",
"type",
644 NULL, MXML_DESCEND)) {
645 e = nftnl_mxml_expr_parse(node, err, set_list);
649 nftnl_rule_add_expr(r, e);
656 static int nftnl_rule_xml_parse(
struct nftnl_rule *r,
const void *xml,
657 struct nftnl_parse_err *err,
658 enum nftnl_parse_input input,
663 mxml_node_t *tree = nftnl_mxml_build_tree(xml,
"rule", err, input);
667 ret = nftnl_mxml_rule_parse(tree, r, err, set_list);
676 static int nftnl_rule_do_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
677 const void *data,
struct nftnl_parse_err *err,
678 enum nftnl_parse_input input)
681 struct nftnl_parse_err perr;
684 case NFTNL_PARSE_XML:
685 ret = nftnl_rule_xml_parse(r, data, &perr, input, NULL);
687 case NFTNL_PARSE_JSON:
688 ret = nftnl_rule_json_parse(r, data, &perr, input, NULL);
700 int nftnl_rule_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
701 const char *data,
struct nftnl_parse_err *err)
703 return nftnl_rule_do_parse(r, type, data, err, NFTNL_PARSE_BUFFER);
705 EXPORT_SYMBOL(nftnl_rule_parse, nft_rule_parse);
707 int nftnl_rule_parse_file(
struct nftnl_rule *r,
enum nftnl_parse_type type,
708 FILE *fp,
struct nftnl_parse_err *err)
710 return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE);
712 EXPORT_SYMBOL(nftnl_rule_parse_file, nft_rule_parse_file);
714 static int nftnl_rule_snprintf_json(
char *buf,
size_t size,
struct nftnl_rule *r,
715 uint32_t type, uint32_t flags)
717 int ret, len = size, offset = 0;
718 struct nftnl_expr *expr;
720 ret = snprintf(buf, len,
"{\"rule\":{");
721 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
723 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
724 ret = snprintf(buf+offset, len,
"\"family\":\"%s\",",
725 nftnl_family2str(r->family));
726 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
729 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
730 ret = snprintf(buf+offset, len,
"\"table\":\"%s\",",
732 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
735 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
736 ret = snprintf(buf+offset, len,
"\"chain\":\"%s\",",
738 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
740 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
741 ret = snprintf(buf+offset, len,
"\"handle\":%llu,",
742 (
unsigned long long)r->handle);
743 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
746 if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) ||
747 r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
748 ret = snprintf(buf+offset, len,
"\"compat_flags\":%u,"
749 "\"compat_proto\":%u,",
750 r->compat.flags, r->compat.proto);
751 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
754 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
755 ret = snprintf(buf+offset, len,
"\"position\":%"PRIu64
",",
757 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
760 ret = snprintf(buf+offset, len,
"\"expr\":[");
761 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
763 list_for_each_entry(expr, &r->expr_list, head) {
764 ret = snprintf(buf+offset, len,
765 "{\"type\":\"%s\",", expr->ops->name);
766 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
768 ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
769 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
780 ret = snprintf(buf+offset, len,
"},");
781 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
786 ret = snprintf(buf+offset, len,
"]}}");
787 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
792 static int nftnl_rule_snprintf_xml(
char *buf,
size_t size,
struct nftnl_rule *r,
793 uint32_t type, uint32_t flags)
795 int ret, len = size, offset = 0;
796 struct nftnl_expr *expr;
798 ret = snprintf(buf, len,
"<rule>");
799 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
801 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
802 ret = snprintf(buf+offset, len,
"<family>%s</family>",
803 nftnl_family2str(r->family));
804 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
807 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
808 ret = snprintf(buf+offset, len,
"<table>%s</table>",
810 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
813 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
814 ret = snprintf(buf+offset, len,
"<chain>%s</chain>",
816 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
818 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
819 ret = snprintf(buf+offset, len,
"<handle>%llu</handle>",
820 (
unsigned long long)r->handle);
821 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
824 if (r->compat.flags != 0 || r->compat.proto != 0) {
825 ret = snprintf(buf+offset, len,
826 "<compat_flags>%u</compat_flags>"
827 "<compat_proto>%u</compat_proto>",
828 r->compat.flags, r->compat.proto);
829 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
832 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
833 ret = snprintf(buf+offset, len,
834 "<position>%"PRIu64
"</position>",
836 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
839 list_for_each_entry(expr, &r->expr_list, head) {
840 ret = snprintf(buf+offset, len,
841 "<expr type=\"%s\">", expr->ops->name);
842 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
844 ret = nftnl_expr_snprintf(buf+offset, len, expr,
846 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
848 ret = snprintf(buf+offset, len,
"</expr>");
849 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
852 ret = snprintf(buf+offset, len,
"</rule>");
853 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
858 static int nftnl_rule_snprintf_default(
char *buf,
size_t size,
struct nftnl_rule *r,
859 uint32_t type, uint32_t flags)
861 struct nftnl_expr *expr;
862 int ret, len = size, offset = 0, i;
864 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
865 ret = snprintf(buf+offset, len,
"%s ",
866 nftnl_family2str(r->family));
867 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
870 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
871 ret = snprintf(buf+offset, len,
"%s ",
873 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
876 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
877 ret = snprintf(buf+offset, len,
"%s ",
879 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
881 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
882 ret = snprintf(buf+offset, len,
"%llu ",
883 (
unsigned long long)r->handle);
884 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
887 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
888 ret = snprintf(buf+offset, len,
"%llu ",
889 (
unsigned long long)r->position);
890 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
893 ret = snprintf(buf+offset, len,
"\n");
894 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
896 list_for_each_entry(expr, &r->expr_list, head) {
897 ret = snprintf(buf+offset, len,
" [ %s ", expr->ops->name);
898 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
900 ret = nftnl_expr_snprintf(buf+offset, len, expr,
902 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
904 ret = snprintf(buf+offset, len,
"]\n");
905 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
909 ret = snprintf(buf+offset, len,
" userdata = { ");
910 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
912 for (i = 0; i < r->user.len; i++) {
913 char *c = r->user.data;
915 ret = snprintf(buf+offset, len,
"%c",
916 isalnum(c[i]) ? c[i] : 0);
917 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
920 ret = snprintf(buf+offset, len,
" }\n");
921 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
928 static int nftnl_rule_cmd_snprintf(
char *buf,
size_t size,
struct nftnl_rule *r,
929 uint32_t cmd, uint32_t type, uint32_t flags)
931 int ret, len = size, offset = 0;
932 uint32_t inner_flags = flags;
934 inner_flags &= ~NFTNL_OF_EVENT_ANY;
936 ret = nftnl_cmd_header_snprintf(buf + offset, len, cmd, type, flags);
937 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
940 case NFTNL_OUTPUT_DEFAULT:
941 ret = nftnl_rule_snprintf_default(buf+offset, len, r, type,
944 case NFTNL_OUTPUT_XML:
945 ret = nftnl_rule_snprintf_xml(buf+offset, len, r, type,
948 case NFTNL_OUTPUT_JSON:
949 ret = nftnl_rule_snprintf_json(buf+offset, len, r, type,
956 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
958 ret = nftnl_cmd_footer_snprintf(buf + offset, len, cmd, type, flags);
959 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
964 int nftnl_rule_snprintf(
char *buf,
size_t size,
struct nftnl_rule *r,
965 uint32_t type, uint32_t flags)
967 return nftnl_rule_cmd_snprintf(buf, size, r, nftnl_flag2cmd(flags), type,
970 EXPORT_SYMBOL(nftnl_rule_snprintf, nft_rule_snprintf);
972 static inline int nftnl_rule_do_snprintf(
char *buf,
size_t size,
void *r,
973 uint32_t cmd, uint32_t type,
976 return nftnl_rule_snprintf(buf, size, r, type, flags);
979 int nftnl_rule_fprintf(FILE *fp,
struct nftnl_rule *r, uint32_t type,
982 return nftnl_fprintf(fp, r, NFTNL_CMD_UNSPEC, type, flags,
983 nftnl_rule_do_snprintf);
985 EXPORT_SYMBOL(nftnl_rule_fprintf, nft_rule_fprintf);
988 int (*cb)(
struct nftnl_expr *e,
void *data),
991 struct nftnl_expr *cur, *tmp;
994 list_for_each_entry_safe(cur, tmp, &r->expr_list, head) {
1001 EXPORT_SYMBOL(nftnl_expr_foreach, nft_rule_expr_foreach);
1005 struct nftnl_expr *cur;
1017 if (list_empty(&r->expr_list))
1020 iter->cur = list_entry(r->expr_list.next,
struct nftnl_expr,
1025 EXPORT_SYMBOL(nftnl_expr_iter_create, nft_rule_expr_iter_create);
1029 struct nftnl_expr *expr = iter->cur;
1035 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_expr, head);
1036 if (&iter->cur->head == iter->r->expr_list.next)
1041 EXPORT_SYMBOL(nftnl_expr_iter_next, nft_rule_expr_iter_next);
1047 EXPORT_SYMBOL(nftnl_expr_iter_destroy, nft_rule_expr_iter_destroy);
1050 struct list_head list;
1061 INIT_LIST_HEAD(&list->list);
1065 EXPORT_SYMBOL(nftnl_rule_list_alloc, nft_rule_list_alloc);
1071 list_for_each_entry_safe(r, tmp, &list->list, head) {
1077 EXPORT_SYMBOL(nftnl_rule_list_free, nft_rule_list_free);
1081 return list_empty(&list->list);
1083 EXPORT_SYMBOL(nftnl_rule_list_is_empty, nft_rule_list_is_empty);
1087 list_add(&r->head, &list->list);
1089 EXPORT_SYMBOL(nftnl_rule_list_add, nft_rule_list_add);
1093 list_add_tail(&r->head, &list->list);
1095 EXPORT_SYMBOL(nftnl_rule_list_add_tail, nft_rule_list_add_tail);
1097 void nftnl_rule_list_del(
struct nftnl_rule *r)
1101 EXPORT_SYMBOL(nftnl_rule_list_del, nft_rule_list_del);
1110 list_for_each_entry_safe(cur, tmp, &rule_list->list, head) {
1111 ret = cb(cur, data);
1117 EXPORT_SYMBOL(nftnl_rule_list_foreach, nft_rule_list_foreach);
1133 if (nftnl_rule_list_is_empty(l))
1136 iter->cur = list_entry(l->list.next,
struct nftnl_rule, head);
1140 EXPORT_SYMBOL(nftnl_rule_list_iter_create, nft_rule_list_iter_create);
1146 EXPORT_SYMBOL(nftnl_rule_list_iter_cur, nft_rule_list_iter_cur);
1156 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_rule, head);
1157 if (&iter->cur->head == iter->list->list.next)
1162 EXPORT_SYMBOL(nftnl_rule_list_iter_next, nft_rule_list_iter_next);
1168 EXPORT_SYMBOL(nftnl_rule_list_iter_destroy, nft_rule_list_iter_destroy);