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_ALIAS(nftnl_rule_alloc, nft_rule_alloc);
67 void nftnl_rule_free(
const struct nftnl_rule *r)
69 struct nftnl_expr *e, *tmp;
71 list_for_each_entry_safe(e, tmp, &r->expr_list, head)
78 if (r->user.data != NULL)
83 EXPORT_SYMBOL_ALIAS(nftnl_rule_free, nft_rule_free);
85 bool nftnl_rule_is_set(const struct
nftnl_rule *r, uint16_t attr)
87 return r->flags & (1 << attr);
89 EXPORT_SYMBOL_ALIAS(nftnl_rule_is_set, nft_rule_attr_is_set);
91 void nftnl_rule_unset(
struct nftnl_rule *r, uint16_t attr)
93 if (!(r->flags & (1 << attr)))
97 case NFTNL_RULE_TABLE:
103 case NFTNL_RULE_CHAIN:
109 case NFTNL_RULE_HANDLE:
110 case NFTNL_RULE_COMPAT_PROTO:
111 case NFTNL_RULE_COMPAT_FLAGS:
112 case NFTNL_RULE_POSITION:
113 case NFTNL_RULE_FAMILY:
114 case NFTNL_RULE_USERDATA:
118 r->flags &= ~(1 << attr);
120 EXPORT_SYMBOL_ALIAS(nftnl_rule_unset, nft_rule_attr_unset);
122 static uint32_t nftnl_rule_validate[NFTNL_RULE_MAX + 1] = {
123 [NFTNL_RULE_HANDLE] =
sizeof(uint64_t),
124 [NFTNL_RULE_COMPAT_PROTO] =
sizeof(uint32_t),
125 [NFTNL_RULE_COMPAT_FLAGS] =
sizeof(uint32_t),
126 [NFTNL_RULE_FAMILY] =
sizeof(uint32_t),
127 [NFTNL_RULE_POSITION] =
sizeof(uint64_t),
130 void nftnl_rule_set_data(
struct nftnl_rule *r, uint16_t attr,
131 const void *data, uint32_t data_len)
133 if (attr > NFTNL_RULE_MAX)
136 nftnl_assert_validate(data, nftnl_rule_validate, attr, data_len);
139 case NFTNL_RULE_TABLE:
143 r->table = strdup(data);
145 case NFTNL_RULE_CHAIN:
149 r->chain = strdup(data);
151 case NFTNL_RULE_HANDLE:
152 r->handle = *((uint64_t *)data);
154 case NFTNL_RULE_COMPAT_PROTO:
155 r->compat.proto = *((uint32_t *)data);
157 case NFTNL_RULE_COMPAT_FLAGS:
158 r->compat.flags = *((uint32_t *)data);
160 case NFTNL_RULE_FAMILY:
161 r->family = *((uint32_t *)data);
163 case NFTNL_RULE_POSITION:
164 r->position = *((uint64_t *)data);
166 case NFTNL_RULE_USERDATA:
167 if (r->user.data != NULL)
170 r->user.data = malloc(data_len);
174 memcpy(r->user.data, data, data_len);
175 r->user.len = data_len;
178 r->flags |= (1 << attr);
180 EXPORT_SYMBOL_ALIAS(nftnl_rule_set_data, nft_rule_attr_set_data);
182 void nftnl_rule_set(
struct nftnl_rule *r, uint16_t attr,
const void *data)
184 nftnl_rule_set_data(r, attr, data, nftnl_rule_validate[attr]);
186 EXPORT_SYMBOL_ALIAS(nftnl_rule_set, nft_rule_attr_set);
188 void nftnl_rule_set_u32(
struct nftnl_rule *r, uint16_t attr, uint32_t val)
190 nftnl_rule_set_data(r, attr, &val,
sizeof(uint32_t));
192 EXPORT_SYMBOL_ALIAS(nftnl_rule_set_u32, nft_rule_attr_set_u32);
194 void nftnl_rule_set_u64(
struct nftnl_rule *r, uint16_t attr, uint64_t val)
196 nftnl_rule_set_data(r, attr, &val,
sizeof(uint64_t));
198 EXPORT_SYMBOL_ALIAS(nftnl_rule_set_u64, nft_rule_attr_set_u64);
200 void nftnl_rule_set_str(
struct nftnl_rule *r, uint16_t attr,
const char *str)
202 nftnl_rule_set_data(r, attr, str, strlen(str));
204 EXPORT_SYMBOL_ALIAS(nftnl_rule_set_str, nft_rule_attr_set_str);
206 const void *nftnl_rule_get_data(
const struct nftnl_rule *r, uint16_t attr,
209 if (!(r->flags & (1 << attr)))
213 case NFTNL_RULE_FAMILY:
214 *data_len =
sizeof(uint32_t);
216 case NFTNL_RULE_TABLE:
218 case NFTNL_RULE_CHAIN:
220 case NFTNL_RULE_HANDLE:
221 *data_len =
sizeof(uint64_t);
223 case NFTNL_RULE_COMPAT_PROTO:
224 *data_len =
sizeof(uint32_t);
225 return &r->compat.proto;
226 case NFTNL_RULE_COMPAT_FLAGS:
227 *data_len =
sizeof(uint32_t);
228 return &r->compat.flags;
229 case NFTNL_RULE_POSITION:
230 *data_len =
sizeof(uint64_t);
232 case NFTNL_RULE_USERDATA:
233 *data_len = r->user.len;
238 EXPORT_SYMBOL_ALIAS(nftnl_rule_get_data, nft_rule_attr_get_data);
240 const void *nftnl_rule_get(
const struct nftnl_rule *r, uint16_t attr)
243 return nftnl_rule_get_data(r, attr, &data_len);
245 EXPORT_SYMBOL_ALIAS(nftnl_rule_get, nft_rule_attr_get);
247 const char *nftnl_rule_get_str(
const struct nftnl_rule *r, uint16_t attr)
249 return nftnl_rule_get(r, attr);
251 EXPORT_SYMBOL_ALIAS(nftnl_rule_get_str, nft_rule_attr_get_str);
253 uint32_t nftnl_rule_get_u32(
const struct nftnl_rule *r, uint16_t attr)
256 const uint32_t *val = nftnl_rule_get_data(r, attr, &data_len);
258 nftnl_assert(val, attr, data_len ==
sizeof(uint32_t));
260 return val ? *val : 0;
262 EXPORT_SYMBOL_ALIAS(nftnl_rule_get_u32, nft_rule_attr_get_u32);
264 uint64_t nftnl_rule_get_u64(
const struct nftnl_rule *r, uint16_t attr)
267 const uint64_t *val = nftnl_rule_get_data(r, attr, &data_len);
269 nftnl_assert(val, attr, data_len ==
sizeof(uint64_t));
271 return val ? *val : 0;
273 EXPORT_SYMBOL_ALIAS(nftnl_rule_get_u64, nft_rule_attr_get_u64);
275 uint8_t nftnl_rule_get_u8(
const struct nftnl_rule *r, uint16_t attr)
278 const uint8_t *val = nftnl_rule_get_data(r, attr, &data_len);
280 nftnl_assert(val, attr, data_len ==
sizeof(uint8_t));
282 return val ? *val : 0;
284 EXPORT_SYMBOL_ALIAS(nftnl_rule_get_u8, nft_rule_attr_get_u8);
286 void nftnl_rule_nlmsg_build_payload(
struct nlmsghdr *nlh,
struct nftnl_rule *r)
288 struct nftnl_expr *expr;
289 struct nlattr *nest, *nest2;
291 if (r->flags & (1 << NFTNL_RULE_TABLE))
292 mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, r->table);
293 if (r->flags & (1 << NFTNL_RULE_CHAIN))
294 mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, r->chain);
295 if (r->flags & (1 << NFTNL_RULE_HANDLE))
296 mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(r->handle));
297 if (r->flags & (1 << NFTNL_RULE_POSITION))
298 mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
299 if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
300 mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
304 if (!list_empty(&r->expr_list)) {
305 nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
306 list_for_each_entry(expr, &r->expr_list, head) {
307 nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
308 nftnl_expr_build_payload(nlh, expr);
309 mnl_attr_nest_end(nlh, nest2);
311 mnl_attr_nest_end(nlh, nest);
314 if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) &&
315 r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
317 nest = mnl_attr_nest_start(nlh, NFTA_RULE_COMPAT);
318 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_PROTO,
319 htonl(r->compat.proto));
320 mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_FLAGS,
321 htonl(r->compat.flags));
322 mnl_attr_nest_end(nlh, nest);
325 EXPORT_SYMBOL_ALIAS(nftnl_rule_nlmsg_build_payload, nft_rule_nlmsg_build_payload);
327 void nftnl_rule_add_expr(
struct nftnl_rule *r,
struct nftnl_expr *expr)
329 list_add_tail(&expr->head, &r->expr_list);
331 EXPORT_SYMBOL_ALIAS(nftnl_rule_add_expr, nft_rule_add_expr);
333 static int nftnl_rule_parse_attr_cb(
const struct nlattr *attr,
void *data)
335 const struct nlattr **tb = data;
336 int type = mnl_attr_get_type(attr);
338 if (mnl_attr_type_valid(attr, NFTA_RULE_MAX) < 0)
342 case NFTA_RULE_TABLE:
343 case NFTA_RULE_CHAIN:
344 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
347 case NFTA_RULE_HANDLE:
348 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
351 case NFTA_RULE_COMPAT:
352 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
355 case NFTA_RULE_POSITION:
356 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
359 case NFTA_RULE_USERDATA:
360 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
369 static int nftnl_rule_parse_expr(
struct nlattr *nest,
struct nftnl_rule *r)
371 struct nftnl_expr *expr;
374 mnl_attr_for_each_nested(attr, nest) {
375 if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
378 expr = nftnl_expr_parse(attr);
382 list_add_tail(&expr->head, &r->expr_list);
387 static int nftnl_rule_parse_compat_cb(
const struct nlattr *attr,
void *data)
389 const struct nlattr **tb = data;
390 int type = mnl_attr_get_type(attr);
392 if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0)
396 case NFTA_RULE_COMPAT_PROTO:
397 case NFTA_RULE_COMPAT_FLAGS:
398 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
407 static int nftnl_rule_parse_compat(
struct nlattr *nest,
struct nftnl_rule *r)
409 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {};
411 if (mnl_attr_parse_nested(nest, nftnl_rule_parse_compat_cb, tb) < 0)
414 if (tb[NFTA_RULE_COMPAT_PROTO]) {
416 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO]));
417 r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
419 if (tb[NFTA_RULE_COMPAT_FLAGS]) {
421 ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS]));
422 r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
427 int nftnl_rule_nlmsg_parse(
const struct nlmsghdr *nlh,
struct nftnl_rule *r)
429 struct nlattr *tb[NFTA_RULE_MAX+1] = {};
430 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
433 if (mnl_attr_parse(nlh,
sizeof(*nfg), nftnl_rule_parse_attr_cb, tb) < 0)
436 if (tb[NFTA_RULE_TABLE]) {
438 r->table = strdup(mnl_attr_get_str(tb[NFTA_RULE_TABLE]));
439 r->flags |= (1 << NFTNL_RULE_TABLE);
441 if (tb[NFTA_RULE_CHAIN]) {
443 r->chain = strdup(mnl_attr_get_str(tb[NFTA_RULE_CHAIN]));
444 r->flags |= (1 << NFTNL_RULE_CHAIN);
446 if (tb[NFTA_RULE_HANDLE]) {
447 r->handle = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_HANDLE]));
448 r->flags |= (1 << NFTNL_RULE_HANDLE);
450 if (tb[NFTA_RULE_EXPRESSIONS])
451 ret = nftnl_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r);
452 if (tb[NFTA_RULE_COMPAT])
453 ret = nftnl_rule_parse_compat(tb[NFTA_RULE_COMPAT], r);
454 if (tb[NFTA_RULE_POSITION]) {
455 r->position = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_POSITION]));
456 r->flags |= (1 << NFTNL_RULE_POSITION);
458 if (tb[NFTA_RULE_USERDATA]) {
460 mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
465 r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
467 r->user.data = malloc(r->user.len);
468 if (r->user.data == NULL)
471 memcpy(r->user.data, udata, r->user.len);
472 r->flags |= (1 << NFTNL_RULE_USERDATA);
475 r->family = nfg->nfgen_family;
476 r->flags |= (1 << NFTNL_RULE_FAMILY);
480 EXPORT_SYMBOL_ALIAS(nftnl_rule_nlmsg_parse, nft_rule_nlmsg_parse);
483 int nftnl_jansson_parse_rule(
struct nftnl_rule *r, json_t *tree,
484 struct nftnl_parse_err *err,
487 json_t *root, *array;
488 struct nftnl_expr *e;
489 const char *str = NULL;
494 root = nftnl_jansson_get_node(tree,
"rule", err);
498 if (nftnl_jansson_node_exist(root,
"family")) {
499 if (nftnl_jansson_parse_family(root, &family, err) != 0)
502 nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
505 if (nftnl_jansson_node_exist(root,
"table")) {
506 str = nftnl_jansson_parse_str(root,
"table", err);
510 nftnl_rule_set_str(r, NFTNL_RULE_TABLE, str);
513 if (nftnl_jansson_node_exist(root,
"chain")) {
514 str = nftnl_jansson_parse_str(root,
"chain", err);
518 nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, str);
521 if (nftnl_jansson_node_exist(root,
"handle")) {
522 if (nftnl_jansson_parse_val(root,
"handle", NFTNL_TYPE_U64, &uval64,
526 nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE, uval64);
529 if (nftnl_jansson_node_exist(root,
"compat_proto") ||
530 nftnl_jansson_node_exist(root,
"compat_flags")) {
531 if (nftnl_jansson_parse_val(root,
"compat_proto", NFTNL_TYPE_U32,
535 nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_PROTO, uval32);
537 if (nftnl_jansson_parse_val(root,
"compat_flags", NFTNL_TYPE_U32,
541 nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_FLAGS, uval32);
544 if (nftnl_jansson_node_exist(root,
"position")) {
545 if (nftnl_jansson_parse_val(root,
"position", NFTNL_TYPE_U64,
549 nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, uval64);
552 array = json_object_get(root,
"expr");
554 err->error = NFTNL_PARSE_EMISSINGNODE;
555 err->node_name =
"expr";
559 for (i = 0; i < json_array_size(array); ++i) {
561 e = nftnl_jansson_expr_parse(json_array_get(array, i), err,
566 nftnl_rule_add_expr(r, e);
575 static int nftnl_rule_json_parse(
struct nftnl_rule *r,
const void *json,
576 struct nftnl_parse_err *err,
577 enum nftnl_parse_input input,
585 tree = nftnl_jansson_create_root(json, &error, err, input);
589 ret = nftnl_jansson_parse_rule(r, tree, err, set_list);
591 nftnl_jansson_free_root(tree);
600 int nftnl_mxml_rule_parse(mxml_node_t *tree,
struct nftnl_rule *r,
601 struct nftnl_parse_err *err,
605 struct nftnl_expr *e;
606 const char *table, *chain;
609 family = nftnl_mxml_family_parse(tree,
"family", MXML_DESCEND_FIRST,
610 NFTNL_XML_MAND, err);
612 nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
614 table = nftnl_mxml_str_parse(tree,
"table", MXML_DESCEND_FIRST,
615 NFTNL_XML_MAND, err);
617 nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
619 chain = nftnl_mxml_str_parse(tree,
"chain", MXML_DESCEND_FIRST,
620 NFTNL_XML_MAND, err);
622 nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
624 if (nftnl_mxml_num_parse(tree,
"handle", MXML_DESCEND_FIRST, BASE_DEC,
625 &r->handle, NFTNL_TYPE_U64, NFTNL_XML_MAND, err) >= 0)
626 r->flags |= (1 << NFTNL_RULE_HANDLE);
628 if (nftnl_mxml_num_parse(tree,
"compat_proto", MXML_DESCEND_FIRST,
629 BASE_DEC, &r->compat.proto, NFTNL_TYPE_U32,
630 NFTNL_XML_OPT, err) >= 0)
631 r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
633 if (nftnl_mxml_num_parse(tree,
"compat_flags", MXML_DESCEND_FIRST,
634 BASE_DEC, &r->compat.flags, NFTNL_TYPE_U32,
635 NFTNL_XML_OPT, err) >= 0)
636 r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
638 if (nftnl_rule_is_set(r, NFTNL_RULE_COMPAT_PROTO) !=
639 nftnl_rule_is_set(r, NFTNL_RULE_COMPAT_FLAGS)) {
643 if (nftnl_mxml_num_parse(tree,
"position", MXML_DESCEND_FIRST,
644 BASE_DEC, &r->position, NFTNL_TYPE_U64,
645 NFTNL_XML_OPT, err) >= 0)
646 r->flags |= (1 << NFTNL_RULE_POSITION);
649 for (node = mxmlFindElement(tree, tree,
"expr",
"type",
652 node = mxmlFindElement(node, tree,
"expr",
"type",
653 NULL, MXML_DESCEND)) {
654 e = nftnl_mxml_expr_parse(node, err, set_list);
658 nftnl_rule_add_expr(r, e);
665 static int nftnl_rule_xml_parse(
struct nftnl_rule *r,
const void *xml,
666 struct nftnl_parse_err *err,
667 enum nftnl_parse_input input,
672 mxml_node_t *tree = nftnl_mxml_build_tree(xml,
"rule", err, input);
676 ret = nftnl_mxml_rule_parse(tree, r, err, set_list);
685 static int nftnl_rule_do_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
686 const void *data,
struct nftnl_parse_err *err,
687 enum nftnl_parse_input input)
690 struct nftnl_parse_err perr;
693 case NFTNL_PARSE_XML:
694 ret = nftnl_rule_xml_parse(r, data, &perr, input, NULL);
696 case NFTNL_PARSE_JSON:
697 ret = nftnl_rule_json_parse(r, data, &perr, input, NULL);
709 int nftnl_rule_parse(
struct nftnl_rule *r,
enum nftnl_parse_type type,
710 const char *data,
struct nftnl_parse_err *err)
712 return nftnl_rule_do_parse(r, type, data, err, NFTNL_PARSE_BUFFER);
714 EXPORT_SYMBOL_ALIAS(nftnl_rule_parse, nft_rule_parse);
716 int nftnl_rule_parse_file(
struct nftnl_rule *r,
enum nftnl_parse_type type,
717 FILE *fp,
struct nftnl_parse_err *err)
719 return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE);
721 EXPORT_SYMBOL_ALIAS(nftnl_rule_parse_file, nft_rule_parse_file);
723 static int nftnl_rule_snprintf_json(
char *buf,
size_t size,
725 uint32_t type, uint32_t flags)
727 int ret, len = size, offset = 0;
728 struct nftnl_expr *expr;
730 ret = snprintf(buf, len,
"{\"rule\":{");
731 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
733 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
734 ret = snprintf(buf+offset, len,
"\"family\":\"%s\",",
735 nftnl_family2str(r->family));
736 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
739 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
740 ret = snprintf(buf+offset, len,
"\"table\":\"%s\",",
742 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
745 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
746 ret = snprintf(buf+offset, len,
"\"chain\":\"%s\",",
748 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
750 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
751 ret = snprintf(buf+offset, len,
"\"handle\":%llu,",
752 (
unsigned long long)r->handle);
753 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
756 if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) ||
757 r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
758 ret = snprintf(buf+offset, len,
"\"compat_flags\":%u,"
759 "\"compat_proto\":%u,",
760 r->compat.flags, r->compat.proto);
761 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
764 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
765 ret = snprintf(buf+offset, len,
"\"position\":%"PRIu64
",",
767 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
770 ret = snprintf(buf+offset, len,
"\"expr\":[");
771 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
773 list_for_each_entry(expr, &r->expr_list, head) {
774 ret = snprintf(buf+offset, len,
775 "{\"type\":\"%s\",", expr->ops->name);
776 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
778 ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
779 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
790 ret = snprintf(buf+offset, len,
"},");
791 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
796 ret = snprintf(buf+offset, len,
"]}}");
797 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
802 static int nftnl_rule_snprintf_xml(
char *buf,
size_t size,
804 uint32_t type, uint32_t flags)
806 int ret, len = size, offset = 0;
807 struct nftnl_expr *expr;
809 ret = snprintf(buf, len,
"<rule>");
810 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
812 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
813 ret = snprintf(buf+offset, len,
"<family>%s</family>",
814 nftnl_family2str(r->family));
815 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
818 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
819 ret = snprintf(buf+offset, len,
"<table>%s</table>",
821 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
824 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
825 ret = snprintf(buf+offset, len,
"<chain>%s</chain>",
827 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
829 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
830 ret = snprintf(buf+offset, len,
"<handle>%llu</handle>",
831 (
unsigned long long)r->handle);
832 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
835 if (r->compat.flags != 0 || r->compat.proto != 0) {
836 ret = snprintf(buf+offset, len,
837 "<compat_flags>%u</compat_flags>"
838 "<compat_proto>%u</compat_proto>",
839 r->compat.flags, r->compat.proto);
840 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
843 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
844 ret = snprintf(buf+offset, len,
845 "<position>%"PRIu64
"</position>",
847 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
850 list_for_each_entry(expr, &r->expr_list, head) {
851 ret = snprintf(buf+offset, len,
852 "<expr type=\"%s\">", expr->ops->name);
853 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
855 ret = nftnl_expr_snprintf(buf+offset, len, expr,
857 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
859 ret = snprintf(buf+offset, len,
"</expr>");
860 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
863 ret = snprintf(buf+offset, len,
"</rule>");
864 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
869 static int nftnl_rule_snprintf_default(
char *buf,
size_t size,
871 uint32_t type, uint32_t flags)
873 struct nftnl_expr *expr;
874 int ret, len = size, offset = 0, i;
876 if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
877 ret = snprintf(buf+offset, len,
"%s ",
878 nftnl_family2str(r->family));
879 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
882 if (r->flags & (1 << NFTNL_RULE_TABLE)) {
883 ret = snprintf(buf+offset, len,
"%s ",
885 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
888 if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
889 ret = snprintf(buf+offset, len,
"%s ",
891 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
893 if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
894 ret = snprintf(buf+offset, len,
"%llu ",
895 (
unsigned long long)r->handle);
896 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
899 if (r->flags & (1 << NFTNL_RULE_POSITION)) {
900 ret = snprintf(buf+offset, len,
"%llu ",
901 (
unsigned long long)r->position);
902 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
905 ret = snprintf(buf+offset, len,
"\n");
906 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
908 list_for_each_entry(expr, &r->expr_list, head) {
909 ret = snprintf(buf+offset, len,
" [ %s ", expr->ops->name);
910 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
912 ret = nftnl_expr_snprintf(buf+offset, len, expr,
914 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
916 ret = snprintf(buf+offset, len,
"]\n");
917 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
921 ret = snprintf(buf+offset, len,
" userdata = { ");
922 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
924 for (i = 0; i < r->user.len; i++) {
925 char *c = r->user.data;
927 ret = snprintf(buf+offset, len,
"%c",
928 isalnum(c[i]) ? c[i] : 0);
929 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
932 ret = snprintf(buf+offset, len,
" }\n");
933 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
940 static int nftnl_rule_cmd_snprintf(
char *buf,
size_t size,
942 uint32_t type, uint32_t flags)
944 int ret, len = size, offset = 0;
945 uint32_t inner_flags = flags;
947 inner_flags &= ~NFTNL_OF_EVENT_ANY;
949 ret = nftnl_cmd_header_snprintf(buf + offset, len, cmd, type, flags);
950 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
953 case NFTNL_OUTPUT_DEFAULT:
954 ret = nftnl_rule_snprintf_default(buf+offset, len, r, type,
957 case NFTNL_OUTPUT_XML:
958 ret = nftnl_rule_snprintf_xml(buf+offset, len, r, type,
961 case NFTNL_OUTPUT_JSON:
962 ret = nftnl_rule_snprintf_json(buf+offset, len, r, type,
969 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
971 ret = nftnl_cmd_footer_snprintf(buf + offset, len, cmd, type, flags);
972 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
977 int nftnl_rule_snprintf(
char *buf,
size_t size,
const struct nftnl_rule *r,
978 uint32_t type, uint32_t flags)
980 return nftnl_rule_cmd_snprintf(buf, size, r, nftnl_flag2cmd(flags), type,
983 EXPORT_SYMBOL_ALIAS(nftnl_rule_snprintf, nft_rule_snprintf);
985 static int nftnl_rule_do_snprintf(
char *buf,
size_t size,
const void *r,
986 uint32_t cmd, uint32_t type, uint32_t flags)
988 return nftnl_rule_snprintf(buf, size, r, type, flags);
991 int nftnl_rule_fprintf(FILE *fp,
const struct nftnl_rule *r, uint32_t type,
994 return nftnl_fprintf(fp, r, NFTNL_CMD_UNSPEC, type, flags,
995 nftnl_rule_do_snprintf);
997 EXPORT_SYMBOL_ALIAS(nftnl_rule_fprintf, nft_rule_fprintf);
1000 int (*cb)(
struct nftnl_expr *e,
void *data),
1003 struct nftnl_expr *cur, *tmp;
1006 list_for_each_entry_safe(cur, tmp, &r->expr_list, head) {
1007 ret = cb(cur, data);
1013 EXPORT_SYMBOL_ALIAS(nftnl_expr_foreach, nft_rule_expr_foreach);
1017 struct nftnl_expr *cur;
1029 if (list_empty(&r->expr_list))
1032 iter->cur = list_entry(r->expr_list.next,
struct nftnl_expr,
1037 EXPORT_SYMBOL_ALIAS(nftnl_expr_iter_create, nft_rule_expr_iter_create);
1041 struct nftnl_expr *expr = iter->cur;
1047 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_expr, head);
1048 if (&iter->cur->head == iter->r->expr_list.next)
1053 EXPORT_SYMBOL_ALIAS(nftnl_expr_iter_next, nft_rule_expr_iter_next);
1059 EXPORT_SYMBOL_ALIAS(nftnl_expr_iter_destroy, nft_rule_expr_iter_destroy);
1062 struct list_head list;
1073 INIT_LIST_HEAD(&list->list);
1077 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_alloc, nft_rule_list_alloc);
1083 list_for_each_entry_safe(r, tmp, &list->list, head) {
1089 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_free, nft_rule_list_free);
1093 return list_empty(&list->list);
1095 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_is_empty, nft_rule_list_is_empty);
1099 list_add(&r->head, &list->list);
1101 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_add, nft_rule_list_add);
1105 list_add_tail(&r->head, &list->list);
1107 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_add_tail, nft_rule_list_add_tail);
1109 void nftnl_rule_list_del(
struct nftnl_rule *r)
1113 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_del, nft_rule_list_del);
1122 list_for_each_entry_safe(cur, tmp, &rule_list->list, head) {
1123 ret = cb(cur, data);
1129 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_foreach, nft_rule_list_foreach);
1145 if (nftnl_rule_list_is_empty(l))
1148 iter->cur = list_entry(l->list.next,
struct nftnl_rule, head);
1152 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_iter_create, nft_rule_list_iter_create);
1158 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_iter_cur, nft_rule_list_iter_cur);
1168 iter->cur = list_entry(iter->cur->head.next,
struct nftnl_rule, head);
1169 if (&iter->cur->head == iter->list->list.next)
1174 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_iter_next, nft_rule_list_iter_next);
1180 EXPORT_SYMBOL_ALIAS(nftnl_rule_list_iter_destroy, nft_rule_list_iter_destroy);