diff options
136 files changed, 2389 insertions, 2144 deletions
diff --git a/Make_global.am b/Make_global.am index 44f0762..36a71d3 100644 --- a/Make_global.am +++ b/Make_global.am @@ -18,7 +18,7 @@ # set age to 0. # </snippet> # -LIBVERSION=14:0:3 +LIBVERSION=17:0:6 AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include ${LIBMNL_CFLAGS} ${LIBMXML_CFLAGS} AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN} diff --git a/configure.ac b/configure.ac index c447d7f..b196f81 100644 --- a/configure.ac +++ b/configure.ac @@ -1,13 +1,13 @@ dnl Process this file with autoconf to create configure. -AC_INIT([libnftnl], [1.1.7]) +AC_INIT([libnftnl], [1.2.6]) AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) -AM_INIT_AUTOMAKE([-Wall foreign tar-pax no-dist-gzip dist-bzip2 +AM_INIT_AUTOMAKE([-Wall foreign tar-pax no-dist-gzip dist-xz 1.6 subdir-objects]) dnl kernel style compile messages diff --git a/examples/nft-chain-add.c b/examples/nft-chain-add.c index f711e09..13be982 100644 --- a/examples/nft-chain-add.c +++ b/examples/nft-chain-add.c @@ -101,9 +101,9 @@ int main(int argc, char *argv[]) mnl_nlmsg_batch_next(batch); chain_seq = seq; - nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWCHAIN, family, - NLM_F_CREATE|NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWCHAIN, family, + NLM_F_CREATE | NLM_F_ACK, seq++); nftnl_chain_nlmsg_build_payload(nlh, t); nftnl_chain_free(t); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-chain-del.c b/examples/nft-chain-del.c index bcc714e..3cd483e 100644 --- a/examples/nft-chain-del.c +++ b/examples/nft-chain-del.c @@ -78,9 +78,8 @@ int main(int argc, char *argv[]) mnl_nlmsg_batch_next(batch); chain_seq = seq; - nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELCHAIN, family, - NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELCHAIN, family, NLM_F_ACK, seq++); nftnl_chain_nlmsg_build_payload(nlh, t); nftnl_chain_free(t); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-chain-get.c b/examples/nft-chain-get.c index 8a6ef91..612f58b 100644 --- a/examples/nft-chain-get.c +++ b/examples/nft-chain-get.c @@ -86,15 +86,15 @@ int main(int argc, char *argv[]) perror("OOM"); exit(EXIT_FAILURE); } - nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, - NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, + NLM_F_ACK, seq); nftnl_chain_set_str(t, NFTNL_CHAIN_TABLE, argv[2]); nftnl_chain_set_str(t, NFTNL_CHAIN_NAME, argv[3]); nftnl_chain_nlmsg_build_payload(nlh, t); nftnl_chain_free(t); } else if (argc >= 2) { - nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, + NLM_F_DUMP, seq); } nl = mnl_socket_open(NETLINK_NETFILTER); diff --git a/examples/nft-flowtable-add.c b/examples/nft-flowtable-add.c index 5ca62be..f509f23 100644 --- a/examples/nft-flowtable-add.c +++ b/examples/nft-flowtable-add.c @@ -47,7 +47,6 @@ int main(int argc, char *argv[]) int ret, family; struct nftnl_flowtable *t; struct mnl_nlmsg_batch *batch; - int batching; if (argc != 6) { fprintf(stderr, "Usage: %s <family> <table> <name> <hook> <prio>\n", @@ -74,32 +73,22 @@ int main(int argc, char *argv[]) if (t == NULL) exit(EXIT_FAILURE); - batching = nftnl_batch_is_supported(); - if (batching < 0) { - perror("cannot talk to nfnetlink"); - exit(EXIT_FAILURE); - } - seq = time(NULL); batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); - if (batching) { - nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); - mnl_nlmsg_batch_next(batch); - } + nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); flowtable_seq = seq; - nlh = nftnl_flowtable_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWFLOWTABLE, family, - NLM_F_CREATE|NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWFLOWTABLE, family, + NLM_F_CREATE | NLM_F_ACK, seq++); nftnl_flowtable_nlmsg_build_payload(nlh, t); nftnl_flowtable_free(t); mnl_nlmsg_batch_next(batch); - if (batching) { - nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); - mnl_nlmsg_batch_next(batch); - } + nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { diff --git a/examples/nft-flowtable-del.c b/examples/nft-flowtable-del.c index 91e5d3a..c5ce339 100644 --- a/examples/nft-flowtable-del.c +++ b/examples/nft-flowtable-del.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq, flowtable_seq; struct nftnl_flowtable *t; - int ret, family, batching; + int ret, family; if (argc != 4) { fprintf(stderr, "Usage: %s <family> <table> <flowtable>\n", @@ -60,32 +60,22 @@ int main(int argc, char *argv[]) if (t == NULL) exit(EXIT_FAILURE); - batching = nftnl_batch_is_supported(); - if (batching < 0) { - perror("cannot talk to nfnetlink"); - exit(EXIT_FAILURE); - } - seq = time(NULL); batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); - if (batching) { - nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); - mnl_nlmsg_batch_next(batch); - } + nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); flowtable_seq = seq; - nlh = nftnl_flowtable_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELFLOWTABLE, family, - NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELFLOWTABLE, family, + NLM_F_ACK, seq++); nftnl_flowtable_nlmsg_build_payload(nlh, t); nftnl_flowtable_free(t); mnl_nlmsg_batch_next(batch); - if (batching) { - nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); - mnl_nlmsg_batch_next(batch); - } + nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { diff --git a/examples/nft-flowtable-get.c b/examples/nft-flowtable-get.c index 38929f3..1d10cc8 100644 --- a/examples/nft-flowtable-get.c +++ b/examples/nft-flowtable-get.c @@ -75,15 +75,15 @@ int main(int argc, char *argv[]) perror("OOM"); exit(EXIT_FAILURE); } - nlh = nftnl_flowtable_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, - NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, + NLM_F_ACK, seq); nftnl_flowtable_set_str(t, NFTNL_FLOWTABLE_TABLE, argv[2]); nftnl_flowtable_set_str(t, NFTNL_FLOWTABLE_NAME, argv[3]); nftnl_flowtable_nlmsg_build_payload(nlh, t); nftnl_flowtable_free(t); } else if (argc >= 2) { - nlh = nftnl_flowtable_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, + NLM_F_DUMP, seq); } nl = mnl_socket_open(NETLINK_NETFILTER); diff --git a/examples/nft-map-add.c b/examples/nft-map-add.c index 7c6eeb9..e5ce664 100644 --- a/examples/nft-map-add.c +++ b/examples/nft-map-add.c @@ -103,9 +103,9 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWSET, family, - NLM_F_CREATE|NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWSET, family, + NLM_F_CREATE | NLM_F_ACK, seq++); nftnl_set_nlmsg_build_payload(nlh, s); nftnl_set_free(s); diff --git a/examples/nft-rule-add.c b/examples/nft-rule-add.c index 77ee480..7d13b92 100644 --- a/examples/nft-rule-add.c +++ b/examples/nft-rule-add.c @@ -165,11 +165,11 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWRULE, - nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), - NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); - + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWRULE, + nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), + NLM_F_APPEND | NLM_F_CREATE | NLM_F_ACK, + seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-rule-ct-expectation-add.c b/examples/nft-rule-ct-expectation-add.c index 2012b3c..07c8306 100644 --- a/examples/nft-rule-ct-expectation-add.c +++ b/examples/nft-rule-ct-expectation-add.c @@ -123,12 +123,11 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWRULE, - nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), - NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, - seq++); - + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWRULE, + nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), + NLM_F_APPEND | NLM_F_CREATE | NLM_F_ACK, + seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-rule-ct-helper-add.c b/examples/nft-rule-ct-helper-add.c index e0338a8..594e6ba 100644 --- a/examples/nft-rule-ct-helper-add.c +++ b/examples/nft-rule-ct-helper-add.c @@ -117,11 +117,11 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWRULE, - nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), - NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); - + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWRULE, + nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), + NLM_F_APPEND | NLM_F_CREATE | NLM_F_ACK, + seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-rule-ct-timeout-add.c b/examples/nft-rule-ct-timeout-add.c index d93cde1..0953cb4 100644 --- a/examples/nft-rule-ct-timeout-add.c +++ b/examples/nft-rule-ct-timeout-add.c @@ -117,11 +117,11 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWRULE, - nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), - NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); - + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWRULE, + nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), + NLM_F_APPEND | NLM_F_CREATE | NLM_F_ACK, + seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-rule-del.c b/examples/nft-rule-del.c index 035aaa2..cb085ff 100644 --- a/examples/nft-rule-del.c +++ b/examples/nft-rule-del.c @@ -72,11 +72,8 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELRULE, - family, - NLM_F_ACK, seq++); - + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELRULE, family, NLM_F_ACK, seq++); nftnl_rule_nlmsg_build_payload(nlh, r); nftnl_rule_free(r); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-rule-get.c b/examples/nft-rule-get.c index 8fb654f..8da5b59 100644 --- a/examples/nft-rule-get.c +++ b/examples/nft-rule-get.c @@ -111,8 +111,8 @@ int main(int argc, char *argv[]) } seq = time(NULL); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, + NLM_F_DUMP, seq); r = setup_rule(family, table, chain, NULL); if (!r) { diff --git a/examples/nft-ruleset-get.c b/examples/nft-ruleset-get.c index 7098437..34ebe1f 100644 --- a/examples/nft-ruleset-get.c +++ b/examples/nft-ruleset-get.c @@ -5,9 +5,9 @@ * * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * */ @@ -97,8 +97,8 @@ static struct nftnl_rule_list *mnl_rule_dump(struct mnl_socket *nf_sock, if (nlr_list == NULL) memory_allocation_error(); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, + NLM_F_DUMP, seq); ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, rule_cb, nlr_list); if (ret < 0) @@ -145,8 +145,8 @@ static struct nftnl_chain_list *mnl_chain_dump(struct mnl_socket *nf_sock, if (nlc_list == NULL) memory_allocation_error(); - nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, + NLM_F_DUMP, seq); ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_cb, nlc_list); if (ret < 0) @@ -193,8 +193,8 @@ static struct nftnl_table_list *mnl_table_dump(struct mnl_socket *nf_sock, if (nlt_list == NULL) memory_allocation_error(); - nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, + NLM_F_DUMP, seq); ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, table_cb, nlt_list); if (ret < 0) @@ -221,8 +221,8 @@ static int mnl_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls) struct nlmsghdr *nlh; uint32_t family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY); - nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family, - NLM_F_DUMP|NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family, + NLM_F_DUMP | NLM_F_ACK, seq); nftnl_set_nlmsg_build_payload(nlh, nls); return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_elem_cb, nls); @@ -266,8 +266,8 @@ mnl_set_dump(struct mnl_socket *nf_sock, int family) if (s == NULL) memory_allocation_error(); - nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, - NLM_F_DUMP|NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, + NLM_F_DUMP | NLM_F_ACK, seq); nftnl_set_nlmsg_build_payload(nlh, s); nftnl_set_free(s); diff --git a/examples/nft-set-add.c b/examples/nft-set-add.c index c9e249d..109e33a 100644 --- a/examples/nft-set-add.c +++ b/examples/nft-set-add.c @@ -99,9 +99,9 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWSET, family, - NLM_F_CREATE|NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWSET, family, + NLM_F_CREATE | NLM_F_ACK, seq++); nftnl_set_nlmsg_build_payload(nlh, s); nftnl_set_free(s); diff --git a/examples/nft-set-del.c b/examples/nft-set-del.c index eafd5d7..5e8dea9 100644 --- a/examples/nft-set-del.c +++ b/examples/nft-set-del.c @@ -62,9 +62,8 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELSET, family, - NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELSET, family, NLM_F_ACK, seq); nftnl_set_set_str(t, NFTNL_SET_TABLE, argv[2]); nftnl_set_set_str(t, NFTNL_SET_NAME, argv[3]); diff --git a/examples/nft-set-elem-del.c b/examples/nft-set-elem-del.c index b569fea..1e6c90d 100644 --- a/examples/nft-set-elem-del.c +++ b/examples/nft-set-elem-del.c @@ -87,9 +87,8 @@ int main(int argc, char *argv[]) nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); - nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELSETELEM, family, - NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELSETELEM, family, NLM_F_ACK, seq); nftnl_set_elems_nlmsg_build_payload(nlh, s); nftnl_set_free(s); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-set-elem-get.c b/examples/nft-set-elem-get.c index 52cdd51..7f99a60 100644 --- a/examples/nft-set-elem-get.c +++ b/examples/nft-set-elem-get.c @@ -81,8 +81,8 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family, - NLM_F_DUMP|NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family, + NLM_F_DUMP | NLM_F_ACK, seq); nftnl_set_set_str(t, NFTNL_SET_NAME, argv[3]); nftnl_set_set_str(t, NFTNL_SET_TABLE, argv[2]); nftnl_set_elems_nlmsg_build_payload(nlh, t); diff --git a/examples/nft-set-get.c b/examples/nft-set-get.c index cbe3f85..48a0699 100644 --- a/examples/nft-set-get.c +++ b/examples/nft-set-get.c @@ -83,8 +83,8 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, - NLM_F_DUMP|NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, + NLM_F_DUMP | NLM_F_ACK, seq); /* Use this below if you want to obtain sets per table */ /* nftnl_set_set(t, NFT_SET_TABLE, argv[2]); */ nftnl_set_nlmsg_build_payload(nlh, t); diff --git a/examples/nft-table-add.c b/examples/nft-table-add.c index 5b5c1dd..3d54e0e 100644 --- a/examples/nft-table-add.c +++ b/examples/nft-table-add.c @@ -79,9 +79,9 @@ int main(int argc, char *argv[]) table_seq = seq; family = nftnl_table_get_u32(t, NFTNL_TABLE_FAMILY); - nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWTABLE, family, - NLM_F_CREATE|NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWTABLE, family, + NLM_F_CREATE | NLM_F_ACK, seq++); nftnl_table_nlmsg_build_payload(nlh, t); nftnl_table_free(t); mnl_nlmsg_batch_next(batch); diff --git a/examples/nft-table-del.c b/examples/nft-table-del.c index 3d78fd4..44f0b1f 100644 --- a/examples/nft-table-del.c +++ b/examples/nft-table-del.c @@ -79,9 +79,9 @@ int main(int argc, char *argv[]) table_seq = seq; family = nftnl_table_get_u32(t, NFTNL_TABLE_FAMILY); - nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_DELTABLE, family, - NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELTABLE, family, + NLM_F_ACK, seq++); nftnl_table_nlmsg_build_payload(nlh, t); mnl_nlmsg_batch_next(batch); nftnl_table_free(t); diff --git a/examples/nft-table-get.c b/examples/nft-table-get.c index 64fd66c..58eca9c 100644 --- a/examples/nft-table-get.c +++ b/examples/nft-table-get.c @@ -88,11 +88,11 @@ int main(int argc, char *argv[]) seq = time(NULL); if (t == NULL) { - nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, - NLM_F_DUMP, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, + NLM_F_DUMP, seq); } else { - nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, - NLM_F_ACK, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, + NLM_F_ACK, seq); nftnl_table_set_str(t, NFTNL_TABLE_NAME, argv[2]); nftnl_table_nlmsg_build_payload(nlh, t); nftnl_table_free(t); diff --git a/examples/nft-table-upd.c b/examples/nft-table-upd.c index 663d09f..7346636 100644 --- a/examples/nft-table-upd.c +++ b/examples/nft-table-upd.c @@ -78,9 +78,8 @@ int main(int argc, char *argv[]) nftnl_table_set_u32(t, NFTNL_TABLE_FLAGS, flags); table_seq = seq; - nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - NFT_MSG_NEWTABLE, family, - NLM_F_ACK, seq++); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWTABLE, family, NLM_F_ACK, seq++); nftnl_table_nlmsg_build_payload(nlh, t); nftnl_table_free(t); mnl_nlmsg_batch_next(batch); diff --git a/include/data_reg.h b/include/data_reg.h index d9578aa..946354d 100644 --- a/include/data_reg.h +++ b/include/data_reg.h @@ -13,6 +13,10 @@ enum { DATA_CHAIN, }; +enum { + DATA_F_NOPFX = 1 << 0, +}; + union nftnl_data_reg { struct { uint32_t val[NFT_DATA_VALUE_MAXLEN / sizeof(uint32_t)]; @@ -27,11 +31,10 @@ union nftnl_data_reg { int nftnl_data_reg_snprintf(char *buf, size_t size, const union nftnl_data_reg *reg, - uint32_t output_format, uint32_t flags, - int reg_type); + uint32_t flags, int reg_type); struct nlattr; int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type); -void nftnl_free_verdict(const union nftnl_data_reg *data); +int nftnl_data_cpy(union nftnl_data_reg *dreg, const void *src, uint32_t len); #endif diff --git a/include/expr_ops.h b/include/expr_ops.h index a7f1b9a..6cfb3b5 100644 --- a/include/expr_ops.h +++ b/include/expr_ops.h @@ -8,16 +8,22 @@ struct nlattr; struct nlmsghdr; struct nftnl_expr; +struct attr_policy { + uint32_t maxlen; +}; + struct expr_ops { const char *name; uint32_t alloc_len; - int max_attr; + int nftnl_max_attr; + struct attr_policy *attr_policy; + void (*init)(const struct nftnl_expr *e); void (*free)(const struct nftnl_expr *e); int (*set)(struct nftnl_expr *e, uint16_t type, const void *data, uint32_t data_len); const void *(*get)(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len); int (*parse)(struct nftnl_expr *e, struct nlattr *attr); void (*build)(struct nlmsghdr *nlh, const struct nftnl_expr *e); - int (*snprintf)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_expr *e); + int (*output)(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e); }; struct expr_ops *nftnl_expr_ops_lookup(const char *name); diff --git a/include/libnftnl/chain.h b/include/libnftnl/chain.h index 0e57a5a..bac1f5f 100644 --- a/include/libnftnl/chain.h +++ b/include/libnftnl/chain.h @@ -34,6 +34,7 @@ enum nftnl_chain_attr { NFTNL_CHAIN_DEVICES, NFTNL_CHAIN_FLAGS, NFTNL_CHAIN_ID, + NFTNL_CHAIN_USERDATA, __NFTNL_CHAIN_MAX }; #define NFTNL_CHAIN_MAX (__NFTNL_CHAIN_MAX - 1) @@ -70,10 +71,6 @@ struct nlmsghdr; void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_chain *t); -int nftnl_chain_parse(struct nftnl_chain *c, enum nftnl_parse_type type, - const char *data, struct nftnl_parse_err *err); -int nftnl_chain_parse_file(struct nftnl_chain *c, enum nftnl_parse_type type, - FILE *fp, struct nftnl_parse_err *err); int nftnl_chain_snprintf(char *buf, size_t size, const struct nftnl_chain *t, uint32_t type, uint32_t flags); int nftnl_chain_fprintf(FILE *fp, const struct nftnl_chain *c, uint32_t type, uint32_t flags); diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h index dcbcf5c..fba1210 100644 --- a/include/libnftnl/expr.h +++ b/include/libnftnl/expr.h @@ -36,6 +36,14 @@ uint32_t nftnl_expr_get_u32(const struct nftnl_expr *expr, uint16_t type); uint64_t nftnl_expr_get_u64(const struct nftnl_expr *expr, uint16_t type); const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type); +void nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr); + +/* For dynset expressions. */ +void nftnl_expr_add_expr(struct nftnl_expr *expr, uint32_t type, struct nftnl_expr *e); +int nftnl_expr_expr_foreach(const struct nftnl_expr *e, + int (*cb)(struct nftnl_expr *e, void *data), + void *data); + int nftnl_expr_snprintf(char *buf, size_t buflen, const struct nftnl_expr *expr, uint32_t type, uint32_t flags); int nftnl_expr_fprintf(FILE *fp, const struct nftnl_expr *expr, uint32_t type, uint32_t flags); @@ -48,6 +56,7 @@ enum { NFTNL_EXPR_PAYLOAD_CSUM_TYPE, NFTNL_EXPR_PAYLOAD_CSUM_OFFSET, NFTNL_EXPR_PAYLOAD_FLAGS, + __NFTNL_EXPR_PAYLOAD_MAX }; enum { @@ -57,33 +66,40 @@ enum { NFTNL_EXPR_NG_OFFSET, NFTNL_EXPR_NG_SET_NAME, /* deprecated */ NFTNL_EXPR_NG_SET_ID, /* deprecated */ + __NFTNL_EXPR_NG_MAX }; enum { NFTNL_EXPR_META_KEY = NFTNL_EXPR_BASE, NFTNL_EXPR_META_DREG, NFTNL_EXPR_META_SREG, + __NFTNL_EXPR_META_MAX }; enum { NFTNL_EXPR_RT_KEY = NFTNL_EXPR_BASE, NFTNL_EXPR_RT_DREG, + __NFTNL_EXPR_RT_MAX }; enum { NFTNL_EXPR_SOCKET_KEY = NFTNL_EXPR_BASE, NFTNL_EXPR_SOCKET_DREG, + NFTNL_EXPR_SOCKET_LEVEL, + __NFTNL_EXPR_SOCKET_MAX }; enum { NFTNL_EXPR_TUNNEL_KEY = NFTNL_EXPR_BASE, NFTNL_EXPR_TUNNEL_DREG, + __NFTNL_EXPR_TUNNEL_MAX }; enum { NFTNL_EXPR_CMP_SREG = NFTNL_EXPR_BASE, NFTNL_EXPR_CMP_OP, NFTNL_EXPR_CMP_DATA, + __NFTNL_EXPR_CMP_MAX }; enum { @@ -91,6 +107,7 @@ enum { NFTNL_EXPR_RANGE_OP, NFTNL_EXPR_RANGE_FROM_DATA, NFTNL_EXPR_RANGE_TO_DATA, + __NFTNL_EXPR_RANGE_MAX }; enum { @@ -99,16 +116,19 @@ enum { NFTNL_EXPR_IMM_VERDICT, NFTNL_EXPR_IMM_CHAIN, NFTNL_EXPR_IMM_CHAIN_ID, + __NFTNL_EXPR_IMM_MAX }; enum { NFTNL_EXPR_CTR_PACKETS = NFTNL_EXPR_BASE, NFTNL_EXPR_CTR_BYTES, + __NFTNL_EXPR_CTR_MAX }; enum { NFTNL_EXPR_CONNLIMIT_COUNT = NFTNL_EXPR_BASE, NFTNL_EXPR_CONNLIMIT_FLAGS, + __NFTNL_EXPR_CONNLIMIT_MAX }; enum { @@ -119,18 +139,21 @@ enum { NFTNL_EXPR_BITWISE_XOR, NFTNL_EXPR_BITWISE_OP, NFTNL_EXPR_BITWISE_DATA, + __NFTNL_EXPR_BITWISE_MAX }; enum { NFTNL_EXPR_TG_NAME = NFTNL_EXPR_BASE, NFTNL_EXPR_TG_REV, NFTNL_EXPR_TG_INFO, + __NFTNL_EXPR_TG_MAX }; enum { NFTNL_EXPR_MT_NAME = NFTNL_EXPR_BASE, NFTNL_EXPR_MT_REV, NFTNL_EXPR_MT_INFO, + __NFTNL_EXPR_MT_MAX }; enum { @@ -141,12 +164,14 @@ enum { NFTNL_EXPR_NAT_REG_PROTO_MIN, NFTNL_EXPR_NAT_REG_PROTO_MAX, NFTNL_EXPR_NAT_FLAGS, + __NFTNL_EXPR_NAT_MAX }; enum { NFTNL_EXPR_TPROXY_FAMILY = NFTNL_EXPR_BASE, NFTNL_EXPR_TPROXY_REG_ADDR, NFTNL_EXPR_TPROXY_REG_PORT, + __NFTNL_EXPR_TPROXY_MAX }; enum { @@ -155,6 +180,7 @@ enum { NFTNL_EXPR_LOOKUP_SET, NFTNL_EXPR_LOOKUP_SET_ID, NFTNL_EXPR_LOOKUP_FLAGS, + __NFTNL_EXPR_LOOKUP_MAX }; enum { @@ -165,6 +191,9 @@ enum { NFTNL_EXPR_DYNSET_SET_NAME, NFTNL_EXPR_DYNSET_SET_ID, NFTNL_EXPR_DYNSET_EXPR, + NFTNL_EXPR_DYNSET_EXPRESSIONS, + NFTNL_EXPR_DYNSET_FLAGS, + __NFTNL_EXPR_DYNSET_MAX }; enum { @@ -174,6 +203,7 @@ enum { NFTNL_EXPR_LOG_QTHRESHOLD, NFTNL_EXPR_LOG_LEVEL, NFTNL_EXPR_LOG_FLAGS, + __NFTNL_EXPR_LOG_MAX }; enum { @@ -184,6 +214,7 @@ enum { NFTNL_EXPR_EXTHDR_FLAGS, NFTNL_EXPR_EXTHDR_OP, NFTNL_EXPR_EXTHDR_SREG, + __NFTNL_EXPR_EXTHDR_MAX }; enum { @@ -191,6 +222,7 @@ enum { NFTNL_EXPR_CT_KEY, NFTNL_EXPR_CT_DIR, NFTNL_EXPR_CT_SREG, + __NFTNL_EXPR_CT_MAX }; enum { @@ -199,6 +231,7 @@ enum { NFTNL_EXPR_BYTEORDER_OP, NFTNL_EXPR_BYTEORDER_LEN, NFTNL_EXPR_BYTEORDER_SIZE, + __NFTNL_EXPR_BYTEORDER_MAX }; enum { @@ -207,11 +240,13 @@ enum { NFTNL_EXPR_LIMIT_BURST, NFTNL_EXPR_LIMIT_TYPE, NFTNL_EXPR_LIMIT_FLAGS, + __NFTNL_EXPR_LIMIT_MAX }; enum { NFTNL_EXPR_REJECT_TYPE = NFTNL_EXPR_BASE, NFTNL_EXPR_REJECT_CODE, + __NFTNL_EXPR_REJECT_MAX }; enum { @@ -219,39 +254,46 @@ enum { NFTNL_EXPR_QUEUE_TOTAL, NFTNL_EXPR_QUEUE_FLAGS, NFTNL_EXPR_QUEUE_SREG_QNUM, + __NFTNL_EXPR_QUEUE_MAX }; enum { NFTNL_EXPR_QUOTA_BYTES = NFTNL_EXPR_BASE, NFTNL_EXPR_QUOTA_FLAGS, NFTNL_EXPR_QUOTA_CONSUMED, + __NFTNL_EXPR_QUOTA_MAX }; enum { NFTNL_EXPR_MASQ_FLAGS = NFTNL_EXPR_BASE, NFTNL_EXPR_MASQ_REG_PROTO_MIN, NFTNL_EXPR_MASQ_REG_PROTO_MAX, + __NFTNL_EXPR_MASQ_MAX }; enum { NFTNL_EXPR_REDIR_REG_PROTO_MIN = NFTNL_EXPR_BASE, NFTNL_EXPR_REDIR_REG_PROTO_MAX, NFTNL_EXPR_REDIR_FLAGS, + __NFTNL_EXPR_REDIR_MAX }; enum { NFTNL_EXPR_DUP_SREG_ADDR = NFTNL_EXPR_BASE, NFTNL_EXPR_DUP_SREG_DEV, + __NFTNL_EXPR_DUP_MAX }; enum { NFTNL_EXPR_FLOW_TABLE_NAME = NFTNL_EXPR_BASE, + __NFTNL_EXPR_FLOW_MAX }; enum { NFTNL_EXPR_FWD_SREG_DEV = NFTNL_EXPR_BASE, NFTNL_EXPR_FWD_SREG_ADDR, NFTNL_EXPR_FWD_NFPROTO, + __NFTNL_EXPR_FWD_MAX }; enum { @@ -264,12 +306,14 @@ enum { NFTNL_EXPR_HASH_TYPE, NFTNL_EXPR_HASH_SET_NAME, /* deprecated */ NFTNL_EXPR_HASH_SET_ID, /* deprecated */ + __NFTNL_EXPR_HASH_MAX }; enum { NFTNL_EXPR_FIB_DREG = NFTNL_EXPR_BASE, NFTNL_EXPR_FIB_RESULT, NFTNL_EXPR_FIB_FLAGS, + __NFTNL_EXPR_FIB_MAX }; enum { @@ -278,12 +322,14 @@ enum { NFTNL_EXPR_OBJREF_SET_SREG, NFTNL_EXPR_OBJREF_SET_NAME, NFTNL_EXPR_OBJREF_SET_ID, + __NFTNL_EXPR_OBJREF_MAX }; enum { NFTNL_EXPR_OSF_DREG = NFTNL_EXPR_BASE, NFTNL_EXPR_OSF_TTL, NFTNL_EXPR_OSF_FLAGS, + __NFTNL_EXPR_OSF_MAX }; enum { @@ -292,12 +338,28 @@ enum { NFTNL_EXPR_XFRM_KEY, NFTNL_EXPR_XFRM_DIR, NFTNL_EXPR_XFRM_SPNUM, + __NFTNL_EXPR_XFRM_MAX }; enum { NFTNL_EXPR_SYNPROXY_MSS = NFTNL_EXPR_BASE, NFTNL_EXPR_SYNPROXY_WSCALE, NFTNL_EXPR_SYNPROXY_FLAGS, + __NFTNL_EXPR_SYNPROXY_MAX +}; + +enum { + NFTNL_EXPR_LAST_MSECS = NFTNL_EXPR_BASE, + NFTNL_EXPR_LAST_SET, + __NFTNL_EXPR_LAST_MAX +}; + +enum { + NFTNL_EXPR_INNER_TYPE = NFTNL_EXPR_BASE, + NFTNL_EXPR_INNER_FLAGS, + NFTNL_EXPR_INNER_HDRSIZE, + NFTNL_EXPR_INNER_EXPR, + __NFTNL_EXPR_INNER_MAX }; #ifdef __cplusplus diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h index 4c23774..9930355 100644 --- a/include/libnftnl/object.h +++ b/include/libnftnl/object.h @@ -19,6 +19,7 @@ enum { NFTNL_OBJ_FAMILY, NFTNL_OBJ_USE, NFTNL_OBJ_HANDLE, + NFTNL_OBJ_USERDATA, NFTNL_OBJ_BASE = 16, __NFTNL_OBJ_MAX }; @@ -27,18 +28,21 @@ enum { enum { NFTNL_OBJ_CTR_PKTS = NFTNL_OBJ_BASE, NFTNL_OBJ_CTR_BYTES, + __NFTNL_OBJ_CTR_MAX, }; enum { NFTNL_OBJ_QUOTA_BYTES = NFTNL_OBJ_BASE, NFTNL_OBJ_QUOTA_CONSUMED, NFTNL_OBJ_QUOTA_FLAGS, + __NFTNL_OBJ_QUOTA_MAX, }; enum { NFTNL_OBJ_CT_HELPER_NAME = NFTNL_OBJ_BASE, NFTNL_OBJ_CT_HELPER_L3PROTO, NFTNL_OBJ_CT_HELPER_L4PROTO, + __NFTNL_OBJ_CT_HELPER_MAX, }; enum nftnl_cttimeout_array_tcp { @@ -68,6 +72,7 @@ enum { NFTNL_OBJ_CT_TIMEOUT_L3PROTO = NFTNL_OBJ_BASE, NFTNL_OBJ_CT_TIMEOUT_L4PROTO, NFTNL_OBJ_CT_TIMEOUT_ARRAY, + __NFTNL_OBJ_CT_TIMEOUT_MAX, }; enum { @@ -76,6 +81,7 @@ enum { NFTNL_OBJ_CT_EXPECT_DPORT, NFTNL_OBJ_CT_EXPECT_TIMEOUT, NFTNL_OBJ_CT_EXPECT_SIZE, + __NFTNL_OBJ_CT_EXPECT_MAX, }; enum { @@ -84,12 +90,14 @@ enum { NFTNL_OBJ_LIMIT_BURST, NFTNL_OBJ_LIMIT_TYPE, NFTNL_OBJ_LIMIT_FLAGS, + __NFTNL_OBJ_LIMIT_MAX, }; enum { NFTNL_OBJ_SYNPROXY_MSS = NFTNL_OBJ_BASE, NFTNL_OBJ_SYNPROXY_WSCALE, NFTNL_OBJ_SYNPROXY_FLAGS, + __NFTNL_OBJ_SYNPROXY_MAX, }; enum { @@ -109,10 +117,12 @@ enum { NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX, NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID, NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR, + __NFTNL_OBJ_TUNNEL_MAX, }; enum { NFTNL_OBJ_SECMARK_CTX = NFTNL_OBJ_BASE, + __NFTNL_OBJ_SECMARK_MAX, }; struct nftnl_obj; @@ -122,22 +132,22 @@ void nftnl_obj_free(const struct nftnl_obj *ne); bool nftnl_obj_is_set(const struct nftnl_obj *ne, uint16_t attr); void nftnl_obj_unset(struct nftnl_obj *ne, uint16_t attr); -void nftnl_obj_set_data(struct nftnl_obj *ne, uint16_t attr, const void *data, - uint32_t data_len); +int nftnl_obj_set_data(struct nftnl_obj *ne, uint16_t attr, const void *data, + uint32_t data_len); void nftnl_obj_set(struct nftnl_obj *ne, uint16_t attr, const void *data) __attribute__((deprecated)); -void nftnl_obj_set_u8(struct nftnl_obj *ne, uint16_t attr, uint8_t val); -void nftnl_obj_set_u16(struct nftnl_obj *ne, uint16_t attr, uint16_t val); -void nftnl_obj_set_u32(struct nftnl_obj *ne, uint16_t attr, uint32_t val); -void nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val); -void nftnl_obj_set_str(struct nftnl_obj *ne, uint16_t attr, const char *str); -const void *nftnl_obj_get_data(struct nftnl_obj *ne, uint16_t attr, +int nftnl_obj_set_u8(struct nftnl_obj *ne, uint16_t attr, uint8_t val); +int nftnl_obj_set_u16(struct nftnl_obj *ne, uint16_t attr, uint16_t val); +int nftnl_obj_set_u32(struct nftnl_obj *ne, uint16_t attr, uint32_t val); +int nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val); +int nftnl_obj_set_str(struct nftnl_obj *ne, uint16_t attr, const char *str); +const void *nftnl_obj_get_data(const struct nftnl_obj *ne, uint16_t attr, uint32_t *data_len); -const void *nftnl_obj_get(struct nftnl_obj *ne, uint16_t attr); -uint8_t nftnl_obj_get_u8(struct nftnl_obj *ne, uint16_t attr); -uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr); -uint32_t nftnl_obj_get_u32(struct nftnl_obj *ne, uint16_t attr); -uint64_t nftnl_obj_get_u64(struct nftnl_obj *obj, uint16_t attr); -const char *nftnl_obj_get_str(struct nftnl_obj *ne, uint16_t attr); +const void *nftnl_obj_get(const struct nftnl_obj *ne, uint16_t attr); +uint8_t nftnl_obj_get_u8(const struct nftnl_obj *ne, uint16_t attr); +uint16_t nftnl_obj_get_u16(const struct nftnl_obj *obj, uint16_t attr); +uint32_t nftnl_obj_get_u32(const struct nftnl_obj *ne, uint16_t attr); +uint64_t nftnl_obj_get_u64(const struct nftnl_obj *obj, uint16_t attr); +const char *nftnl_obj_get_str(const struct nftnl_obj *ne, uint16_t attr); void nftnl_obj_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_obj *ne); diff --git a/include/libnftnl/rule.h b/include/libnftnl/rule.h index e5d1ca0..b6b93c6 100644 --- a/include/libnftnl/rule.h +++ b/include/libnftnl/rule.h @@ -51,6 +51,7 @@ uint32_t nftnl_rule_get_u32(const struct nftnl_rule *r, uint16_t attr); uint64_t nftnl_rule_get_u64(const struct nftnl_rule *r, uint16_t attr); void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr); +void nftnl_rule_del_expr(struct nftnl_expr *expr); struct nlmsghdr; diff --git a/include/libnftnl/set.h b/include/libnftnl/set.h index 961ce5d..e2e5795 100644 --- a/include/libnftnl/set.h +++ b/include/libnftnl/set.h @@ -31,6 +31,7 @@ enum nftnl_set_attr { NFTNL_SET_HANDLE, NFTNL_SET_DESC_CONCAT, NFTNL_SET_EXPR, + NFTNL_SET_EXPRESSIONS, __NFTNL_SET_MAX }; #define NFTNL_SET_MAX (__NFTNL_SET_MAX - 1) @@ -80,6 +81,12 @@ int nftnl_set_list_foreach(struct nftnl_set_list *set_list, int (*cb)(struct nft struct nftnl_set *nftnl_set_list_lookup_byname(struct nftnl_set_list *set_list, const char *set); +struct nftnl_expr; +void nftnl_set_add_expr(struct nftnl_set *s, struct nftnl_expr *expr); +int nftnl_set_expr_foreach(const struct nftnl_set *s, + int (*cb)(struct nftnl_expr *e, void *data), + void *data); + struct nftnl_set_list_iter; struct nftnl_set_list_iter *nftnl_set_list_iter_create(const struct nftnl_set_list *l); struct nftnl_set *nftnl_set_list_iter_cur(const struct nftnl_set_list_iter *iter); @@ -107,6 +114,7 @@ enum { NFTNL_SET_ELEM_EXPR, NFTNL_SET_ELEM_OBJREF, NFTNL_SET_ELEM_KEY_END, + NFTNL_SET_ELEM_EXPRESSIONS, __NFTNL_SET_ELEM_MAX }; #define NFTNL_SET_ELEM_MAX (__NFTNL_SET_ELEM_MAX - 1) @@ -136,6 +144,8 @@ bool nftnl_set_elem_is_set(const struct nftnl_set_elem *s, uint16_t attr); #define nftnl_set_elem_nlmsg_build_hdr nftnl_nlmsg_build_hdr void nftnl_set_elems_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s); void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set_elem *e); +struct nlattr *nftnl_set_elem_nlmsg_build(struct nlmsghdr *nlh, + struct nftnl_set_elem *elem, int i); int nftnl_set_elem_parse(struct nftnl_set_elem *e, enum nftnl_parse_type type, const char *data, struct nftnl_parse_err *err); @@ -144,6 +154,12 @@ int nftnl_set_elem_parse_file(struct nftnl_set_elem *e, enum nftnl_parse_type ty int nftnl_set_elem_snprintf(char *buf, size_t size, const struct nftnl_set_elem *s, uint32_t type, uint32_t flags); int nftnl_set_elem_fprintf(FILE *fp, const struct nftnl_set_elem *se, uint32_t type, uint32_t flags); +struct nftnl_expr; +void nftnl_set_elem_add_expr(struct nftnl_set_elem *e, struct nftnl_expr *expr); +int nftnl_set_elem_expr_foreach(struct nftnl_set_elem *e, + int (*cb)(struct nftnl_expr *e, void *data), + void *data); + int nftnl_set_elem_foreach(struct nftnl_set *s, int (*cb)(struct nftnl_set_elem *e, void *data), void *data); struct nftnl_set_elems_iter; diff --git a/include/libnftnl/table.h b/include/libnftnl/table.h index a37fba2..d28c375 100644 --- a/include/libnftnl/table.h +++ b/include/libnftnl/table.h @@ -24,6 +24,7 @@ enum nftnl_table_attr { NFTNL_TABLE_USE, NFTNL_TABLE_HANDLE, NFTNL_TABLE_USERDATA, + NFTNL_TABLE_OWNER, __NFTNL_TABLE_MAX }; #define NFTNL_TABLE_MAX (__NFTNL_TABLE_MAX - 1) diff --git a/include/libnftnl/udata.h b/include/libnftnl/udata.h index ba6b3ab..dbf3a60 100644 --- a/include/libnftnl/udata.h +++ b/include/libnftnl/udata.h @@ -15,6 +15,12 @@ enum nftnl_udata_table_types { }; #define NFTNL_UDATA_TABLE_MAX (__NFTNL_UDATA_TABLE_MAX - 1) +enum nftnl_udata_chain_types { + NFTNL_UDATA_CHAIN_COMMENT, + __NFTNL_UDATA_CHAIN_MAX +}; +#define NFTNL_UDATA_CHAIN_MAX (__NFTNL_UDATA_CHAIN_MAX - 1) + enum nftnl_udata_rule_types { NFTNL_UDATA_RULE_COMMENT, NFTNL_UDATA_RULE_EBTABLES_POLICY, @@ -22,6 +28,12 @@ enum nftnl_udata_rule_types { }; #define NFTNL_UDATA_RULE_MAX (__NFTNL_UDATA_RULE_MAX - 1) +enum nftnl_udata_obj_types { + NFTNL_UDATA_OBJ_COMMENT, + __NFTNL_UDATA_OBJ_MAX +}; +#define NFTNL_UDATA_OBJ_MAX (__NFTNL_UDATA_OBJ_MAX - 1) + #define NFTNL_UDATA_COMMENT_MAXLEN 128 enum nftnl_udata_set_types { diff --git a/include/linux/netfilter/nf_log.h b/include/linux/netfilter/nf_log.h index 8be21e0..2ae0093 100644 --- a/include/linux/netfilter/nf_log.h +++ b/include/linux/netfilter/nf_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NETFILTER_NF_LOG_H #define _NETFILTER_NF_LOG_H @@ -9,4 +10,6 @@ #define NF_LOG_MACDECODE 0x20 /* Decode MAC header */ #define NF_LOG_MASK 0x2f +#define NF_LOG_PREFIXLEN 128 + #endif /* _NETFILTER_NF_LOG_H */ diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index d508154..c48b193 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -133,7 +133,7 @@ enum nf_tables_msg_types { * @NFTA_LIST_ELEM: list element (NLA_NESTED) */ enum nft_list_attributes { - NFTA_LIST_UNPEC, + NFTA_LIST_UNSPEC, NFTA_LIST_ELEM, __NFTA_LIST_MAX }; @@ -164,7 +164,10 @@ enum nft_hook_attributes { */ enum nft_table_flags { NFT_TABLE_F_DORMANT = 0x1, + NFT_TABLE_F_OWNER = 0x2, }; +#define NFT_TABLE_F_MASK (NFT_TABLE_F_DORMANT | \ + NFT_TABLE_F_OWNER) /** * enum nft_table_attributes - nf_tables table netlink attributes @@ -172,6 +175,8 @@ enum nft_table_flags { * @NFTA_TABLE_NAME: name of the table (NLA_STRING) * @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32) * @NFTA_TABLE_USE: number of chains in this table (NLA_U32) + * @NFTA_TABLE_USERDATA: user data (NLA_BINARY) + * @NFTA_TABLE_OWNER: owner of this table through netlink portID (NLA_U32) */ enum nft_table_attributes { NFTA_TABLE_UNSPEC, @@ -181,10 +186,20 @@ enum nft_table_attributes { NFTA_TABLE_HANDLE, NFTA_TABLE_PAD, NFTA_TABLE_USERDATA, + NFTA_TABLE_OWNER, __NFTA_TABLE_MAX }; #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) +enum nft_chain_flags { + NFT_CHAIN_BASE = (1 << 0), + NFT_CHAIN_HW_OFFLOAD = (1 << 1), + NFT_CHAIN_BINDING = (1 << 2), +}; +#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | \ + NFT_CHAIN_HW_OFFLOAD | \ + NFT_CHAIN_BINDING) + /** * enum nft_chain_attributes - nf_tables chain netlink attributes * @@ -197,6 +212,8 @@ enum nft_table_attributes { * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING) * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes) * @NFTA_CHAIN_FLAGS: chain flags + * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32) + * @NFTA_CHAIN_USERDATA: user data (NLA_BINARY) */ enum nft_chain_attributes { NFTA_CHAIN_UNSPEC, @@ -211,6 +228,7 @@ enum nft_chain_attributes { NFTA_CHAIN_PAD, NFTA_CHAIN_FLAGS, NFTA_CHAIN_ID, + NFTA_CHAIN_USERDATA, __NFTA_CHAIN_MAX }; #define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1) @@ -240,6 +258,7 @@ enum nft_rule_attributes { NFTA_RULE_PAD, NFTA_RULE_ID, NFTA_RULE_POSITION_ID, + NFTA_RULE_CHAIN_ID, __NFTA_RULE_MAX }; #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) @@ -278,6 +297,8 @@ enum nft_rule_compat_attributes { * @NFT_SET_TIMEOUT: set uses timeouts * @NFT_SET_EVAL: set can be updated from the evaluation path * @NFT_SET_OBJECT: set contains stateful objects + * @NFT_SET_CONCAT: set contains a concatenation + * @NFT_SET_EXPR: set contains expressions */ enum nft_set_flags { NFT_SET_ANONYMOUS = 0x1, @@ -287,6 +308,8 @@ enum nft_set_flags { NFT_SET_TIMEOUT = 0x10, NFT_SET_EVAL = 0x20, NFT_SET_OBJECT = 0x40, + NFT_SET_CONCAT = 0x80, + NFT_SET_EXPR = 0x100, }; /** @@ -345,6 +368,7 @@ enum nft_set_field_attributes { * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) * @NFTA_SET_HANDLE: set handle (NLA_U64) * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes) + * @NFTA_SET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_set_attributes { NFTA_SET_UNSPEC, @@ -365,6 +389,7 @@ enum nft_set_attributes { NFTA_SET_OBJ_TYPE, NFTA_SET_HANDLE, NFTA_SET_EXPR, + NFTA_SET_EXPRESSIONS, __NFTA_SET_MAX }; #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) @@ -373,9 +398,11 @@ enum nft_set_attributes { * enum nft_set_elem_flags - nf_tables set element flags * * @NFT_SET_ELEM_INTERVAL_END: element ends the previous interval + * @NFT_SET_ELEM_CATCHALL: special catch-all element */ enum nft_set_elem_flags { NFT_SET_ELEM_INTERVAL_END = 0x1, + NFT_SET_ELEM_CATCHALL = 0x2, }; /** @@ -390,6 +417,7 @@ enum nft_set_elem_flags { * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING) * @NFTA_SET_ELEM_KEY_END: closing key value (NLA_NESTED: nft_data) + * @NFTA_SET_ELEM_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_set_elem_attributes { NFTA_SET_ELEM_UNSPEC, @@ -403,6 +431,7 @@ enum nft_set_elem_attributes { NFTA_SET_ELEM_PAD, NFTA_SET_ELEM_OBJREF, NFTA_SET_ELEM_KEY_END, + NFTA_SET_ELEM_EXPRESSIONS, __NFTA_SET_ELEM_MAX }; #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) @@ -468,6 +497,7 @@ enum nft_data_attributes { * * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts) * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING) + * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32) */ enum nft_verdict_attributes { NFTA_VERDICT_UNSPEC, @@ -685,6 +715,7 @@ enum nft_dynset_ops { enum nft_dynset_flags { NFT_DYNSET_F_INV = (1 << 0), + NFT_DYNSET_F_EXPR = (1 << 1), }; /** @@ -698,6 +729,7 @@ enum nft_dynset_flags { * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64) * @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @NFTA_DYNSET_FLAGS: flags (NLA_U32) + * @NFTA_DYNSET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_dynset_attributes { NFTA_DYNSET_UNSPEC, @@ -710,6 +742,7 @@ enum nft_dynset_attributes { NFTA_DYNSET_EXPR, NFTA_DYNSET_PAD, NFTA_DYNSET_FLAGS, + NFTA_DYNSET_EXPRESSIONS, __NFTA_DYNSET_MAX, }; #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1) @@ -720,11 +753,14 @@ enum nft_dynset_attributes { * @NFT_PAYLOAD_LL_HEADER: link layer header * @NFT_PAYLOAD_NETWORK_HEADER: network header * @NFT_PAYLOAD_TRANSPORT_HEADER: transport header + * @NFT_PAYLOAD_INNER_HEADER: inner header / payload */ enum nft_payload_bases { NFT_PAYLOAD_LL_HEADER, NFT_PAYLOAD_NETWORK_HEADER, NFT_PAYLOAD_TRANSPORT_HEADER, + NFT_PAYLOAD_INNER_HEADER, + NFT_PAYLOAD_TUN_HEADER, }; /** @@ -732,16 +768,43 @@ enum nft_payload_bases { * * @NFT_PAYLOAD_CSUM_NONE: no checksumming * @NFT_PAYLOAD_CSUM_INET: internet checksum (RFC 791) + * @NFT_PAYLOAD_CSUM_SCTP: CRC-32c, for use in SCTP header (RFC 3309) */ enum nft_payload_csum_types { NFT_PAYLOAD_CSUM_NONE, NFT_PAYLOAD_CSUM_INET, + NFT_PAYLOAD_CSUM_SCTP, }; enum nft_payload_csum_flags { NFT_PAYLOAD_L4CSUM_PSEUDOHDR = (1 << 0), }; +enum nft_inner_type { + NFT_INNER_UNSPEC = 0, + NFT_INNER_VXLAN, +}; + +enum nft_inner_flags { + NFT_INNER_HDRSIZE = (1 << 0), + NFT_INNER_LL = (1 << 1), + NFT_INNER_NH = (1 << 2), + NFT_INNER_TH = (1 << 3), +}; +#define NFT_INNER_MASK (NFT_INNER_HDRSIZE | NFT_INNER_LL | \ + NFT_INNER_NH | NFT_INNER_TH) + +enum nft_inner_attributes { + NFTA_INNER_UNSPEC, + NFTA_INNER_NUM, + NFTA_INNER_TYPE, + NFTA_INNER_FLAGS, + NFTA_INNER_HDRSIZE, + NFTA_INNER_EXPR, + __NFTA_INNER_MAX +}; +#define NFTA_INNER_MAX (__NFTA_INNER_MAX - 1) + /** * enum nft_payload_attributes - nf_tables payload expression netlink attributes * @@ -778,11 +841,13 @@ enum nft_exthdr_flags { * @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers * @NFT_EXTHDR_OP_TCP: match against tcp options * @NFT_EXTHDR_OP_IPV4: match against ipv4 options + * @NFT_EXTHDR_OP_SCTP: match against sctp chunks */ enum nft_exthdr_op { NFT_EXTHDR_OP_IPV6, NFT_EXTHDR_OP_TCPOPT, NFT_EXTHDR_OP_IPV4, + NFT_EXTHDR_OP_SCTP, __NFT_EXTHDR_OP_MAX }; #define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1) @@ -849,6 +914,7 @@ enum nft_exthdr_attributes { * @NFT_META_TIME_HOUR: hour of day (in seconds) * @NFT_META_SDIF: slave device interface index * @NFT_META_SDIFNAME: slave device interface name + * @NFT_META_BRI_BROUTE: packet br_netfilter_broute bit */ enum nft_meta_keys { NFT_META_LEN, @@ -859,7 +925,8 @@ enum nft_meta_keys { NFT_META_OIF, NFT_META_IIFNAME, NFT_META_OIFNAME, - NFT_META_IIFTYPE, + NFT_META_IFTYPE, +#define NFT_META_IIFTYPE NFT_META_IFTYPE NFT_META_OIFTYPE, NFT_META_SKUID, NFT_META_SKGID, @@ -886,6 +953,8 @@ enum nft_meta_keys { NFT_META_TIME_HOUR, NFT_META_SDIF, NFT_META_SDIFNAME, + NFT_META_BRI_BROUTE, + __NFT_META_IIFTYPE, }; /** @@ -981,11 +1050,13 @@ enum nft_rt_attributes { * * @NFTA_SOCKET_KEY: socket key to match * @NFTA_SOCKET_DREG: destination register + * @NFTA_SOCKET_LEVEL: cgroups2 ancestor level (only for cgroupsv2) */ enum nft_socket_attributes { NFTA_SOCKET_UNSPEC, NFTA_SOCKET_KEY, NFTA_SOCKET_DREG, + NFTA_SOCKET_LEVEL, __NFTA_SOCKET_MAX }; #define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1) @@ -995,10 +1066,14 @@ enum nft_socket_attributes { * * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option * @NFT_SOCKET_MARK: Value of the socket mark + * @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0) + * @NFT_SOCKET_CGROUPV2: Match on cgroups version 2 */ enum nft_socket_keys { NFT_SOCKET_TRANSPARENT, NFT_SOCKET_MARK, + NFT_SOCKET_WILDCARD, + NFT_SOCKET_CGROUPV2, __NFT_SOCKET_MAX }; #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) @@ -1153,6 +1228,21 @@ enum nft_counter_attributes { #define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1) /** + * enum nft_last_attributes - nf_tables last expression netlink attributes + * + * @NFTA_LAST_SET: last update has been set, zero means never updated (NLA_U32) + * @NFTA_LAST_MSECS: milliseconds since last update (NLA_U64) + */ +enum nft_last_attributes { + NFTA_LAST_UNSPEC, + NFTA_LAST_SET, + NFTA_LAST_MSECS, + NFTA_LAST_PAD, + __NFTA_LAST_MAX +}; +#define NFTA_LAST_MAX (__NFTA_LAST_MAX - 1) + +/** * enum nft_log_attributes - nf_tables log expression netlink attributes * * @NFTA_LOG_GROUP: netlink group to send messages to (NLA_U32) @@ -1542,6 +1632,7 @@ enum nft_ct_expectation_attributes { * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) * @NFTA_OBJ_HANDLE: object handle (NLA_U64) + * @NFTA_OBJ_USERDATA: user data (NLA_BINARY) */ enum nft_object_attributes { NFTA_OBJ_UNSPEC, @@ -1552,6 +1643,7 @@ enum nft_object_attributes { NFTA_OBJ_USE, NFTA_OBJ_HANDLE, NFTA_OBJ_PAD, + NFTA_OBJ_USERDATA, __NFTA_OBJ_MAX }; #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) diff --git a/include/obj.h b/include/obj.h index 10f806c..d217737 100644 --- a/include/obj.h +++ b/include/obj.h @@ -22,6 +22,11 @@ struct nftnl_obj { uint32_t flags; uint64_t handle; + struct { + void *data; + uint32_t len; + } user; + union { struct nftnl_obj_counter { uint64_t pkts; @@ -99,12 +104,13 @@ struct obj_ops { const char *name; uint32_t type; size_t alloc_len; - int max_attr; + int nftnl_max_attr; + struct attr_policy *attr_policy; int (*set)(struct nftnl_obj *e, uint16_t type, const void *data, uint32_t data_len); const void *(*get)(const struct nftnl_obj *e, uint16_t type, uint32_t *data_len); int (*parse)(struct nftnl_obj *e, struct nlattr *attr); void (*build)(struct nlmsghdr *nlh, const struct nftnl_obj *e); - int (*snprintf)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_obj *e); + int (*output)(char *buf, size_t len, uint32_t flags, const struct nftnl_obj *e); }; extern struct obj_ops obj_ops_counter; diff --git a/include/set.h b/include/set.h index 66ac129..55018b6 100644 --- a/include/set.h +++ b/include/set.h @@ -33,7 +33,7 @@ struct nftnl_set { uint32_t flags; uint32_t gc_interval; uint64_t timeout; - struct nftnl_expr *expr; + struct list_head expr_list; }; struct nftnl_set_list; diff --git a/include/set_elem.h b/include/set_elem.h index 52f185a..7628005 100644 --- a/include/set_elem.h +++ b/include/set_elem.h @@ -10,7 +10,7 @@ struct nftnl_set_elem { union nftnl_data_reg key; union nftnl_data_reg key_end; union nftnl_data_reg data; - struct nftnl_expr *expr; + struct list_head expr_list; uint64_t timeout; uint64_t expiration; const char *objref; @@ -20,4 +20,7 @@ struct nftnl_set_elem { } user; }; +int nftnl_set_elem_snprintf_default(char *buf, size_t size, + const struct nftnl_set_elem *e); + #endif diff --git a/include/utils.h b/include/utils.h index 8af5a8e..eed6127 100644 --- a/include/utils.h +++ b/include/utils.h @@ -37,9 +37,9 @@ void __nftnl_assert_fail(uint16_t attr, const char *filename, int line); #define nftnl_assert_validate(data, _validate_array, _attr, _data_len) \ ({ \ if (!data) \ - __nftnl_assert_fail(attr, __FILE__, __LINE__); \ + __nftnl_assert_fail(_attr, __FILE__, __LINE__); \ if (_validate_array[_attr]) \ - nftnl_assert(data, attr, _validate_array[_attr] == _data_len); \ + nftnl_assert(data, _attr, _validate_array[_attr] == _data_len); \ }) void __nftnl_assert_attr_exists(uint16_t attr, uint16_t attr_max, @@ -68,27 +68,8 @@ void __nftnl_assert_attr_exists(uint16_t attr, uint16_t attr_max, #define array_size(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) const char *nftnl_family2str(uint32_t family); -int nftnl_str2family(const char *family); - -enum nftnl_type { - NFTNL_TYPE_U8, - NFTNL_TYPE_U16, - NFTNL_TYPE_U32, - NFTNL_TYPE_U64, - NFTNL_TYPE_S8, - NFTNL_TYPE_S16, - NFTNL_TYPE_S32, - NFTNL_TYPE_S64, -}; - -int nftnl_strtoi(const char *string, int base, void *number, enum nftnl_type type); -int nftnl_get_value(enum nftnl_type type, void *val, void *out); const char *nftnl_verdict2str(uint32_t verdict); -int nftnl_str2verdict(const char *verdict, int *verdict_num); - -const char *nftnl_cmd2tag(enum nftnl_cmd_type cmd); -uint32_t nftnl_str2cmd(const char *cmd); enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags); @@ -98,4 +79,7 @@ int nftnl_fprintf(FILE *fpconst, const void *obj, uint32_t cmd, uint32_t type, uint32_t cmd, uint32_t type, uint32_t flags)); +int nftnl_set_str_attr(const char **dptr, uint32_t *flags, + uint16_t attr, const void *data, uint32_t data_len); + #endif diff --git a/src/Makefile.am b/src/Makefile.am index 90b1967..3cd259c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,11 +34,13 @@ libnftnl_la_SOURCES = utils.c \ expr/flow_offload.c \ expr/fib.c \ expr/fwd.c \ + expr/last.c \ expr/limit.c \ expr/log.c \ expr/lookup.c \ expr/dynset.c \ expr/immediate.c \ + expr/inner.c \ expr/match.c \ expr/meta.c \ expr/numgen.c \ diff --git a/src/batch.c b/src/batch.c index ca8f922..8a9c6f9 100644 --- a/src/batch.c +++ b/src/batch.c @@ -2,8 +2,9 @@ * Copyright (c) 2013-2015 Pablo Neira Ayuso <pablo@netfilter.org> * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. */ #include "internal.h" diff --git a/src/chain.c b/src/chain.c index 94efa90..c7026f4 100644 --- a/src/chain.c +++ b/src/chain.c @@ -51,6 +51,11 @@ struct nftnl_chain { uint32_t flags; uint32_t chain_id; + struct { + void *data; + uint32_t len; + } user; + struct list_head rule_list; }; @@ -125,6 +130,8 @@ void nftnl_chain_free(const struct nftnl_chain *c) xfree(c->type); if (c->flags & (1 << NFTNL_CHAIN_DEV)) xfree(c->dev); + if (c->flags & (1 << NFTNL_CHAIN_USERDATA)) + xfree(c->user.data); if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) { for (i = 0; i < c->dev_array_len; i++) xfree(c->dev_array[i]); @@ -189,6 +196,7 @@ static uint32_t nftnl_chain_validate[NFTNL_CHAIN_MAX + 1] = { [NFTNL_CHAIN_HOOKNUM] = sizeof(uint32_t), [NFTNL_CHAIN_PRIO] = sizeof(int32_t), [NFTNL_CHAIN_POLICY] = sizeof(uint32_t), + [NFTNL_CHAIN_USE] = sizeof(uint32_t), [NFTNL_CHAIN_BYTES] = sizeof(uint64_t), [NFTNL_CHAIN_PACKETS] = sizeof(uint64_t), [NFTNL_CHAIN_HANDLE] = sizeof(uint64_t), @@ -209,21 +217,11 @@ int nftnl_chain_set_data(struct nftnl_chain *c, uint16_t attr, switch(attr) { case NFTNL_CHAIN_NAME: - if (c->flags & (1 << NFTNL_CHAIN_NAME)) - xfree(c->name); - - c->name = strdup(data); - if (!c->name) - return -1; - break; + return nftnl_set_str_attr(&c->name, &c->flags, + attr, data, data_len); case NFTNL_CHAIN_TABLE: - if (c->flags & (1 << NFTNL_CHAIN_TABLE)) - xfree(c->table); - - c->table = strdup(data); - if (!c->table) - return -1; - break; + return nftnl_set_str_attr(&c->table, &c->flags, + attr, data, data_len); case NFTNL_CHAIN_HOOKNUM: memcpy(&c->hooknum, data, sizeof(c->hooknum)); break; @@ -249,21 +247,11 @@ int nftnl_chain_set_data(struct nftnl_chain *c, uint16_t attr, memcpy(&c->family, data, sizeof(c->family)); break; case NFTNL_CHAIN_TYPE: - if (c->flags & (1 << NFTNL_CHAIN_TYPE)) - xfree(c->type); - - c->type = strdup(data); - if (!c->type) - return -1; - break; + return nftnl_set_str_attr(&c->type, &c->flags, + attr, data, data_len); case NFTNL_CHAIN_DEV: - if (c->flags & (1 << NFTNL_CHAIN_DEV)) - xfree(c->dev); - - c->dev = strdup(data); - if (!c->dev) - return -1; - break; + return nftnl_set_str_attr(&c->dev, &c->flags, + attr, data, data_len); case NFTNL_CHAIN_DEVICES: dev_array = (const char **)data; while (dev_array[len] != NULL) @@ -290,6 +278,16 @@ int nftnl_chain_set_data(struct nftnl_chain *c, uint16_t attr, case NFTNL_CHAIN_ID: memcpy(&c->chain_id, data, sizeof(c->chain_id)); break; + case NFTNL_CHAIN_USERDATA: + if (c->flags & (1 << NFTNL_CHAIN_USERDATA)) + xfree(c->user.data); + + c->user.data = malloc(data_len); + if (!c->user.data) + return -1; + memcpy(c->user.data, data, data_len); + c->user.len = data_len; + break; } c->flags |= (1 << attr); return 0; @@ -391,6 +389,9 @@ const void *nftnl_chain_get_data(const struct nftnl_chain *c, uint16_t attr, case NFTNL_CHAIN_ID: *data_len = sizeof(uint32_t); return &c->chain_id; + case NFTNL_CHAIN_USERDATA: + *data_len = c->user.len; + return c->user.data; } return NULL; } @@ -466,40 +467,49 @@ const char *const *nftnl_chain_get_array(const struct nftnl_chain *c, uint16_t a EXPORT_SYMBOL(nftnl_chain_nlmsg_build_payload); void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_chain *c) { + struct nlattr *nest = NULL; int i; if (c->flags & (1 << NFTNL_CHAIN_TABLE)) mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, c->table); if (c->flags & (1 << NFTNL_CHAIN_NAME)) mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, c->name); - if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) && - (c->flags & (1 << NFTNL_CHAIN_PRIO))) { - struct nlattr *nest; + if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) || + (c->flags & (1 << NFTNL_CHAIN_PRIO)) || + (c->flags & (1 << NFTNL_CHAIN_DEV)) || + (c->flags & (1 << NFTNL_CHAIN_DEVICES))) nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK); + + if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM))) mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(c->hooknum)); + if ((c->flags & (1 << NFTNL_CHAIN_PRIO))) mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio)); - if (c->flags & (1 << NFTNL_CHAIN_DEV)) - mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev); - else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) { - struct nlattr *nest_dev; - nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS); - for (i = 0; i < c->dev_array_len; i++) - mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, - c->dev_array[i]); - mnl_attr_nest_end(nlh, nest_dev); - } - mnl_attr_nest_end(nlh, nest); + if (c->flags & (1 << NFTNL_CHAIN_DEV)) + mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev); + else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) { + struct nlattr *nest_dev; + + nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS); + for (i = 0; i < c->dev_array_len; i++) + mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, + c->dev_array[i]); + mnl_attr_nest_end(nlh, nest_dev); } + + if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) || + (c->flags & (1 << NFTNL_CHAIN_PRIO)) || + (c->flags & (1 << NFTNL_CHAIN_DEV)) || + (c->flags & (1 << NFTNL_CHAIN_DEVICES))) + mnl_attr_nest_end(nlh, nest); + if (c->flags & (1 << NFTNL_CHAIN_POLICY)) mnl_attr_put_u32(nlh, NFTA_CHAIN_POLICY, htonl(c->policy)); if (c->flags & (1 << NFTNL_CHAIN_USE)) mnl_attr_put_u32(nlh, NFTA_CHAIN_USE, htonl(c->use)); if ((c->flags & (1 << NFTNL_CHAIN_PACKETS)) && (c->flags & (1 << NFTNL_CHAIN_BYTES))) { - struct nlattr *nest; - nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_COUNTERS); mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, be64toh(c->packets)); mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, be64toh(c->bytes)); @@ -513,6 +523,8 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch mnl_attr_put_u32(nlh, NFTA_CHAIN_FLAGS, htonl(c->chain_flags)); if (c->flags & (1 << NFTNL_CHAIN_ID)) mnl_attr_put_u32(nlh, NFTA_CHAIN_ID, htonl(c->chain_id)); + if (c->flags & (1 << NFTNL_CHAIN_USERDATA)) + mnl_attr_put(nlh, NFTA_CHAIN_USERDATA, c->user.len, c->user.data); } EXPORT_SYMBOL(nftnl_chain_rule_add); @@ -576,6 +588,10 @@ static int nftnl_chain_parse_attr_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) abi_breakage(); break; + case NFTA_CHAIN_USERDATA: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -777,6 +793,11 @@ int nftnl_chain_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_chain *c) c->chain_id = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_ID])); c->flags |= (1 << NFTNL_CHAIN_ID); } + if (tb[NFTA_CHAIN_USERDATA]) { + nftnl_chain_set_data(c, NFTNL_CHAIN_USERDATA, + mnl_attr_get_payload(tb[NFTA_CHAIN_USERDATA]), + mnl_attr_get_payload_len(tb[NFTA_CHAIN_USERDATA])); + } c->family = nfg->nfgen_family; c->flags |= (1 << NFTNL_CHAIN_FAMILY); @@ -795,10 +816,10 @@ static inline int nftnl_str2hooknum(int family, const char *hook) return -1; } -static int nftnl_chain_snprintf_default(char *buf, size_t size, +static int nftnl_chain_snprintf_default(char *buf, size_t remain, const struct nftnl_chain *c) { - int ret, remain = size, offset = 0, i; + int ret, offset = 0, i; ret = snprintf(buf, remain, "%s %s %s use %u", nftnl_family2str(c->family), c->table, c->name, c->use); @@ -853,23 +874,17 @@ static int nftnl_chain_snprintf_default(char *buf, size_t size, return offset; } -static int nftnl_chain_cmd_snprintf(char *buf, size_t size, +static int nftnl_chain_cmd_snprintf(char *buf, size_t remain, const struct nftnl_chain *c, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_chain_snprintf_default(buf + offset, remain, c); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + ret = nftnl_chain_snprintf_default(buf + offset, remain, c); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } diff --git a/src/common.c b/src/common.c index 2d83c12..ec84fa0 100644 --- a/src/common.c +++ b/src/common.c @@ -10,6 +10,7 @@ #include <stdlib.h> #include <sys/socket.h> #include <time.h> +#include <arpa/inet.h> #include <linux/netlink.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nf_tables.h> @@ -37,7 +38,7 @@ static struct nlmsghdr *__nftnl_nlmsg_build_hdr(char *buf, uint16_t type, nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = family; nfh->version = NFNETLINK_V0; - nfh->res_id = res_id; + nfh->res_id = htons(res_id); return nlh; } @@ -126,9 +127,8 @@ int nftnl_batch_is_supported(void) mnl_nlmsg_batch_next(b); req_seq = seq; - nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), - NFT_MSG_NEWSET, AF_INET, - NLM_F_ACK, seq++); + nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), NFT_MSG_NEWSET, + AF_INET, NLM_F_ACK, seq++); mnl_nlmsg_batch_next(b); nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++); @@ -42,6 +42,9 @@ struct nftnl_expr *nftnl_expr_alloc(const char *name) expr->flags |= (1 << NFTNL_EXPR_NAME); expr->ops = ops; + if (ops->init) + ops->init(expr); + return expr; } @@ -68,6 +71,16 @@ int nftnl_expr_set(struct nftnl_expr *expr, uint16_t type, case NFTNL_EXPR_NAME: /* cannot be modified */ return 0; default: + if (type < NFTNL_EXPR_BASE || type > expr->ops->nftnl_max_attr) + return -1; + + if (!expr->ops->attr_policy) + return -1; + + if (expr->ops->attr_policy[type].maxlen && + expr->ops->attr_policy[type].maxlen < data_len) + return -1; + if (expr->ops->set(expr, type, data, data_len) < 0) return -1; } @@ -203,6 +216,7 @@ const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type) return (const char *)nftnl_expr_get(expr, type, &data_len); } +EXPORT_SYMBOL(nftnl_expr_build_payload); void nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr) { struct nlattr *nest; @@ -266,19 +280,19 @@ err1: } EXPORT_SYMBOL(nftnl_expr_snprintf); -int nftnl_expr_snprintf(char *buf, size_t size, const struct nftnl_expr *expr, +int nftnl_expr_snprintf(char *buf, size_t remain, const struct nftnl_expr *expr, uint32_t type, uint32_t flags) { int ret; - unsigned int offset = 0, remain = size; + unsigned int offset = 0; - if (size) + if (remain) buf[0] = '\0'; - if (!expr->ops->snprintf) + if (!expr->ops->output || type != NFTNL_OUTPUT_DEFAULT) return 0; - ret = expr->ops->snprintf(buf + offset, remain, type, flags, expr); + ret = expr->ops->output(buf + offset, remain, flags, expr); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c index 9ea2f66..e99131a 100644 --- a/src/expr/bitwise.c +++ b/src/expr/bitwise.c @@ -39,31 +39,23 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_BITWISE_SREG: - memcpy(&bitwise->sreg, data, sizeof(bitwise->sreg)); + memcpy(&bitwise->sreg, data, data_len); break; case NFTNL_EXPR_BITWISE_DREG: - memcpy(&bitwise->dreg, data, sizeof(bitwise->dreg)); + memcpy(&bitwise->dreg, data, data_len); break; case NFTNL_EXPR_BITWISE_OP: - memcpy(&bitwise->op, data, sizeof(bitwise->op)); + memcpy(&bitwise->op, data, data_len); break; case NFTNL_EXPR_BITWISE_LEN: - memcpy(&bitwise->len, data, sizeof(bitwise->len)); + memcpy(&bitwise->len, data, data_len); break; case NFTNL_EXPR_BITWISE_MASK: - memcpy(&bitwise->mask.val, data, data_len); - bitwise->mask.len = data_len; - break; + return nftnl_data_cpy(&bitwise->mask, data, data_len); case NFTNL_EXPR_BITWISE_XOR: - memcpy(&bitwise->xor.val, data, data_len); - bitwise->xor.len = data_len; - break; + return nftnl_data_cpy(&bitwise->xor, data, data_len); case NFTNL_EXPR_BITWISE_DATA: - memcpy(&bitwise->data.val, data, data_len); - bitwise->data.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&bitwise->data, data, data_len); } return 0; } @@ -210,40 +202,40 @@ nftnl_expr_bitwise_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_bitwise_snprintf_bool(char *buf, size_t size, +nftnl_expr_bitwise_snprintf_bool(char *buf, size_t remain, const struct nftnl_expr_bitwise *bitwise) { - int remain = size, offset = 0, ret; + int offset = 0, ret; - ret = snprintf(buf, remain, "reg %u = (reg=%u & ", + ret = snprintf(buf, remain, "reg %u = ( reg %u & ", bitwise->dreg, bitwise->sreg); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->mask, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = snprintf(buf + offset, remain, ") ^ "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->xor, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } static int -nftnl_expr_bitwise_snprintf_shift(char *buf, size_t size, const char *op, +nftnl_expr_bitwise_snprintf_shift(char *buf, size_t remain, const char *op, const struct nftnl_expr_bitwise *bitwise) -{ int remain = size, offset = 0, ret; +{ int offset = 0, ret; ret = snprintf(buf, remain, "reg %u = ( reg %u %s ", bitwise->dreg, bitwise->sreg, op); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->data, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = snprintf(buf + offset, remain, ") "); @@ -252,8 +244,9 @@ nftnl_expr_bitwise_snprintf_shift(char *buf, size_t size, const char *op, return offset; } -static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_bitwise_snprintf(char *buf, size_t size, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_bitwise *bitwise = nftnl_expr_data(e); int err = -1; @@ -273,26 +266,24 @@ static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size, return err; } -static int -nftnl_expr_bitwise_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_bitwise_snprintf_default(buf, size, e); - default: - break; - } - return -1; -} +static struct attr_policy bitwise_attr_policy[__NFTNL_EXPR_BITWISE_MAX] = { + [NFTNL_EXPR_BITWISE_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_MASK] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_XOR] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BITWISE_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, +}; struct expr_ops expr_ops_bitwise = { .name = "bitwise", .alloc_len = sizeof(struct nftnl_expr_bitwise), - .max_attr = NFTA_BITWISE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_BITWISE_MAX - 1, + .attr_policy = bitwise_attr_policy, .set = nftnl_expr_bitwise_set, .get = nftnl_expr_bitwise_get, .parse = nftnl_expr_bitwise_parse, .build = nftnl_expr_bitwise_build, - .snprintf = nftnl_expr_bitwise_snprintf, + .output = nftnl_expr_bitwise_snprintf, }; diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c index efdfa2b..383e80d 100644 --- a/src/expr/byteorder.c +++ b/src/expr/byteorder.c @@ -37,22 +37,20 @@ nftnl_expr_byteorder_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_BYTEORDER_SREG: - memcpy(&byteorder->sreg, data, sizeof(byteorder->sreg)); + memcpy(&byteorder->sreg, data, data_len); break; case NFTNL_EXPR_BYTEORDER_DREG: - memcpy(&byteorder->dreg, data, sizeof(byteorder->dreg)); + memcpy(&byteorder->dreg, data, data_len); break; case NFTNL_EXPR_BYTEORDER_OP: - memcpy(&byteorder->op, data, sizeof(byteorder->op)); + memcpy(&byteorder->op, data, data_len); break; case NFTNL_EXPR_BYTEORDER_LEN: - memcpy(&byteorder->len, data, sizeof(byteorder->len)); + memcpy(&byteorder->len, data, data_len); break; case NFTNL_EXPR_BYTEORDER_SIZE: - memcpy(&byteorder->size, data, sizeof(byteorder->size)); + memcpy(&byteorder->size, data, data_len); break; - default: - return -1; } return 0; } @@ -197,11 +195,12 @@ static inline int nftnl_str2ntoh(const char *op) } } -static int nftnl_expr_byteorder_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_byteorder_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e); - int remain = size, offset = 0, ret; + int offset = 0, ret; ret = snprintf(buf, remain, "reg %u = %s(reg %u, %u, %u) ", byteorder->dreg, bo2str(byteorder->op), @@ -211,28 +210,22 @@ static int nftnl_expr_byteorder_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_byteorder_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_byteorder_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy byteorder_attr_policy[__NFTNL_EXPR_BYTEORDER_MAX] = { + [NFTNL_EXPR_BYTEORDER_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_BYTEORDER_SIZE] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_byteorder = { .name = "byteorder", .alloc_len = sizeof(struct nftnl_expr_byteorder), - .max_attr = NFTA_BYTEORDER_MAX, + .nftnl_max_attr = __NFTNL_EXPR_BYTEORDER_MAX - 1, + .attr_policy = byteorder_attr_policy, .set = nftnl_expr_byteorder_set, .get = nftnl_expr_byteorder_get, .parse = nftnl_expr_byteorder_parse, .build = nftnl_expr_byteorder_build, - .snprintf = nftnl_expr_byteorder_snprintf, + .output = nftnl_expr_byteorder_snprintf, }; diff --git a/src/expr/cmp.c b/src/expr/cmp.c index 86d7842..d1f0f64 100644 --- a/src/expr/cmp.c +++ b/src/expr/cmp.c @@ -36,17 +36,13 @@ nftnl_expr_cmp_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CMP_SREG: - memcpy(&cmp->sreg, data, sizeof(cmp->sreg)); + memcpy(&cmp->sreg, data, data_len); break; case NFTNL_EXPR_CMP_OP: - memcpy(&cmp->op, data, sizeof(cmp->op)); + memcpy(&cmp->op, data, data_len); break; case NFTNL_EXPR_CMP_DATA: - memcpy(&cmp->data.val, data, data_len); - cmp->data.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&cmp->data, data, data_len); } return 0; } @@ -176,45 +172,38 @@ static inline int nftnl_str2cmp(const char *op) } } -static int nftnl_expr_cmp_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_cmp_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_cmp *cmp = nftnl_expr_data(e); - int remain = size, offset = 0, ret; + int offset = 0, ret; ret = snprintf(buf, remain, "%s reg %u ", cmp2str(cmp->op), cmp->sreg); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &cmp->data, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } -static int -nftnl_expr_cmp_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_cmp_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy cmp_attr_policy[__NFTNL_EXPR_CMP_MAX] = { + [NFTNL_EXPR_CMP_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CMP_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CMP_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN } +}; struct expr_ops expr_ops_cmp = { .name = "cmp", .alloc_len = sizeof(struct nftnl_expr_cmp), - .max_attr = NFTA_CMP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CMP_MAX - 1, + .attr_policy = cmp_attr_policy, .set = nftnl_expr_cmp_set, .get = nftnl_expr_cmp_get, .parse = nftnl_expr_cmp_parse, .build = nftnl_expr_cmp_build, - .snprintf = nftnl_expr_cmp_snprintf, + .output = nftnl_expr_cmp_snprintf, }; diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c index 53af93b..fcac8bf 100644 --- a/src/expr/connlimit.c +++ b/src/expr/connlimit.c @@ -33,13 +33,11 @@ nftnl_expr_connlimit_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CONNLIMIT_COUNT: - memcpy(&connlimit->count, data, sizeof(connlimit->count)); + memcpy(&connlimit->count, data, data_len); break; case NFTNL_EXPR_CONNLIMIT_FLAGS: - memcpy(&connlimit->flags, data, sizeof(connlimit->flags)); + memcpy(&connlimit->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -117,8 +115,9 @@ nftnl_expr_connlimit_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_connlimit_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_expr *e) { struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e); @@ -126,28 +125,19 @@ static int nftnl_expr_connlimit_snprintf_default(char *buf, size_t len, connlimit->count, connlimit->flags); } -static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_connlimit_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy connlimit_attr_policy[__NFTNL_EXPR_CONNLIMIT_MAX] = { + [NFTNL_EXPR_CONNLIMIT_COUNT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CONNLIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_connlimit = { .name = "connlimit", .alloc_len = sizeof(struct nftnl_expr_connlimit), - .max_attr = NFTA_CONNLIMIT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CONNLIMIT_MAX - 1, + .attr_policy = connlimit_attr_policy, .set = nftnl_expr_connlimit_set, .get = nftnl_expr_connlimit_get, .parse = nftnl_expr_connlimit_parse, .build = nftnl_expr_connlimit_build, - .snprintf = nftnl_expr_connlimit_snprintf, + .output = nftnl_expr_connlimit_snprintf, }; diff --git a/src/expr/counter.c b/src/expr/counter.c index 89a602e..cef9119 100644 --- a/src/expr/counter.c +++ b/src/expr/counter.c @@ -35,13 +35,11 @@ nftnl_expr_counter_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CTR_BYTES: - memcpy(&ctr->bytes, data, sizeof(ctr->bytes)); + memcpy(&ctr->bytes, data, data_len); break; case NFTNL_EXPR_CTR_PACKETS: - memcpy(&ctr->pkts, data, sizeof(ctr->pkts)); + memcpy(&ctr->pkts, data, data_len); break; - default: - return -1; } return 0; } @@ -115,8 +113,9 @@ nftnl_expr_counter_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_counter_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int nftnl_expr_counter_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_expr *e) { struct nftnl_expr_counter *ctr = nftnl_expr_data(e); @@ -124,28 +123,19 @@ static int nftnl_expr_counter_snprintf_default(char *buf, size_t len, ctr->pkts, ctr->bytes); } -static int nftnl_expr_counter_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_counter_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy counter_attr_policy[__NFTNL_EXPR_CTR_MAX] = { + [NFTNL_EXPR_CTR_PACKETS] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_CTR_BYTES] = { .maxlen = sizeof(uint64_t) }, +}; struct expr_ops expr_ops_counter = { .name = "counter", .alloc_len = sizeof(struct nftnl_expr_counter), - .max_attr = NFTA_COUNTER_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CTR_MAX - 1, + .attr_policy = counter_attr_policy, .set = nftnl_expr_counter_set, .get = nftnl_expr_counter_get, .parse = nftnl_expr_counter_parse, .build = nftnl_expr_counter_build, - .snprintf = nftnl_expr_counter_snprintf, + .output = nftnl_expr_counter_snprintf, }; diff --git a/src/expr/ct.c b/src/expr/ct.c index 124de9d..bea0522 100644 --- a/src/expr/ct.c +++ b/src/expr/ct.c @@ -39,19 +39,17 @@ nftnl_expr_ct_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_CT_KEY: - memcpy(&ct->key, data, sizeof(ct->key)); + memcpy(&ct->key, data, data_len); break; case NFTNL_EXPR_CT_DIR: - memcpy(&ct->dir, data, sizeof(ct->dir)); + memcpy(&ct->dir, data, data_len); break; case NFTNL_EXPR_CT_DREG: - memcpy(&ct->dreg, data, sizeof(ct->dreg)); + memcpy(&ct->dreg, data, data_len); break; case NFTNL_EXPR_CT_SREG: - memcpy(&ct->sreg, data, sizeof(ct->sreg)); + memcpy(&ct->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -223,14 +221,14 @@ static inline int str2ctdir(const char *str, uint8_t *ctdir) } static int -nftnl_expr_ct_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_ct_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int ret, remain = size, offset = 0; struct nftnl_expr_ct *ct = nftnl_expr_data(e); + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_CT_SREG)) { - ret = snprintf(buf, size, "set %s with reg %u ", + ret = snprintf(buf, remain, "set %s with reg %u ", ctkey2str(ct->key), ct->sreg); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -250,28 +248,21 @@ nftnl_expr_ct_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_ct_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_ct_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy ct_attr_policy[__NFTNL_EXPR_CT_MAX] = { + [NFTNL_EXPR_CT_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CT_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_CT_DIR] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_CT_SREG] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_ct = { .name = "ct", .alloc_len = sizeof(struct nftnl_expr_ct), - .max_attr = NFTA_CT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_CT_MAX - 1, + .attr_policy = ct_attr_policy, .set = nftnl_expr_ct_set, .get = nftnl_expr_ct_get, .parse = nftnl_expr_ct_parse, .build = nftnl_expr_ct_build, - .snprintf = nftnl_expr_ct_snprintf, + .output = nftnl_expr_ct_snprintf, }; diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c index 4e35a79..d2ccf2e 100644 --- a/src/expr/data_reg.c +++ b/src/expr/data_reg.c @@ -25,14 +25,18 @@ #include "internal.h" static int -nftnl_data_reg_value_snprintf_default(char *buf, size_t size, +nftnl_data_reg_value_snprintf_default(char *buf, size_t remain, const union nftnl_data_reg *reg, uint32_t flags) { - int remain = size, offset = 0, ret, i; + const char *pfx = flags & DATA_F_NOPFX ? "" : "0x"; + int offset = 0, ret, i; + + for (i = 0; i < div_round_up(reg->len, sizeof(uint32_t)); i++) { - ret = snprintf(buf + offset, remain, "0x%.8x ", reg->val[i]); + ret = snprintf(buf + offset, remain, + "%s%.8x ", pfx, reg->val[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -59,38 +63,19 @@ nftnl_data_reg_verdict_snprintf_def(char *buf, size_t size, int nftnl_data_reg_snprintf(char *buf, size_t size, const union nftnl_data_reg *reg, - uint32_t output_format, uint32_t flags, - int reg_type) + uint32_t flags, int reg_type) { switch(reg_type) { case DATA_VALUE: - switch(output_format) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_data_reg_value_snprintf_default(buf, size, - reg, flags); - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: - break; - } - break; + return nftnl_data_reg_value_snprintf_default(buf, size, + reg, flags); case DATA_VERDICT: case DATA_CHAIN: - switch(output_format) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_data_reg_verdict_snprintf_def(buf, size, - reg, flags); - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: - break; - } - break; + return nftnl_data_reg_verdict_snprintf_def(buf, size, + reg, flags); default: - break; + return -1; } - - return -1; } static int nftnl_data_parse_cb(const struct nlattr *attr, void *data) @@ -221,14 +206,16 @@ int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type) return ret; } -void nftnl_free_verdict(const union nftnl_data_reg *data) +int nftnl_data_cpy(union nftnl_data_reg *dreg, const void *src, uint32_t len) { - switch(data->verdict) { - case NFT_JUMP: - case NFT_GOTO: - xfree(data->chain); - break; - default: - break; + int ret = 0; + + if (len > sizeof(dreg->val)) { + len = sizeof(dreg->val); + ret = -1; } + + memcpy(dreg->val, src, len); + dreg->len = len; + return ret; } diff --git a/src/expr/dup.c b/src/expr/dup.c index ac39839..28d686b 100644 --- a/src/expr/dup.c +++ b/src/expr/dup.c @@ -32,13 +32,11 @@ static int nftnl_expr_dup_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_DUP_SREG_ADDR: - memcpy(&dup->sreg_addr, data, sizeof(dup->sreg_addr)); + memcpy(&dup->sreg_addr, data, data_len); break; case NFTNL_EXPR_DUP_SREG_DEV: - memcpy(&dup->sreg_dev, data, sizeof(dup->sreg_dev)); + memcpy(&dup->sreg_dev, data, data_len); break; - default: - return -1; } return 0; } @@ -111,47 +109,38 @@ static int nftnl_expr_dup_parse(struct nftnl_expr *e, struct nlattr *attr) return ret; } -static int nftnl_expr_dup_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e, - uint32_t flags) +static int nftnl_expr_dup_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int remain = len, offset = 0, ret; struct nftnl_expr_dup *dup = nftnl_expr_data(e); + int offset = 0, ret; if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_ADDR)) { - ret = snprintf(buf + offset, len, "sreg_addr %u ", dup->sreg_addr); + ret = snprintf(buf + offset, remain, "sreg_addr %u ", dup->sreg_addr); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_DEV)) { - ret = snprintf(buf + offset, len, "sreg_dev %u ", dup->sreg_dev); + ret = snprintf(buf + offset, remain, "sreg_dev %u ", dup->sreg_dev); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } return offset; } -static int nftnl_expr_dup_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_dup_snprintf_default(buf, len, e, flags); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy dup_attr_policy[__NFTNL_EXPR_DUP_MAX] = { + [NFTNL_EXPR_DUP_SREG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DUP_SREG_DEV] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_dup = { .name = "dup", .alloc_len = sizeof(struct nftnl_expr_dup), - .max_attr = NFTA_DUP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_DUP_MAX - 1, + .attr_policy = dup_attr_policy, .set = nftnl_expr_dup_set, .get = nftnl_expr_dup_get, .parse = nftnl_expr_dup_parse, .build = nftnl_expr_dup_build, - .snprintf = nftnl_expr_dup_snprintf, + .output = nftnl_expr_dup_snprintf, }; diff --git a/src/expr/dynset.c b/src/expr/dynset.c index 91dbea9..8a159f8 100644 --- a/src/expr/dynset.c +++ b/src/expr/dynset.c @@ -26,9 +26,10 @@ struct nftnl_expr_dynset { enum nft_registers sreg_data; enum nft_dynset_ops op; uint64_t timeout; - struct nftnl_expr *expr; + struct list_head expr_list; char *set_name; uint32_t set_id; + uint32_t dynset_flags; }; static int @@ -36,19 +37,20 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type, const void *data, uint32_t data_len) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + struct nftnl_expr *expr, *next; switch (type) { case NFTNL_EXPR_DYNSET_SREG_KEY: - memcpy(&dynset->sreg_key, data, sizeof(dynset->sreg_key)); + memcpy(&dynset->sreg_key, data, data_len); break; case NFTNL_EXPR_DYNSET_SREG_DATA: - memcpy(&dynset->sreg_data, data, sizeof(dynset->sreg_data)); + memcpy(&dynset->sreg_data, data, data_len); break; case NFTNL_EXPR_DYNSET_OP: - memcpy(&dynset->op, data, sizeof(dynset->op)); + memcpy(&dynset->op, data, data_len); break; case NFTNL_EXPR_DYNSET_TIMEOUT: - memcpy(&dynset->timeout, data, sizeof(dynset->timeout)); + memcpy(&dynset->timeout, data, data_len); break; case NFTNL_EXPR_DYNSET_SET_NAME: dynset->set_name = strdup((const char *)data); @@ -56,10 +58,17 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_DYNSET_SET_ID: - memcpy(&dynset->set_id, data, sizeof(dynset->set_id)); + memcpy(&dynset->set_id, data, data_len); break; case NFTNL_EXPR_DYNSET_EXPR: - dynset->expr = (void *)data; + list_for_each_entry_safe(expr, next, &dynset->expr_list, head) + nftnl_expr_free(expr); + + expr = (void *)data; + list_add(&expr->head, &dynset->expr_list); + break; + case NFTNL_EXPR_DYNSET_FLAGS: + memcpy(&dynset->dynset_flags, data, data_len); break; default: return -1; @@ -72,6 +81,7 @@ nftnl_expr_dynset_get(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + struct nftnl_expr *expr; switch (type) { case NFTNL_EXPR_DYNSET_SREG_KEY: @@ -93,7 +103,12 @@ nftnl_expr_dynset_get(const struct nftnl_expr *e, uint16_t type, *data_len = sizeof(dynset->set_id); return &dynset->set_id; case NFTNL_EXPR_DYNSET_EXPR: - return dynset->expr; + list_for_each_entry(expr, &dynset->expr_list, head) + break; + return expr; + case NFTNL_EXPR_DYNSET_FLAGS: + *data_len = sizeof(dynset->dynset_flags); + return &dynset->dynset_flags; } return NULL; } @@ -111,6 +126,7 @@ static int nftnl_expr_dynset_cb(const struct nlattr *attr, void *data) case NFTA_DYNSET_SREG_DATA: case NFTA_DYNSET_SET_ID: case NFTA_DYNSET_OP: + case NFTA_DYNSET_FLAGS: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) abi_breakage(); break; @@ -137,6 +153,7 @@ nftnl_expr_dynset_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); struct nlattr *nest; + int num_exprs = 0; if (e->flags & (1 << NFTNL_EXPR_DYNSET_SREG_KEY)) mnl_attr_put_u32(nlh, NFTA_DYNSET_SREG_KEY, htonl(dynset->sreg_key)); @@ -150,11 +167,58 @@ nftnl_expr_dynset_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) mnl_attr_put_strz(nlh, NFTA_DYNSET_SET_NAME, dynset->set_name); if (e->flags & (1 << NFTNL_EXPR_DYNSET_SET_ID)) mnl_attr_put_u32(nlh, NFTA_DYNSET_SET_ID, htonl(dynset->set_id)); - if (e->flags & (1 << NFTNL_EXPR_DYNSET_EXPR)) { - nest = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPR); - nftnl_expr_build_payload(nlh, dynset->expr); - mnl_attr_nest_end(nlh, nest); + if (!list_empty(&dynset->expr_list)) { + struct nftnl_expr *expr; + + list_for_each_entry(expr, &dynset->expr_list, head) + num_exprs++; + + if (num_exprs == 1) { + nest = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPR); + list_for_each_entry(expr, &dynset->expr_list, head) + nftnl_expr_build_payload(nlh, expr); + mnl_attr_nest_end(nlh, nest); + } else if (num_exprs > 1) { + struct nlattr *nest1, *nest2; + + nest1 = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPRESSIONS); + list_for_each_entry(expr, &dynset->expr_list, head) { + nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM); + nftnl_expr_build_payload(nlh, expr); + mnl_attr_nest_end(nlh, nest2); + } + mnl_attr_nest_end(nlh, nest1); + } + } + if (e->flags & (1 << NFTNL_EXPR_DYNSET_FLAGS)) + mnl_attr_put_u32(nlh, NFTA_DYNSET_FLAGS, + htonl(dynset->dynset_flags)); +} + +EXPORT_SYMBOL(nftnl_expr_add_expr); +void nftnl_expr_add_expr(struct nftnl_expr *e, uint32_t type, + struct nftnl_expr *expr) +{ + struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + + list_add_tail(&expr->head, &dynset->expr_list); +} + +EXPORT_SYMBOL(nftnl_expr_expr_foreach); +int nftnl_expr_expr_foreach(const struct nftnl_expr *e, + int (*cb)(struct nftnl_expr *e, void *data), + void *data) +{ + struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + struct nftnl_expr *cur, *tmp; + int ret; + + list_for_each_entry_safe(cur, tmp, &dynset->expr_list, head) { + ret = cb(cur, data); + if (ret < 0) + return ret; } + return 0; } static int @@ -162,6 +226,7 @@ nftnl_expr_dynset_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); struct nlattr *tb[NFTA_SET_MAX+1] = {}; + struct nftnl_expr *expr, *next; int ret = 0; if (mnl_attr_parse_nested(attr, nftnl_expr_dynset_cb, tb) < 0) @@ -195,13 +260,38 @@ nftnl_expr_dynset_parse(struct nftnl_expr *e, struct nlattr *attr) e->flags |= (1 << NFTNL_EXPR_DYNSET_SET_ID); } if (tb[NFTA_DYNSET_EXPR]) { - e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPR); - dynset->expr = nftnl_expr_parse(tb[NFTA_DYNSET_EXPR]); - if (dynset->expr == NULL) + expr = nftnl_expr_parse(tb[NFTA_DYNSET_EXPR]); + if (expr == NULL) return -1; + + list_add(&expr->head, &dynset->expr_list); + e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPR); + } else if (tb[NFTA_DYNSET_EXPRESSIONS]) { + struct nlattr *attr2; + + mnl_attr_for_each_nested(attr2, tb[NFTA_DYNSET_EXPRESSIONS]) { + if (mnl_attr_get_type(attr2) != NFTA_LIST_ELEM) + goto out_dynset_expr; + + expr = nftnl_expr_parse(attr2); + if (!expr) + goto out_dynset_expr; + + list_add_tail(&expr->head, &dynset->expr_list); + } + e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPRESSIONS); + } + if (tb[NFTA_DYNSET_FLAGS]) { + dynset->dynset_flags = ntohl(mnl_attr_get_u32(tb[NFTA_DYNSET_FLAGS])); + e->flags |= (1 << NFTNL_EXPR_DYNSET_FLAGS); } return ret; +out_dynset_expr: + list_for_each_entry_safe(expr, next, &dynset->expr_list, head) + nftnl_expr_free(expr); + + return -1; } static const char *op2str_array[] = { @@ -218,12 +308,12 @@ static const char *op2str(enum nft_dynset_ops op) } static int -nftnl_expr_dynset_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_dynset_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); struct nftnl_expr *expr; - int remain = size, offset = 0, ret; + int offset = 0, ret; ret = snprintf(buf, remain, "%s reg_key %u set %s ", op2str(dynset->op), dynset->sreg_key, dynset->set_name); @@ -239,8 +329,7 @@ nftnl_expr_dynset_snprintf_default(char *buf, size_t size, dynset->timeout); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - if (e->flags & (1 << NFTNL_EXPR_DYNSET_EXPR)) { - expr = dynset->expr; + list_for_each_entry(expr, &dynset->expr_list, head) { ret = snprintf(buf + offset, remain, "expr [ %s ", expr->ops->name); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -257,38 +346,45 @@ nftnl_expr_dynset_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_dynset_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) +static void nftnl_expr_dynset_init(const struct nftnl_expr *e) { - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_dynset_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; + struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + + INIT_LIST_HEAD(&dynset->expr_list); } static void nftnl_expr_dynset_free(const struct nftnl_expr *e) { struct nftnl_expr_dynset *dynset = nftnl_expr_data(e); + struct nftnl_expr *expr, *next; xfree(dynset->set_name); - if (dynset->expr) - nftnl_expr_free(dynset->expr); + list_for_each_entry_safe(expr, next, &dynset->expr_list, head) + nftnl_expr_free(expr); } +static struct attr_policy dynset_attr_policy[__NFTNL_EXPR_DYNSET_MAX] = { + [NFTNL_EXPR_DYNSET_SREG_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_SREG_DATA] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_TIMEOUT] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_DYNSET_SET_NAME] = { .maxlen = NFT_SET_MAXNAMELEN }, + [NFTNL_EXPR_DYNSET_SET_ID] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_DYNSET_EXPR] = { .maxlen = 0 }, + [NFTNL_EXPR_DYNSET_EXPRESSIONS] = { .maxlen = 0 }, + [NFTNL_EXPR_DYNSET_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_dynset = { .name = "dynset", .alloc_len = sizeof(struct nftnl_expr_dynset), - .max_attr = NFTA_DYNSET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_DYNSET_MAX - 1, + .attr_policy = dynset_attr_policy, + .init = nftnl_expr_dynset_init, .free = nftnl_expr_dynset_free, .set = nftnl_expr_dynset_set, .get = nftnl_expr_dynset_get, .parse = nftnl_expr_dynset_parse, .build = nftnl_expr_dynset_build, - .snprintf = nftnl_expr_dynset_snprintf, + .output = nftnl_expr_dynset_snprintf, }; diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c index e5f714b..453902c 100644 --- a/src/expr/exthdr.c +++ b/src/expr/exthdr.c @@ -46,28 +46,26 @@ nftnl_expr_exthdr_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_EXTHDR_DREG: - memcpy(&exthdr->dreg, data, sizeof(exthdr->dreg)); + memcpy(&exthdr->dreg, data, data_len); break; case NFTNL_EXPR_EXTHDR_TYPE: - memcpy(&exthdr->type, data, sizeof(exthdr->type)); + memcpy(&exthdr->type, data, data_len); break; case NFTNL_EXPR_EXTHDR_OFFSET: - memcpy(&exthdr->offset, data, sizeof(exthdr->offset)); + memcpy(&exthdr->offset, data, data_len); break; case NFTNL_EXPR_EXTHDR_LEN: - memcpy(&exthdr->len, data, sizeof(exthdr->len)); + memcpy(&exthdr->len, data, data_len); break; case NFTNL_EXPR_EXTHDR_OP: - memcpy(&exthdr->op, data, sizeof(exthdr->op)); + memcpy(&exthdr->op, data, data_len); break; case NFTNL_EXPR_EXTHDR_FLAGS: - memcpy(&exthdr->flags, data, sizeof(exthdr->flags)); + memcpy(&exthdr->flags, data, data_len); break; case NFTNL_EXPR_EXTHDR_SREG: - memcpy(&exthdr->sreg, data, sizeof(exthdr->sreg)); + memcpy(&exthdr->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -235,8 +233,9 @@ static inline int str2exthdr_type(const char *str) return -1; } -static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int +nftnl_expr_exthdr_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e); @@ -246,35 +245,36 @@ static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len, exthdr->offset, exthdr->flags & NFT_EXTHDR_F_PRESENT ? " present" : "", exthdr->dreg); - else + else if (e->flags & (1 << NFTNL_EXPR_EXTHDR_SREG)) return snprintf(buf, len, "write%s reg %u => %ub @ %u + %u ", op2str(exthdr->op), exthdr->sreg, exthdr->len, exthdr->type, exthdr->offset); + else if (exthdr->op == NFT_EXTHDR_OP_TCPOPT && exthdr->len == 0) + return snprintf(buf, len, "reset tcpopt %u ", exthdr->type); + else + return snprintf(buf, len, "op %u len %u type %u offset %u ", + exthdr->op, exthdr->len, exthdr->type, exthdr->offset); } -static int -nftnl_expr_exthdr_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_exthdr_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy exthdr_attr_policy[__NFTNL_EXPR_EXTHDR_MAX] = { + [NFTNL_EXPR_EXTHDR_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_TYPE] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_EXTHDR_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_EXTHDR_SREG] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_exthdr = { .name = "exthdr", .alloc_len = sizeof(struct nftnl_expr_exthdr), - .max_attr = NFTA_EXTHDR_MAX, + .nftnl_max_attr = __NFTNL_EXPR_EXTHDR_MAX - 1, + .attr_policy = exthdr_attr_policy, .set = nftnl_expr_exthdr_set, .get = nftnl_expr_exthdr_get, .parse = nftnl_expr_exthdr_parse, .build = nftnl_expr_exthdr_build, - .snprintf = nftnl_expr_exthdr_snprintf, + .output = nftnl_expr_exthdr_snprintf, }; diff --git a/src/expr/fib.c b/src/expr/fib.c index 9475af4..20bc125 100644 --- a/src/expr/fib.c +++ b/src/expr/fib.c @@ -35,16 +35,14 @@ nftnl_expr_fib_set(struct nftnl_expr *e, uint16_t result, switch (result) { case NFTNL_EXPR_FIB_RESULT: - memcpy(&fib->result, data, sizeof(fib->result)); + memcpy(&fib->result, data, data_len); break; case NFTNL_EXPR_FIB_DREG: - memcpy(&fib->dreg, data, sizeof(fib->dreg)); + memcpy(&fib->dreg, data, data_len); break; case NFTNL_EXPR_FIB_FLAGS: - memcpy(&fib->flags, data, sizeof(fib->flags)); + memcpy(&fib->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -143,13 +141,13 @@ static const char *fib_type_str(enum nft_fib_result r) } static int -nftnl_expr_fib_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_fib_snprintf(char *buf, size_t remain, + uint32_t printflags, const struct nftnl_expr *e) { struct nftnl_expr_fib *fib = nftnl_expr_data(e); - int remain = size, offset = 0, ret, i; uint32_t flags = fib->flags & ~NFTA_FIB_F_PRESENT; uint32_t present_flag = fib->flags & NFTA_FIB_F_PRESENT; + int offset = 0, ret, i; static const struct { int bit; const char *name; @@ -190,28 +188,20 @@ nftnl_expr_fib_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_fib_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_fib_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy fib_attr_policy[__NFTNL_EXPR_FIB_MAX] = { + [NFTNL_EXPR_FIB_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FIB_RESULT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FIB_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_fib = { .name = "fib", .alloc_len = sizeof(struct nftnl_expr_fib), - .max_attr = NFTA_FIB_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FIB_MAX - 1, + .attr_policy = fib_attr_policy, .set = nftnl_expr_fib_set, .get = nftnl_expr_fib_get, .parse = nftnl_expr_fib_parse, .build = nftnl_expr_fib_build, - .snprintf = nftnl_expr_fib_snprintf, + .output = nftnl_expr_fib_snprintf, }; diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c index 6ccec9a..5f209a6 100644 --- a/src/expr/flow_offload.c +++ b/src/expr/flow_offload.c @@ -25,8 +25,6 @@ static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type, if (!flow->table_name) return -1; break; - default: - return -1; } return 0; } @@ -92,11 +90,11 @@ static int nftnl_expr_flow_parse(struct nftnl_expr *e, struct nlattr *attr) return ret; } -static int nftnl_expr_flow_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int nftnl_expr_flow_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int remain = size, offset = 0, ret; struct nftnl_expr_flow *l = nftnl_expr_data(e); + int offset = 0, ret; ret = snprintf(buf, remain, "flowtable %s ", l->table_name); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -104,20 +102,6 @@ static int nftnl_expr_flow_snprintf_default(char *buf, size_t size, return offset; } -static int nftnl_expr_flow_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_flow_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} - static void nftnl_expr_flow_free(const struct nftnl_expr *e) { struct nftnl_expr_flow *flow = nftnl_expr_data(e); @@ -125,14 +109,19 @@ static void nftnl_expr_flow_free(const struct nftnl_expr *e) xfree(flow->table_name); } +static struct attr_policy flow_offload_attr_policy[__NFTNL_EXPR_FLOW_MAX] = { + [NFTNL_EXPR_FLOW_TABLE_NAME] = { .maxlen = NFT_NAME_MAXLEN }, +}; + struct expr_ops expr_ops_flow = { .name = "flow_offload", .alloc_len = sizeof(struct nftnl_expr_flow), - .max_attr = NFTA_FLOW_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FLOW_MAX - 1, + .attr_policy = flow_offload_attr_policy, .free = nftnl_expr_flow_free, .set = nftnl_expr_flow_set, .get = nftnl_expr_flow_get, .parse = nftnl_expr_flow_parse, .build = nftnl_expr_flow_build, - .snprintf = nftnl_expr_flow_snprintf, + .output = nftnl_expr_flow_snprintf, }; diff --git a/src/expr/fwd.c b/src/expr/fwd.c index 2ec63c1..04cb089 100644 --- a/src/expr/fwd.c +++ b/src/expr/fwd.c @@ -33,16 +33,14 @@ static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_FWD_SREG_DEV: - memcpy(&fwd->sreg_dev, data, sizeof(fwd->sreg_dev)); + memcpy(&fwd->sreg_dev, data, data_len); break; case NFTNL_EXPR_FWD_SREG_ADDR: - memcpy(&fwd->sreg_addr, data, sizeof(fwd->sreg_addr)); + memcpy(&fwd->sreg_addr, data, data_len); break; case NFTNL_EXPR_FWD_NFPROTO: - memcpy(&fwd->nfproto, data, sizeof(fwd->nfproto)); + memcpy(&fwd->nfproto, data, data_len); break; - default: - return -1; } return 0; } @@ -125,12 +123,11 @@ static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr) return ret; } -static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e, - uint32_t flags) +static int nftnl_expr_fwd_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int remain = len, offset = 0, ret; struct nftnl_expr_fwd *fwd = nftnl_expr_data(e); + int offset = 0, ret; if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV)) { ret = snprintf(buf + offset, remain, "sreg_dev %u ", @@ -151,27 +148,20 @@ static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len, return offset; } -static int nftnl_expr_fwd_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_fwd_snprintf_default(buf, len, e, flags); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy fwd_attr_policy[__NFTNL_EXPR_FWD_MAX] = { + [NFTNL_EXPR_FWD_SREG_DEV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FWD_SREG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_FWD_NFPROTO] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_fwd = { .name = "fwd", .alloc_len = sizeof(struct nftnl_expr_fwd), - .max_attr = NFTA_FWD_MAX, + .nftnl_max_attr = __NFTNL_EXPR_FWD_MAX - 1, + .attr_policy = fwd_attr_policy, .set = nftnl_expr_fwd_set, .get = nftnl_expr_fwd_get, .parse = nftnl_expr_fwd_parse, .build = nftnl_expr_fwd_build, - .snprintf = nftnl_expr_fwd_snprintf, + .output = nftnl_expr_fwd_snprintf, }; diff --git a/src/expr/hash.c b/src/expr/hash.c index 2c801d2..eb44b2e 100644 --- a/src/expr/hash.c +++ b/src/expr/hash.c @@ -37,25 +37,25 @@ nftnl_expr_hash_set(struct nftnl_expr *e, uint16_t type, struct nftnl_expr_hash *hash = nftnl_expr_data(e); switch (type) { case NFTNL_EXPR_HASH_SREG: - memcpy(&hash->sreg, data, sizeof(hash->sreg)); + memcpy(&hash->sreg, data, data_len); break; case NFTNL_EXPR_HASH_DREG: - memcpy(&hash->dreg, data, sizeof(hash->dreg)); + memcpy(&hash->dreg, data, data_len); break; case NFTNL_EXPR_HASH_LEN: - memcpy(&hash->len, data, sizeof(hash->len)); + memcpy(&hash->len, data, data_len); break; case NFTNL_EXPR_HASH_MODULUS: - memcpy(&hash->modulus, data, sizeof(hash->modulus)); + memcpy(&hash->modulus, data, data_len); break; case NFTNL_EXPR_HASH_SEED: - memcpy(&hash->seed, data, sizeof(hash->seed)); + memcpy(&hash->seed, data, data_len); break; case NFTNL_EXPR_HASH_OFFSET: - memcpy(&hash->offset, data, sizeof(hash->offset)); + memcpy(&hash->offset, data, data_len); break; case NFTNL_EXPR_HASH_TYPE: - memcpy(&hash->type, data, sizeof(hash->type)); + memcpy(&hash->type, data, data_len); break; default: return -1; @@ -184,11 +184,11 @@ nftnl_expr_hash_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_hash_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_hash_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_hash *hash = nftnl_expr_data(e); - int remain = size, offset = 0, ret; + int offset = 0, ret; switch (hash->type) { case NFT_HASH_SYM: @@ -218,28 +218,24 @@ nftnl_expr_hash_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_hash_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_hash_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy hash_attr_policy[__NFTNL_EXPR_HASH_MAX] = { + [NFTNL_EXPR_HASH_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_MODULUS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_SEED] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_HASH_TYPE] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_hash = { .name = "hash", .alloc_len = sizeof(struct nftnl_expr_hash), - .max_attr = NFTA_HASH_MAX, + .nftnl_max_attr = __NFTNL_EXPR_HASH_MAX - 1, + .attr_policy = hash_attr_policy, .set = nftnl_expr_hash_set, .get = nftnl_expr_hash_get, .parse = nftnl_expr_hash_parse, .build = nftnl_expr_hash_build, - .snprintf = nftnl_expr_hash_snprintf, + .output = nftnl_expr_hash_snprintf, }; diff --git a/src/expr/immediate.c b/src/expr/immediate.c index 7f34772..ab1276a 100644 --- a/src/expr/immediate.c +++ b/src/expr/immediate.c @@ -33,14 +33,12 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_IMM_DREG: - memcpy(&imm->dreg, data, sizeof(imm->dreg)); + memcpy(&imm->dreg, data, data_len); break; case NFTNL_EXPR_IMM_DATA: - memcpy(&imm->data.val, data, data_len); - imm->data.len = data_len; - break; + return nftnl_data_cpy(&imm->data, data, data_len); case NFTNL_EXPR_IMM_VERDICT: - memcpy(&imm->data.verdict, data, sizeof(imm->data.verdict)); + memcpy(&imm->data.verdict, data, data_len); break; case NFTNL_EXPR_IMM_CHAIN: if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) @@ -51,10 +49,8 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_IMM_CHAIN_ID: - memcpy(&imm->data.chain_id, data, sizeof(uint32_t)); + memcpy(&imm->data.chain_id, data, data_len); break; - default: - return -1; } return 0; } @@ -184,66 +180,59 @@ nftnl_expr_immediate_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_immediate_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e, - uint32_t flags) +nftnl_expr_immediate_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int remain = len, offset = 0, ret; struct nftnl_expr_immediate *imm = nftnl_expr_data(e); + int offset = 0, ret; ret = snprintf(buf, remain, "reg %u ", imm->dreg); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (e->flags & (1 << NFTNL_EXPR_IMM_DATA)) { ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data, - NFTNL_OUTPUT_DEFAULT, flags, DATA_VALUE); + flags, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } else if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT)) { ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data, - NFTNL_OUTPUT_DEFAULT, flags, DATA_VERDICT); + flags, DATA_VERDICT); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } else if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) { ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data, - NFTNL_OUTPUT_DEFAULT, flags, DATA_CHAIN); + flags, DATA_CHAIN); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } return offset; } -static int -nftnl_expr_immediate_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_immediate_snprintf_default(buf, len, e, flags); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} - static void nftnl_expr_immediate_free(const struct nftnl_expr *e) { struct nftnl_expr_immediate *imm = nftnl_expr_data(e); - if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT)) - nftnl_free_verdict(&imm->data); + if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) + xfree(imm->data.chain); } +static struct attr_policy immediate_attr_policy[__NFTNL_EXPR_IMM_MAX] = { + [NFTNL_EXPR_IMM_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_IMM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_IMM_VERDICT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_IMM_CHAIN] = { .maxlen = NFT_CHAIN_MAXNAMELEN }, + [NFTNL_EXPR_IMM_CHAIN_ID] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_immediate = { .name = "immediate", .alloc_len = sizeof(struct nftnl_expr_immediate), - .max_attr = NFTA_IMMEDIATE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_IMM_MAX - 1, + .attr_policy = immediate_attr_policy, .free = nftnl_expr_immediate_free, .set = nftnl_expr_immediate_set, .get = nftnl_expr_immediate_get, .parse = nftnl_expr_immediate_parse, .build = nftnl_expr_immediate_build, - .snprintf = nftnl_expr_immediate_snprintf, + .output = nftnl_expr_immediate_snprintf, }; diff --git a/src/expr/inner.c b/src/expr/inner.c new file mode 100644 index 0000000..4f66e94 --- /dev/null +++ b/src/expr/inner.c @@ -0,0 +1,220 @@ +/* + * (C) 2012-2022 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "internal.h" + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> +#include <arpa/inet.h> +#include <errno.h> +#include <libmnl/libmnl.h> + +#include <linux/netfilter/nf_tables.h> + +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> + +struct nftnl_expr_inner { + uint32_t type; + uint32_t flags; + uint32_t hdrsize; + struct nftnl_expr *expr; +}; + +static void nftnl_expr_inner_free(const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + if (inner->expr) + nftnl_expr_free(inner->expr); +} + +static int +nftnl_expr_inner_set(struct nftnl_expr *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_TYPE: + memcpy(&inner->type, data, data_len); + break; + case NFTNL_EXPR_INNER_FLAGS: + memcpy(&inner->flags, data, data_len); + break; + case NFTNL_EXPR_INNER_HDRSIZE: + memcpy(&inner->hdrsize, data, data_len); + break; + case NFTNL_EXPR_INNER_EXPR: + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = (void *)data; + break; + } + return 0; +} + +static const void * +nftnl_expr_inner_get(const struct nftnl_expr *e, uint16_t type, + uint32_t *data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_FLAGS: + *data_len = sizeof(inner->flags); + return &inner->flags; + case NFTNL_EXPR_INNER_TYPE: + *data_len = sizeof(inner->type); + return &inner->type; + case NFTNL_EXPR_INNER_HDRSIZE: + *data_len = sizeof(inner->hdrsize); + return &inner->hdrsize; + case NFTNL_EXPR_INNER_EXPR: + return inner->expr; + } + return NULL; +} + +static void +nftnl_expr_inner_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *nest; + + mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0)); + if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE)) + mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type)); + if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS)) + mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags)); + if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE)) + mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize)); + if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) { + nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR); + nftnl_expr_build_payload(nlh, inner->expr); + mnl_attr_nest_end(nlh, nest); + } +} + +static int nftnl_inner_parse_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_INNER_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_INNER_NUM: + case NFTA_INNER_TYPE: + case NFTA_INNER_HDRSIZE: + case NFTA_INNER_FLAGS: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; + case NFTA_INNER_EXPR: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + abi_breakage(); + break; + } + + tb[type] = attr; + + return MNL_CB_OK; +} + +static int +nftnl_expr_inner_parse(struct nftnl_expr *e, struct nlattr *attr) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *tb[NFTA_INNER_MAX + 1] = {}; + struct nftnl_expr *expr; + int err; + + err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb); + if (err < 0) + return err; + + if (tb[NFTA_INNER_HDRSIZE]) { + inner->hdrsize = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE])); + e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE); + } + if (tb[NFTA_INNER_FLAGS]) { + inner->flags = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS])); + e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS); + } + if (tb[NFTA_INNER_TYPE]) { + inner->type = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE])); + e->flags |= (1 << NFTNL_EXPR_INNER_TYPE); + } + if (tb[NFTA_INNER_EXPR]) { + expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]); + if (!expr) + return -1; + + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = expr; + e->flags |= (1 << NFTNL_EXPR_INNER_EXPR); + } + + return 0; +} + +static int +nftnl_expr_inner_snprintf(char *buf, size_t remain, uint32_t flags, + const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + uint32_t offset = 0; + int ret; + + ret = snprintf(buf, remain, "type %u hdrsize %u flags %x [", + inner->type, inner->hdrsize, inner->flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, " %s ", inner->expr->ops->name); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr, + NFTNL_OUTPUT_DEFAULT, 0); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, "] "); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + return offset; +} + +static struct attr_policy inner_attr_policy[__NFTNL_EXPR_INNER_MAX] = { + [NFTNL_EXPR_INNER_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_HDRSIZE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_INNER_EXPR] = { .maxlen = 0 }, +}; + +struct expr_ops expr_ops_inner = { + .name = "inner", + .alloc_len = sizeof(struct nftnl_expr_inner), + .nftnl_max_attr = __NFTNL_EXPR_INNER_MAX - 1, + .attr_policy = inner_attr_policy, + .free = nftnl_expr_inner_free, + .set = nftnl_expr_inner_set, + .get = nftnl_expr_inner_get, + .parse = nftnl_expr_inner_parse, + .build = nftnl_expr_inner_build, + .output = nftnl_expr_inner_snprintf, +}; diff --git a/src/expr/last.c b/src/expr/last.c new file mode 100644 index 0000000..8e5b88e --- /dev/null +++ b/src/expr/last.c @@ -0,0 +1,142 @@ +/* + * (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <stdio.h> +#include <stdint.h> +#include <arpa/inet.h> +#include <errno.h> +#include <inttypes.h> + +#include <linux/netfilter/nf_tables.h> + +#include "internal.h" +#include <libmnl/libmnl.h> +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> + +struct nftnl_expr_last { + uint64_t msecs; + uint32_t set; +}; + +static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nftnl_expr_last *last = nftnl_expr_data(e); + + switch (type) { + case NFTNL_EXPR_LAST_MSECS: + memcpy(&last->msecs, data, data_len); + break; + case NFTNL_EXPR_LAST_SET: + memcpy(&last->set, data, data_len); + break; + } + return 0; +} + +static const void *nftnl_expr_last_get(const struct nftnl_expr *e, + uint16_t type, uint32_t *data_len) +{ + struct nftnl_expr_last *last = nftnl_expr_data(e); + + switch (type) { + case NFTNL_EXPR_LAST_MSECS: + *data_len = sizeof(last->msecs); + return &last->msecs; + case NFTNL_EXPR_LAST_SET: + *data_len = sizeof(last->set); + return &last->set; + } + return NULL; +} + +static int nftnl_expr_last_cb(const struct nlattr *attr, void *data) +{ + int type = mnl_attr_get_type(attr); + const struct nlattr **tb = data; + + if (mnl_attr_type_valid(attr, NFTA_LAST_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_LAST_MSECS: + if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) + abi_breakage(); + break; + case NFTA_LAST_SET: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; + } + + tb[type] = attr; + return MNL_CB_OK; +} + +static void +nftnl_expr_last_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) +{ + struct nftnl_expr_last *last = nftnl_expr_data(e); + + if (e->flags & (1 << NFTNL_EXPR_LAST_MSECS)) + mnl_attr_put_u64(nlh, NFTA_LAST_MSECS, htobe64(last->msecs)); + if (e->flags & (1 << NFTNL_EXPR_LAST_SET)) + mnl_attr_put_u32(nlh, NFTA_LAST_SET, htonl(last->set)); +} + +static int +nftnl_expr_last_parse(struct nftnl_expr *e, struct nlattr *attr) +{ + struct nftnl_expr_last *last = nftnl_expr_data(e); + struct nlattr *tb[NFTA_LAST_MAX + 1] = {}; + + if (mnl_attr_parse_nested(attr, nftnl_expr_last_cb, tb) < 0) + return -1; + + if (tb[NFTA_LAST_MSECS]) { + last->msecs = be64toh(mnl_attr_get_u64(tb[NFTA_LAST_MSECS])); + e->flags |= (1 << NFTNL_EXPR_LAST_MSECS); + } + if (tb[NFTA_LAST_SET]) { + last->set = ntohl(mnl_attr_get_u32(tb[NFTA_LAST_SET])); + e->flags |= (1 << NFTNL_EXPR_LAST_SET); + } + + return 0; +} + +static int nftnl_expr_last_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_expr *e) +{ + struct nftnl_expr_last *last = nftnl_expr_data(e); + + if (!last->set) + return snprintf(buf, len, "never "); + + return snprintf(buf, len, "%"PRIu64" ", last->msecs); +} + +static struct attr_policy last_attr_policy[__NFTNL_EXPR_LAST_MAX] = { + [NFTNL_EXPR_LAST_MSECS] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LAST_SET] = { .maxlen = sizeof(uint32_t) }, +}; + +struct expr_ops expr_ops_last = { + .name = "last", + .alloc_len = sizeof(struct nftnl_expr_last), + .nftnl_max_attr = __NFTNL_EXPR_LAST_MAX - 1, + .attr_policy = last_attr_policy, + .set = nftnl_expr_last_set, + .get = nftnl_expr_last_get, + .parse = nftnl_expr_last_parse, + .build = nftnl_expr_last_build, + .output = nftnl_expr_last_snprintf, +}; diff --git a/src/expr/limit.c b/src/expr/limit.c index 5872e27..9d02592 100644 --- a/src/expr/limit.c +++ b/src/expr/limit.c @@ -38,22 +38,20 @@ nftnl_expr_limit_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_LIMIT_RATE: - memcpy(&limit->rate, data, sizeof(limit->rate)); + memcpy(&limit->rate, data, data_len); break; case NFTNL_EXPR_LIMIT_UNIT: - memcpy(&limit->unit, data, sizeof(limit->unit)); + memcpy(&limit->unit, data, data_len); break; case NFTNL_EXPR_LIMIT_BURST: - memcpy(&limit->burst, data, sizeof(limit->burst)); + memcpy(&limit->burst, data, data_len); break; case NFTNL_EXPR_LIMIT_TYPE: - memcpy(&limit->type, data, sizeof(limit->type)); + memcpy(&limit->type, data, data_len); break; case NFTNL_EXPR_LIMIT_FLAGS: - memcpy(&limit->flags, data, sizeof(limit->flags)); + memcpy(&limit->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -183,8 +181,9 @@ static const char *limit_to_type(enum nft_limit_type type) } } -static int nftnl_expr_limit_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int +nftnl_expr_limit_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_limit *limit = nftnl_expr_data(e); @@ -193,28 +192,22 @@ static int nftnl_expr_limit_snprintf_default(char *buf, size_t len, limit_to_type(limit->type), limit->flags); } -static int -nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_limit_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy limit_attr_policy[__NFTNL_EXPR_LIMIT_MAX] = { + [NFTNL_EXPR_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_limit = { .name = "limit", .alloc_len = sizeof(struct nftnl_expr_limit), - .max_attr = NFTA_LIMIT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LIMIT_MAX - 1, + .attr_policy = limit_attr_policy, .set = nftnl_expr_limit_set, .get = nftnl_expr_limit_get, .parse = nftnl_expr_limit_parse, .build = nftnl_expr_limit_build, - .snprintf = nftnl_expr_limit_snprintf, + .output = nftnl_expr_limit_snprintf, }; diff --git a/src/expr/log.c b/src/expr/log.c index bbe43d2..18ec2b6 100644 --- a/src/expr/log.c +++ b/src/expr/log.c @@ -46,22 +46,20 @@ static int nftnl_expr_log_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_LOG_GROUP: - memcpy(&log->group, data, sizeof(log->group)); + memcpy(&log->group, data, data_len); break; case NFTNL_EXPR_LOG_SNAPLEN: - memcpy(&log->snaplen, data, sizeof(log->snaplen)); + memcpy(&log->snaplen, data, data_len); break; case NFTNL_EXPR_LOG_QTHRESHOLD: - memcpy(&log->qthreshold, data, sizeof(log->qthreshold)); + memcpy(&log->qthreshold, data, data_len); break; case NFTNL_EXPR_LOG_LEVEL: - memcpy(&log->level, data, sizeof(log->level)); + memcpy(&log->level, data, data_len); break; case NFTNL_EXPR_LOG_FLAGS: - memcpy(&log->flags, data, sizeof(log->flags)); + memcpy(&log->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -186,11 +184,12 @@ nftnl_expr_log_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_log_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_log_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_log *log = nftnl_expr_data(e); - int ret, offset = 0, remain = size; + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_LOG_PREFIX)) { ret = snprintf(buf, remain, "prefix %s ", log->prefix); @@ -236,21 +235,6 @@ static int nftnl_expr_log_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_log_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_log_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} - static void nftnl_expr_log_free(const struct nftnl_expr *e) { struct nftnl_expr_log *log = nftnl_expr_data(e); @@ -258,14 +242,24 @@ static void nftnl_expr_log_free(const struct nftnl_expr *e) xfree(log->prefix); } +static struct attr_policy log_attr_policy[__NFTNL_EXPR_LOG_MAX] = { + [NFTNL_EXPR_LOG_PREFIX] = { .maxlen = NF_LOG_PREFIXLEN }, + [NFTNL_EXPR_LOG_GROUP] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_LOG_SNAPLEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOG_QTHRESHOLD] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_LOG_LEVEL] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOG_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_log = { .name = "log", .alloc_len = sizeof(struct nftnl_expr_log), - .max_attr = NFTA_LOG_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LOG_MAX - 1, + .attr_policy = log_attr_policy, .free = nftnl_expr_log_free, .set = nftnl_expr_log_set, .get = nftnl_expr_log_get, .parse = nftnl_expr_log_parse, .build = nftnl_expr_log_build, - .snprintf = nftnl_expr_log_snprintf, + .output = nftnl_expr_log_snprintf, }; diff --git a/src/expr/lookup.c b/src/expr/lookup.c index a495ac0..21a7fce 100644 --- a/src/expr/lookup.c +++ b/src/expr/lookup.c @@ -37,10 +37,10 @@ nftnl_expr_lookup_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_LOOKUP_SREG: - memcpy(&lookup->sreg, data, sizeof(lookup->sreg)); + memcpy(&lookup->sreg, data, data_len); break; case NFTNL_EXPR_LOOKUP_DREG: - memcpy(&lookup->dreg, data, sizeof(lookup->dreg)); + memcpy(&lookup->dreg, data, data_len); break; case NFTNL_EXPR_LOOKUP_SET: lookup->set_name = strdup((const char *)data); @@ -48,13 +48,11 @@ nftnl_expr_lookup_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_LOOKUP_SET_ID: - memcpy(&lookup->set_id, data, sizeof(lookup->set_id)); + memcpy(&lookup->set_id, data, data_len); break; case NFTNL_EXPR_LOOKUP_FLAGS: - memcpy(&lookup->flags, data, sizeof(lookup->flags)); + memcpy(&lookup->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -168,11 +166,11 @@ nftnl_expr_lookup_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_lookup_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_lookup_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int remain = size, offset = 0, ret; struct nftnl_expr_lookup *l = nftnl_expr_data(e); + int offset = 0, ret; ret = snprintf(buf, remain, "reg %u set %s ", l->sreg, l->set_name); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -190,21 +188,6 @@ nftnl_expr_lookup_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_lookup_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_lookup_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} - static void nftnl_expr_lookup_free(const struct nftnl_expr *e) { struct nftnl_expr_lookup *lookup = nftnl_expr_data(e); @@ -212,14 +195,23 @@ static void nftnl_expr_lookup_free(const struct nftnl_expr *e) xfree(lookup->set_name); } +static struct attr_policy lookup_attr_policy[__NFTNL_EXPR_LOOKUP_MAX] = { + [NFTNL_EXPR_LOOKUP_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_SET] = { .maxlen = NFT_SET_MAXNAMELEN }, + [NFTNL_EXPR_LOOKUP_SET_ID] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_LOOKUP_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_lookup = { .name = "lookup", .alloc_len = sizeof(struct nftnl_expr_lookup), - .max_attr = NFTA_LOOKUP_MAX, + .nftnl_max_attr = __NFTNL_EXPR_LOOKUP_MAX - 1, + .attr_policy = lookup_attr_policy, .free = nftnl_expr_lookup_free, .set = nftnl_expr_lookup_set, .get = nftnl_expr_lookup_get, .parse = nftnl_expr_lookup_parse, .build = nftnl_expr_lookup_build, - .snprintf = nftnl_expr_lookup_snprintf, + .output = nftnl_expr_lookup_snprintf, }; diff --git a/src/expr/masq.c b/src/expr/masq.c index 622ba28..e0565db 100644 --- a/src/expr/masq.c +++ b/src/expr/masq.c @@ -34,16 +34,14 @@ nftnl_expr_masq_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_MASQ_FLAGS: - memcpy(&masq->flags, data, sizeof(masq->flags)); + memcpy(&masq->flags, data, data_len); break; case NFTNL_EXPR_MASQ_REG_PROTO_MIN: - memcpy(&masq->sreg_proto_min, data, sizeof(masq->sreg_proto_min)); + memcpy(&masq->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_MASQ_REG_PROTO_MAX: - memcpy(&masq->sreg_proto_max, data, sizeof(masq->sreg_proto_max)); + memcpy(&masq->sreg_proto_max, data, data_len); break; - default: - return -1; } return 0; } @@ -131,16 +129,20 @@ nftnl_expr_masq_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_masq_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int nftnl_expr_masq_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_masq *masq = nftnl_expr_data(e); - int remain = len, offset = 0, ret = 0; + int offset = 0, ret = 0; if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MIN)) { - ret = snprintf(buf, remain, - "proto_min reg %u proto_max reg %u ", - masq->sreg_proto_min, masq->sreg_proto_max); + ret = snprintf(buf + offset, remain, "proto_min reg %u ", + masq->sreg_proto_min); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MAX)) { + ret = snprintf(buf + offset, remain, "proto_max reg %u ", + masq->sreg_proto_max); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_EXPR_MASQ_FLAGS)) { @@ -151,27 +153,20 @@ static int nftnl_expr_masq_snprintf_default(char *buf, size_t len, return offset; } -static int nftnl_expr_masq_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_masq_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy masq_attr_policy[__NFTNL_EXPR_MASQ_MAX] = { + [NFTNL_EXPR_MASQ_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MASQ_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MASQ_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_masq = { .name = "masq", .alloc_len = sizeof(struct nftnl_expr_masq), - .max_attr = NFTA_MASQ_MAX, + .nftnl_max_attr = __NFTNL_EXPR_MASQ_MAX - 1, + .attr_policy = masq_attr_policy, .set = nftnl_expr_masq_set, .get = nftnl_expr_masq_get, .parse = nftnl_expr_masq_parse, .build = nftnl_expr_masq_build, - .snprintf = nftnl_expr_masq_snprintf, + .output = nftnl_expr_masq_snprintf, }; diff --git a/src/expr/match.c b/src/expr/match.c index 4fa74b2..8c1bc74 100644 --- a/src/expr/match.c +++ b/src/expr/match.c @@ -46,7 +46,7 @@ nftnl_expr_match_set(struct nftnl_expr *e, uint16_t type, (const char *)data); break; case NFTNL_EXPR_MT_REV: - memcpy(&mt->rev, data, sizeof(mt->rev)); + memcpy(&mt->rev, data, data_len); break; case NFTNL_EXPR_MT_INFO: if (e->flags & (1 << NFTNL_EXPR_MT_INFO)) @@ -55,8 +55,6 @@ nftnl_expr_match_set(struct nftnl_expr *e, uint16_t type, mt->data = data; mt->data_len = data_len; break; - default: - return -1; } return 0; } @@ -165,21 +163,12 @@ static int nftnl_expr_match_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_match_snprintf(char *buf, size_t len, uint32_t type, +nftnl_expr_match_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_match *match = nftnl_expr_data(e); - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return snprintf(buf, len, "name %s rev %u ", - match->name, match->rev); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; + return snprintf(buf, len, "name %s rev %u ", match->name, match->rev); } static void nftnl_expr_match_free(const struct nftnl_expr *e) @@ -189,14 +178,21 @@ static void nftnl_expr_match_free(const struct nftnl_expr *e) xfree(match->data); } +static struct attr_policy match_attr_policy[__NFTNL_EXPR_MT_MAX] = { + [NFTNL_EXPR_MT_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN }, + [NFTNL_EXPR_MT_REV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_MT_INFO] = { .maxlen = 0 }, +}; + struct expr_ops expr_ops_match = { .name = "match", .alloc_len = sizeof(struct nftnl_expr_match), - .max_attr = NFTA_MATCH_MAX, + .nftnl_max_attr = __NFTNL_EXPR_MT_MAX - 1, + .attr_policy = match_attr_policy, .free = nftnl_expr_match_free, .set = nftnl_expr_match_set, .get = nftnl_expr_match_get, .parse = nftnl_expr_match_parse, .build = nftnl_expr_match_build, - .snprintf = nftnl_expr_match_snprintf, + .output = nftnl_expr_match_snprintf, }; diff --git a/src/expr/meta.c b/src/expr/meta.c index 6ed8ee5..136a450 100644 --- a/src/expr/meta.c +++ b/src/expr/meta.c @@ -22,7 +22,7 @@ #include <libnftnl/rule.h> #ifndef NFT_META_MAX -#define NFT_META_MAX (NFT_META_SDIFNAME + 1) +#define NFT_META_MAX (NFT_META_BRI_BROUTE + 1) #endif struct nftnl_expr_meta { @@ -39,16 +39,14 @@ nftnl_expr_meta_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_META_KEY: - memcpy(&meta->key, data, sizeof(meta->key)); + memcpy(&meta->key, data, data_len); break; case NFTNL_EXPR_META_DREG: - memcpy(&meta->dreg, data, sizeof(meta->dreg)); + memcpy(&meta->dreg, data, data_len); break; case NFTNL_EXPR_META_SREG: - memcpy(&meta->sreg, data, sizeof(meta->sreg)); + memcpy(&meta->sreg, data, data_len); break; - default: - return -1; } return 0; } @@ -168,6 +166,7 @@ static const char *meta_key2str_array[NFT_META_MAX] = { [NFT_META_TIME_HOUR] = "hour", [NFT_META_SDIF] = "sdif", [NFT_META_SDIFNAME] = "sdifname", + [NFT_META_BRI_BROUTE] = "broute", }; static const char *meta_key2str(uint8_t key) @@ -192,8 +191,8 @@ static inline int str2meta_key(const char *str) } static int -nftnl_expr_meta_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +nftnl_expr_meta_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_meta *meta = nftnl_expr_data(e); @@ -208,28 +207,20 @@ nftnl_expr_meta_snprintf_default(char *buf, size_t len, return 0; } -static int -nftnl_expr_meta_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_meta_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy meta_attr_policy[__NFTNL_EXPR_META_MAX] = { + [NFTNL_EXPR_META_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_META_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_META_SREG] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_meta = { .name = "meta", .alloc_len = sizeof(struct nftnl_expr_meta), - .max_attr = NFTA_META_MAX, + .nftnl_max_attr = __NFTNL_EXPR_META_MAX - 1, + .attr_policy = meta_attr_policy, .set = nftnl_expr_meta_set, .get = nftnl_expr_meta_get, .parse = nftnl_expr_meta_parse, .build = nftnl_expr_meta_build, - .snprintf = nftnl_expr_meta_snprintf, + .output = nftnl_expr_meta_snprintf, }; diff --git a/src/expr/nat.c b/src/expr/nat.c index 4085216..1235ba4 100644 --- a/src/expr/nat.c +++ b/src/expr/nat.c @@ -42,28 +42,26 @@ nftnl_expr_nat_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_NAT_TYPE: - memcpy(&nat->type, data, sizeof(nat->type)); + memcpy(&nat->type, data, data_len); break; case NFTNL_EXPR_NAT_FAMILY: - memcpy(&nat->family, data, sizeof(nat->family)); + memcpy(&nat->family, data, data_len); break; case NFTNL_EXPR_NAT_REG_ADDR_MIN: - memcpy(&nat->sreg_addr_min, data, sizeof(nat->sreg_addr_min)); + memcpy(&nat->sreg_addr_min, data, data_len); break; case NFTNL_EXPR_NAT_REG_ADDR_MAX: - memcpy(&nat->sreg_addr_max, data, sizeof(nat->sreg_addr_max)); + memcpy(&nat->sreg_addr_max, data, data_len); break; case NFTNL_EXPR_NAT_REG_PROTO_MIN: - memcpy(&nat->sreg_proto_min, data, sizeof(nat->sreg_proto_min)); + memcpy(&nat->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_NAT_REG_PROTO_MAX: - memcpy(&nat->sreg_proto_max, data, sizeof(nat->sreg_proto_max)); + memcpy(&nat->sreg_proto_max, data, data_len); break; case NFTNL_EXPR_NAT_FLAGS: - memcpy(&nat->flags, data, sizeof(nat->flags)); + memcpy(&nat->flags, data, data_len); break; - default: - return -1; } return 0; @@ -221,11 +219,11 @@ static inline int nftnl_str2nat(const char *nat) } static int -nftnl_expr_nat_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_nat_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_nat *nat = nftnl_expr_data(e); - int remain = size, offset = 0, ret = 0; + int offset = 0, ret = 0; ret = snprintf(buf, remain, "%s ", nat2str(nat->type)); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -236,15 +234,25 @@ nftnl_expr_nat_snprintf_default(char *buf, size_t size, if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) { ret = snprintf(buf + offset, remain, - "addr_min reg %u addr_max reg %u ", - nat->sreg_addr_min, nat->sreg_addr_max); + "addr_min reg %u ", nat->sreg_addr_min); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + + if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX)) { + ret = snprintf(buf + offset, remain, + "addr_max reg %u ", nat->sreg_addr_max); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) { ret = snprintf(buf + offset, remain, - "proto_min reg %u proto_max reg %u ", - nat->sreg_proto_min, nat->sreg_proto_max); + "proto_min reg %u ", nat->sreg_proto_min); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + + if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX)) { + ret = snprintf(buf + offset, remain, + "proto_max reg %u ", nat->sreg_proto_max); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -256,28 +264,24 @@ nftnl_expr_nat_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_nat_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_nat_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy nat_attr_policy[__NFTNL_EXPR_NAT_MAX] = { + [NFTNL_EXPR_NAT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_FAMILY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_ADDR_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_ADDR_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NAT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_nat = { .name = "nat", .alloc_len = sizeof(struct nftnl_expr_nat), - .max_attr = NFTA_NAT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_NAT_MAX - 1, + .attr_policy = nat_attr_policy, .set = nftnl_expr_nat_set, .get = nftnl_expr_nat_get, .parse = nftnl_expr_nat_parse, .build = nftnl_expr_nat_build, - .snprintf = nftnl_expr_nat_snprintf, + .output = nftnl_expr_nat_snprintf, }; diff --git a/src/expr/numgen.c b/src/expr/numgen.c index 4e0d541..c015b88 100644 --- a/src/expr/numgen.c +++ b/src/expr/numgen.c @@ -35,16 +35,16 @@ nftnl_expr_ng_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_NG_DREG: - memcpy(&ng->dreg, data, sizeof(ng->dreg)); + memcpy(&ng->dreg, data, data_len); break; case NFTNL_EXPR_NG_MODULUS: - memcpy(&ng->modulus, data, sizeof(ng->modulus)); + memcpy(&ng->modulus, data, data_len); break; case NFTNL_EXPR_NG_TYPE: - memcpy(&ng->type, data, sizeof(ng->type)); + memcpy(&ng->type, data, data_len); break; case NFTNL_EXPR_NG_OFFSET: - memcpy(&ng->offset, data, sizeof(ng->offset)); + memcpy(&ng->offset, data, data_len); break; default: return -1; @@ -143,11 +143,11 @@ nftnl_expr_ng_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_ng_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_ng_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_ng *ng = nftnl_expr_data(e); - int remain = size, offset = 0, ret; + int offset = 0, ret; switch (ng->type) { case NFT_NG_INCREMENTAL: @@ -172,28 +172,21 @@ nftnl_expr_ng_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_ng_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_ng_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy numgen_attr_policy[__NFTNL_EXPR_NG_MAX] = { + [NFTNL_EXPR_NG_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_MODULUS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_NG_OFFSET] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_ng = { .name = "numgen", .alloc_len = sizeof(struct nftnl_expr_ng), - .max_attr = NFTA_NG_MAX, + .nftnl_max_attr = __NFTNL_EXPR_NG_MAX - 1, + .attr_policy = numgen_attr_policy, .set = nftnl_expr_ng_set, .get = nftnl_expr_ng_get, .parse = nftnl_expr_ng_parse, .build = nftnl_expr_ng_build, - .snprintf = nftnl_expr_ng_snprintf, + .output = nftnl_expr_ng_snprintf, }; diff --git a/src/expr/objref.c b/src/expr/objref.c index 2eb5c47..0053805 100644 --- a/src/expr/objref.c +++ b/src/expr/objref.c @@ -39,7 +39,7 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_OBJREF_IMM_TYPE: - memcpy(&objref->imm.type, data, sizeof(objref->imm.type)); + memcpy(&objref->imm.type, data, data_len); break; case NFTNL_EXPR_OBJREF_IMM_NAME: objref->imm.name = strdup(data); @@ -47,7 +47,7 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_OBJREF_SET_SREG: - memcpy(&objref->set.sreg, data, sizeof(objref->set.sreg)); + memcpy(&objref->set.sreg, data, data_len); break; case NFTNL_EXPR_OBJREF_SET_NAME: objref->set.name = strdup(data); @@ -55,10 +55,8 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type, return -1; break; case NFTNL_EXPR_OBJREF_SET_ID: - memcpy(&objref->set.id, data, sizeof(objref->set.id)); + memcpy(&objref->set.id, data, data_len); break; - default: - return -1; } return 0; } @@ -174,8 +172,9 @@ static int nftnl_expr_objref_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_objref_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int nftnl_expr_objref_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_expr *e) { struct nftnl_expr_objref *objref = nftnl_expr_data(e); @@ -195,29 +194,23 @@ static void nftnl_expr_objref_free(const struct nftnl_expr *e) xfree(objref->set.name); } -static int nftnl_expr_objref_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_objref_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy objref_attr_policy[__NFTNL_EXPR_OBJREF_MAX] = { + [NFTNL_EXPR_OBJREF_IMM_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OBJREF_IMM_NAME] = { .maxlen = NFT_NAME_MAXLEN }, + [NFTNL_EXPR_OBJREF_SET_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OBJREF_SET_NAME] = { .maxlen = NFT_NAME_MAXLEN }, + [NFTNL_EXPR_OBJREF_SET_ID] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_objref = { .name = "objref", .alloc_len = sizeof(struct nftnl_expr_objref), - .max_attr = NFTA_OBJREF_MAX, + .nftnl_max_attr = __NFTNL_EXPR_OBJREF_MAX - 1, + .attr_policy = objref_attr_policy, .free = nftnl_expr_objref_free, .set = nftnl_expr_objref_set, .get = nftnl_expr_objref_get, .parse = nftnl_expr_objref_parse, .build = nftnl_expr_objref_build, - .snprintf = nftnl_expr_objref_snprintf, + .output = nftnl_expr_objref_snprintf, }; diff --git a/src/expr/osf.c b/src/expr/osf.c index 98d0df9..060394b 100644 --- a/src/expr/osf.c +++ b/src/expr/osf.c @@ -25,13 +25,13 @@ static int nftnl_expr_osf_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_OSF_DREG: - memcpy(&osf->dreg, data, sizeof(osf->dreg)); + memcpy(&osf->dreg, data, data_len); break; case NFTNL_EXPR_OSF_TTL: - memcpy(&osf->ttl, data, sizeof(osf->ttl)); + memcpy(&osf->ttl, data, data_len); break; case NFTNL_EXPR_OSF_FLAGS: - memcpy(&osf->flags, data, sizeof(osf->flags)); + memcpy(&osf->flags, data, data_len); break; } return 0; @@ -124,11 +124,12 @@ nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_osf_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_osf_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_osf *osf = nftnl_expr_data(e); - int ret, offset = 0, len = size; + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_OSF_DREG)) { ret = snprintf(buf, len, "dreg %u ", osf->dreg); @@ -138,28 +139,20 @@ static int nftnl_expr_osf_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_osf_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_osf_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy osf_attr_policy[__NFTNL_EXPR_OSF_MAX] = { + [NFTNL_EXPR_OSF_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_OSF_TTL] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_OSF_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_osf = { .name = "osf", .alloc_len = sizeof(struct nftnl_expr_osf), - .max_attr = NFTA_OSF_MAX, + .nftnl_max_attr = __NFTNL_EXPR_OSF_MAX - 1, + .attr_policy = osf_attr_policy, .set = nftnl_expr_osf_set, .get = nftnl_expr_osf_get, .parse = nftnl_expr_osf_parse, .build = nftnl_expr_osf_build, - .snprintf = nftnl_expr_osf_snprintf, + .output = nftnl_expr_osf_snprintf, }; diff --git a/src/expr/payload.c b/src/expr/payload.c index 2192dad..35cd10c 100644 --- a/src/expr/payload.c +++ b/src/expr/payload.c @@ -43,31 +43,29 @@ nftnl_expr_payload_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_PAYLOAD_SREG: - memcpy(&payload->sreg, data, sizeof(payload->sreg)); + memcpy(&payload->sreg, data, data_len); break; case NFTNL_EXPR_PAYLOAD_DREG: - memcpy(&payload->dreg, data, sizeof(payload->dreg)); + memcpy(&payload->dreg, data, data_len); break; case NFTNL_EXPR_PAYLOAD_BASE: - memcpy(&payload->base, data, sizeof(payload->base)); + memcpy(&payload->base, data, data_len); break; case NFTNL_EXPR_PAYLOAD_OFFSET: - memcpy(&payload->offset, data, sizeof(payload->offset)); + memcpy(&payload->offset, data, data_len); break; case NFTNL_EXPR_PAYLOAD_LEN: - memcpy(&payload->len, data, sizeof(payload->len)); + memcpy(&payload->len, data, data_len); break; case NFTNL_EXPR_PAYLOAD_CSUM_TYPE: - memcpy(&payload->csum_type, data, sizeof(payload->csum_type)); + memcpy(&payload->csum_type, data, data_len); break; case NFTNL_EXPR_PAYLOAD_CSUM_OFFSET: - memcpy(&payload->csum_offset, data, sizeof(payload->csum_offset)); + memcpy(&payload->csum_offset, data, data_len); break; case NFTNL_EXPR_PAYLOAD_FLAGS: - memcpy(&payload->csum_flags, data, sizeof(payload->csum_flags)); + memcpy(&payload->csum_flags, data, data_len); break; - default: - return -1; } return 0; } @@ -203,68 +201,60 @@ nftnl_expr_payload_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static const char *base2str_array[NFT_PAYLOAD_TRANSPORT_HEADER+1] = { +static const char *base2str_array[NFT_PAYLOAD_TUN_HEADER + 1] = { [NFT_PAYLOAD_LL_HEADER] = "link", [NFT_PAYLOAD_NETWORK_HEADER] = "network", [NFT_PAYLOAD_TRANSPORT_HEADER] = "transport", + [NFT_PAYLOAD_INNER_HEADER] = "inner", + [NFT_PAYLOAD_TUN_HEADER] = "tunnel", }; static const char *base2str(enum nft_payload_bases base) { - if (base > NFT_PAYLOAD_TRANSPORT_HEADER) + if (base > NFT_PAYLOAD_INNER_HEADER) return "unknown"; return base2str_array[base]; } -static inline int nftnl_str2base(const char *base) -{ - if (strcmp(base, "link") == 0) - return NFT_PAYLOAD_LL_HEADER; - else if (strcmp(base, "network") == 0) - return NFT_PAYLOAD_NETWORK_HEADER; - else if (strcmp(base, "transport") == 0) - return NFT_PAYLOAD_TRANSPORT_HEADER; - else { - errno = EINVAL; - return -1; - } -} - static int -nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t type, +nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_payload *payload = nftnl_expr_data(e); - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - if (payload->sreg) - return snprintf(buf, len, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ", - payload->sreg, - payload->len, base2str(payload->base), - payload->offset, payload->csum_type, - payload->csum_offset, - payload->csum_flags); - else - return snprintf(buf, len, "load %ub @ %s header + %u => reg %u ", - payload->len, base2str(payload->base), - payload->offset, payload->dreg); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; + if (payload->sreg) + return snprintf(buf, len, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ", + payload->sreg, + payload->len, base2str(payload->base), + payload->offset, payload->csum_type, + payload->csum_offset, + payload->csum_flags); + else + return snprintf(buf, len, "load %ub @ %s header + %u => reg %u ", + payload->len, base2str(payload->base), + payload->offset, payload->dreg); } +static struct attr_policy payload_attr_policy[__NFTNL_EXPR_PAYLOAD_MAX] = { + [NFTNL_EXPR_PAYLOAD_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_BASE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_LEN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_CSUM_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_CSUM_OFFSET] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_PAYLOAD_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_payload = { .name = "payload", .alloc_len = sizeof(struct nftnl_expr_payload), - .max_attr = NFTA_PAYLOAD_MAX, + .nftnl_max_attr = __NFTNL_EXPR_PAYLOAD_MAX - 1, + .attr_policy = payload_attr_policy, .set = nftnl_expr_payload_set, .get = nftnl_expr_payload_get, .parse = nftnl_expr_payload_parse, .build = nftnl_expr_payload_build, - .snprintf = nftnl_expr_payload_snprintf, + .output = nftnl_expr_payload_snprintf, }; diff --git a/src/expr/queue.c b/src/expr/queue.c index 051ef71..09220c4 100644 --- a/src/expr/queue.c +++ b/src/expr/queue.c @@ -34,19 +34,17 @@ static int nftnl_expr_queue_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_QUEUE_NUM: - memcpy(&queue->queuenum, data, sizeof(queue->queuenum)); + memcpy(&queue->queuenum, data, data_len); break; case NFTNL_EXPR_QUEUE_TOTAL: - memcpy(&queue->queues_total, data, sizeof(queue->queues_total)); + memcpy(&queue->queues_total, data, data_len); break; case NFTNL_EXPR_QUEUE_FLAGS: - memcpy(&queue->flags, data, sizeof(queue->flags)); + memcpy(&queue->flags, data, data_len); break; case NFTNL_EXPR_QUEUE_SREG_QNUM: - memcpy(&queue->sreg_qnum, data, sizeof(queue->sreg_qnum)); + memcpy(&queue->sreg_qnum, data, data_len); break; - default: - return -1; } return 0; } @@ -143,69 +141,63 @@ nftnl_expr_queue_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_queue_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int +nftnl_expr_queue_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_queue *queue = nftnl_expr_data(e); - int ret, remain = len, offset = 0; uint16_t total_queues; + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_QUEUE_NUM)) { total_queues = queue->queuenum + queue->queues_total - 1; - ret = snprintf(buf + offset, len, "num %u", queue->queuenum); + ret = snprintf(buf + offset, remain, "num %u", queue->queuenum); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (queue->queues_total && total_queues != queue->queuenum) { - ret = snprintf(buf + offset, len, "-%u", total_queues); + ret = snprintf(buf + offset, remain, "-%u", total_queues); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, len, " "); + ret = snprintf(buf + offset, remain, " "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM)) { - ret = snprintf(buf + offset, len, "sreg_qnum %u ", + ret = snprintf(buf + offset, remain, "sreg_qnum %u ", queue->sreg_qnum); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS)) { if (queue->flags & (NFT_QUEUE_FLAG_BYPASS)) { - ret = snprintf(buf + offset, len, "bypass "); + ret = snprintf(buf + offset, remain, "bypass "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (queue->flags & (NFT_QUEUE_FLAG_CPU_FANOUT)) { - ret = snprintf(buf + offset, len, "fanout "); + ret = snprintf(buf + offset, remain, "fanout "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } } return offset; } -static int -nftnl_expr_queue_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_queue_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy queue_attr_policy[__NFTNL_EXPR_QUEUE_MAX] = { + [NFTNL_EXPR_QUEUE_NUM] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_TOTAL] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_FLAGS] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_QUEUE_SREG_QNUM] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_queue = { .name = "queue", .alloc_len = sizeof(struct nftnl_expr_queue), - .max_attr = NFTA_QUEUE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_QUEUE_MAX - 1, + .attr_policy = queue_attr_policy, .set = nftnl_expr_queue_set, .get = nftnl_expr_queue_get, .parse = nftnl_expr_queue_parse, .build = nftnl_expr_queue_build, - .snprintf = nftnl_expr_queue_snprintf, + .output = nftnl_expr_queue_snprintf, }; diff --git a/src/expr/quota.c b/src/expr/quota.c index 39a92e6..ddf232f 100644 --- a/src/expr/quota.c +++ b/src/expr/quota.c @@ -33,16 +33,14 @@ static int nftnl_expr_quota_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_QUOTA_BYTES: - memcpy("a->bytes, data, sizeof(quota->bytes)); + memcpy("a->bytes, data, data_len); break; case NFTNL_EXPR_QUOTA_CONSUMED: - memcpy("a->consumed, data, sizeof(quota->consumed)); + memcpy("a->consumed, data, data_len); break; case NFTNL_EXPR_QUOTA_FLAGS: - memcpy("a->flags, data, sizeof(quota->flags)); + memcpy("a->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -128,8 +126,9 @@ nftnl_expr_quota_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_quota_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int nftnl_expr_quota_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_expr *e) { struct nftnl_expr_quota *quota = nftnl_expr_data(e); @@ -138,28 +137,20 @@ static int nftnl_expr_quota_snprintf_default(char *buf, size_t len, quota->bytes, quota->consumed, quota->flags); } -static int nftnl_expr_quota_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_quota_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy quota_attr_policy[__NFTNL_EXPR_QUOTA_MAX] = { + [NFTNL_EXPR_QUOTA_BYTES] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_EXPR_QUOTA_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_QUOTA_CONSUMED] = { .maxlen = sizeof(uint64_t) }, +}; struct expr_ops expr_ops_quota = { .name = "quota", .alloc_len = sizeof(struct nftnl_expr_quota), - .max_attr = NFTA_QUOTA_MAX, + .nftnl_max_attr = __NFTNL_EXPR_QUOTA_MAX - 1, + .attr_policy = quota_attr_policy, .set = nftnl_expr_quota_set, .get = nftnl_expr_quota_get, .parse = nftnl_expr_quota_parse, .build = nftnl_expr_quota_build, - .snprintf = nftnl_expr_quota_snprintf, + .output = nftnl_expr_quota_snprintf, }; diff --git a/src/expr/range.c b/src/expr/range.c index d1d5083..96bb140 100644 --- a/src/expr/range.c +++ b/src/expr/range.c @@ -34,21 +34,15 @@ static int nftnl_expr_range_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_RANGE_SREG: - memcpy(&range->sreg, data, sizeof(range->sreg)); + memcpy(&range->sreg, data, data_len); break; case NFTNL_EXPR_RANGE_OP: - memcpy(&range->op, data, sizeof(range->op)); + memcpy(&range->op, data, data_len); break; case NFTNL_EXPR_RANGE_FROM_DATA: - memcpy(&range->data_from.val, data, data_len); - range->data_from.len = data_len; - break; + return nftnl_data_cpy(&range->data_from, data, data_len); case NFTNL_EXPR_RANGE_TO_DATA: - memcpy(&range->data_to.val, data, data_len); - range->data_to.len = data_len; - break; - default: - return -1; + return nftnl_data_cpy(&range->data_to, data, data_len); } return 0; } @@ -184,48 +178,42 @@ static inline int nftnl_str2range(const char *op) } } -static int nftnl_expr_range_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int nftnl_expr_range_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_range *range = nftnl_expr_data(e); - int remain = size, offset = 0, ret; + int offset = 0, ret; ret = snprintf(buf, remain, "%s reg %u ", range2str(range->op), range->sreg); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_from, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_to, - NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE); + 0, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } -static int nftnl_expr_range_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_range_snprintf_default(buf, size, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy range_attr_policy[__NFTNL_EXPR_RANGE_MAX] = { + [NFTNL_EXPR_RANGE_SREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RANGE_OP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RANGE_FROM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_RANGE_TO_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, +}; struct expr_ops expr_ops_range = { .name = "range", .alloc_len = sizeof(struct nftnl_expr_range), - .max_attr = NFTA_RANGE_MAX, + .nftnl_max_attr = __NFTNL_EXPR_RANGE_MAX - 1, + .attr_policy = range_attr_policy, .set = nftnl_expr_range_set, .get = nftnl_expr_range_get, .parse = nftnl_expr_range_parse, .build = nftnl_expr_range_build, - .snprintf = nftnl_expr_range_snprintf, + .output = nftnl_expr_range_snprintf, }; diff --git a/src/expr/redir.c b/src/expr/redir.c index 477659a..9971306 100644 --- a/src/expr/redir.c +++ b/src/expr/redir.c @@ -34,16 +34,14 @@ nftnl_expr_redir_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_REDIR_REG_PROTO_MIN: - memcpy(&redir->sreg_proto_min, data, sizeof(redir->sreg_proto_min)); + memcpy(&redir->sreg_proto_min, data, data_len); break; case NFTNL_EXPR_REDIR_REG_PROTO_MAX: - memcpy(&redir->sreg_proto_max, data, sizeof(redir->sreg_proto_max)); + memcpy(&redir->sreg_proto_max, data, data_len); break; case NFTNL_EXPR_REDIR_FLAGS: - memcpy(&redir->flags, data, sizeof(redir->flags)); + memcpy(&redir->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -131,26 +129,27 @@ nftnl_expr_redir_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_redir_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int +nftnl_expr_redir_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { - int ret, remain = len, offset = 0; + int ret, offset = 0; struct nftnl_expr_redir *redir = nftnl_expr_data(e); if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MIN)) { - ret = snprintf(buf + offset, len, "proto_min reg %u ", + ret = snprintf(buf + offset, remain, "proto_min reg %u ", redir->sreg_proto_min); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MAX)) { - ret = snprintf(buf + offset, len, "proto_max reg %u ", + ret = snprintf(buf + offset, remain, "proto_max reg %u ", redir->sreg_proto_max); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_FLAGS)) { - ret = snprintf(buf + offset, len, "flags 0x%x ", + ret = snprintf(buf + offset, remain, "flags 0x%x ", redir->flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -158,28 +157,20 @@ static int nftnl_expr_redir_snprintf_default(char *buf, size_t len, return offset; } -static int -nftnl_expr_redir_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_redir_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy redir_attr_policy[__NFTNL_EXPR_REDIR_MAX] = { + [NFTNL_EXPR_REDIR_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REDIR_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REDIR_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_redir = { .name = "redir", .alloc_len = sizeof(struct nftnl_expr_redir), - .max_attr = NFTA_REDIR_MAX, + .nftnl_max_attr = __NFTNL_EXPR_REDIR_MAX - 1, + .attr_policy = redir_attr_policy, .set = nftnl_expr_redir_set, .get = nftnl_expr_redir_get, .parse = nftnl_expr_redir_parse, .build = nftnl_expr_redir_build, - .snprintf = nftnl_expr_redir_snprintf, + .output = nftnl_expr_redir_snprintf, }; diff --git a/src/expr/reject.c b/src/expr/reject.c index 141942e..9090db3 100644 --- a/src/expr/reject.c +++ b/src/expr/reject.c @@ -33,13 +33,11 @@ static int nftnl_expr_reject_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_REJECT_TYPE: - memcpy(&reject->type, data, sizeof(reject->type)); + memcpy(&reject->type, data, data_len); break; case NFTNL_EXPR_REJECT_CODE: - memcpy(&reject->icmp_code, data, sizeof(reject->icmp_code)); + memcpy(&reject->icmp_code, data, data_len); break; - default: - return -1; } return 0; } @@ -116,8 +114,9 @@ nftnl_expr_reject_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_reject_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +static int +nftnl_expr_reject_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_reject *reject = nftnl_expr_data(e); @@ -125,28 +124,19 @@ static int nftnl_expr_reject_snprintf_default(char *buf, size_t len, reject->type, reject->icmp_code); } -static int -nftnl_expr_reject_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_reject_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy reject_attr_policy[__NFTNL_EXPR_REJECT_MAX] = { + [NFTNL_EXPR_REJECT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_REJECT_CODE] = { .maxlen = sizeof(uint8_t) }, +}; struct expr_ops expr_ops_reject = { .name = "reject", .alloc_len = sizeof(struct nftnl_expr_reject), - .max_attr = NFTA_REJECT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_REJECT_MAX - 1, + .attr_policy = reject_attr_policy, .set = nftnl_expr_reject_set, .get = nftnl_expr_reject_get, .parse = nftnl_expr_reject_parse, .build = nftnl_expr_reject_build, - .snprintf = nftnl_expr_reject_snprintf, + .output = nftnl_expr_reject_snprintf, }; diff --git a/src/expr/rt.c b/src/expr/rt.c index 0fce72d..ff4fd03 100644 --- a/src/expr/rt.c +++ b/src/expr/rt.c @@ -32,13 +32,11 @@ nftnl_expr_rt_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_RT_KEY: - memcpy(&rt->key, data, sizeof(rt->key)); + memcpy(&rt->key, data, data_len); break; case NFTNL_EXPR_RT_DREG: - memcpy(&rt->dreg, data, sizeof(rt->dreg)); + memcpy(&rt->dreg, data, data_len); break; - default: - return -1; } return 0; } @@ -142,8 +140,8 @@ static inline int str2rt_key(const char *str) } static int -nftnl_expr_rt_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +nftnl_expr_rt_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_rt *rt = nftnl_expr_data(e); @@ -154,28 +152,19 @@ nftnl_expr_rt_snprintf_default(char *buf, size_t len, return 0; } -static int -nftnl_expr_rt_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_rt_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy rt_attr_policy[__NFTNL_EXPR_RT_MAX] = { + [NFTNL_EXPR_RT_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_RT_DREG] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_rt = { .name = "rt", .alloc_len = sizeof(struct nftnl_expr_rt), - .max_attr = NFTA_RT_MAX, + .nftnl_max_attr = __NFTNL_EXPR_RT_MAX - 1, + .attr_policy = rt_attr_policy, .set = nftnl_expr_rt_set, .get = nftnl_expr_rt_get, .parse = nftnl_expr_rt_parse, .build = nftnl_expr_rt_build, - .snprintf = nftnl_expr_rt_snprintf, + .output = nftnl_expr_rt_snprintf, }; diff --git a/src/expr/socket.c b/src/expr/socket.c index 96550d5..7a25cdf 100644 --- a/src/expr/socket.c +++ b/src/expr/socket.c @@ -22,6 +22,7 @@ struct nftnl_expr_socket { enum nft_socket_keys key; enum nft_registers dreg; + uint32_t level; }; static int @@ -32,13 +33,14 @@ nftnl_expr_socket_set(struct nftnl_expr *e, uint16_t type, switch (type) { case NFTNL_EXPR_SOCKET_KEY: - memcpy(&socket->key, data, sizeof(socket->key)); + memcpy(&socket->key, data, data_len); break; case NFTNL_EXPR_SOCKET_DREG: - memcpy(&socket->dreg, data, sizeof(socket->dreg)); + memcpy(&socket->dreg, data, data_len); + break; + case NFTNL_EXPR_SOCKET_LEVEL: + memcpy(&socket->level, data, data_len); break; - default: - return -1; } return 0; } @@ -56,6 +58,9 @@ nftnl_expr_socket_get(const struct nftnl_expr *e, uint16_t type, case NFTNL_EXPR_SOCKET_DREG: *data_len = sizeof(socket->dreg); return &socket->dreg; + case NFTNL_EXPR_SOCKET_LEVEL: + *data_len = sizeof(socket->level); + return &socket->level; } return NULL; } @@ -71,6 +76,7 @@ static int nftnl_expr_socket_cb(const struct nlattr *attr, void *data) switch (type) { case NFTA_SOCKET_KEY: case NFTA_SOCKET_DREG: + case NFTA_SOCKET_LEVEL: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) abi_breakage(); break; @@ -89,6 +95,8 @@ nftnl_expr_socket_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) mnl_attr_put_u32(nlh, NFTA_SOCKET_KEY, htonl(socket->key)); if (e->flags & (1 << NFTNL_EXPR_SOCKET_DREG)) mnl_attr_put_u32(nlh, NFTA_SOCKET_DREG, htonl(socket->dreg)); + if (e->flags & (1 << NFTNL_EXPR_SOCKET_LEVEL)) + mnl_attr_put_u32(nlh, NFTA_SOCKET_LEVEL, htonl(socket->level)); } static int @@ -108,6 +116,10 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr) socket->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_DREG])); e->flags |= (1 << NFTNL_EXPR_SOCKET_DREG); } + if (tb[NFTA_SOCKET_LEVEL]) { + socket->level = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_LEVEL])); + e->flags |= (1 << NFTNL_EXPR_SOCKET_LEVEL); + } return 0; } @@ -115,6 +127,8 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr) static const char *socket_key2str_array[NFT_SOCKET_MAX + 1] = { [NFT_SOCKET_TRANSPARENT] = "transparent", [NFT_SOCKET_MARK] = "mark", + [NFT_SOCKET_WILDCARD] = "wildcard", + [NFT_SOCKET_CGROUPV2] = "cgroupv2", }; static const char *socket_key2str(uint8_t key) @@ -125,22 +139,9 @@ static const char *socket_key2str(uint8_t key) return "unknown"; } -static inline int str2socket_key(const char *str) -{ - int i; - - for (i = 0; i < NFT_SOCKET_MAX + 1; i++) { - if (strcmp(str, socket_key2str_array[i]) == 0) - return i; - } - - errno = EINVAL; - return -1; -} - static int -nftnl_expr_socket_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +nftnl_expr_socket_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_socket *socket = nftnl_expr_data(e); @@ -148,31 +149,26 @@ nftnl_expr_socket_snprintf_default(char *buf, size_t len, return snprintf(buf, len, "load %s => reg %u ", socket_key2str(socket->key), socket->dreg); } + if (e->flags & (1 << NFTNL_EXPR_SOCKET_LEVEL)) + return snprintf(buf, len, "level %u ", socket->level); + return 0; } -static int -nftnl_expr_socket_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_socket_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy socket_attr_policy[__NFTNL_EXPR_SOCKET_MAX] = { + [NFTNL_EXPR_SOCKET_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_SOCKET_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_SOCKET_LEVEL] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_socket = { .name = "socket", .alloc_len = sizeof(struct nftnl_expr_socket), - .max_attr = NFTA_SOCKET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_SOCKET_MAX - 1, + .attr_policy = socket_attr_policy, .set = nftnl_expr_socket_set, .get = nftnl_expr_socket_get, .parse = nftnl_expr_socket_parse, .build = nftnl_expr_socket_build, - .snprintf = nftnl_expr_socket_snprintf, + .output = nftnl_expr_socket_snprintf, }; diff --git a/src/expr/synproxy.c b/src/expr/synproxy.c index 245f4fb..97c321b 100644 --- a/src/expr/synproxy.c +++ b/src/expr/synproxy.c @@ -23,13 +23,13 @@ static int nftnl_expr_synproxy_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_SYNPROXY_MSS: - memcpy(&synproxy->mss, data, sizeof(synproxy->mss)); + memcpy(&synproxy->mss, data, data_len); break; case NFTNL_EXPR_SYNPROXY_WSCALE: - memcpy(&synproxy->wscale, data, sizeof(synproxy->wscale)); + memcpy(&synproxy->wscale, data, data_len); break; case NFTNL_EXPR_SYNPROXY_FLAGS: - memcpy(&synproxy->flags, data, sizeof(synproxy->flags)); + memcpy(&synproxy->flags, data, data_len); break; } return 0; @@ -127,11 +127,12 @@ nftnl_expr_synproxy_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static int nftnl_expr_synproxy_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +static int +nftnl_expr_synproxy_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_synproxy *synproxy = nftnl_expr_data(e); - int ret, offset = 0, len = size; + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_SYNPROXY_MSS) && e->flags & (1 << NFTNL_EXPR_SYNPROXY_WSCALE)) { @@ -143,28 +144,20 @@ static int nftnl_expr_synproxy_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_synproxy_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_synproxy_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy synproxy_attr_policy[__NFTNL_EXPR_SYNPROXY_MAX] = { + [NFTNL_EXPR_SYNPROXY_MSS] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_EXPR_SYNPROXY_WSCALE] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_SYNPROXY_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_synproxy = { .name = "synproxy", .alloc_len = sizeof(struct nftnl_expr_synproxy), - .max_attr = NFTA_SYNPROXY_MAX, + .nftnl_max_attr = __NFTNL_EXPR_SYNPROXY_MAX - 1, + .attr_policy = synproxy_attr_policy, .set = nftnl_expr_synproxy_set, .get = nftnl_expr_synproxy_get, .parse = nftnl_expr_synproxy_parse, .build = nftnl_expr_synproxy_build, - .snprintf = nftnl_expr_synproxy_snprintf, + .output = nftnl_expr_synproxy_snprintf, }; diff --git a/src/expr/target.c b/src/expr/target.c index 9100038..8259a20 100644 --- a/src/expr/target.c +++ b/src/expr/target.c @@ -46,7 +46,7 @@ nftnl_expr_target_set(struct nftnl_expr *e, uint16_t type, (const char *) data); break; case NFTNL_EXPR_TG_REV: - memcpy(&tg->rev, data, sizeof(tg->rev)); + memcpy(&tg->rev, data, data_len); break; case NFTNL_EXPR_TG_INFO: if (e->flags & (1 << NFTNL_EXPR_TG_INFO)) @@ -55,8 +55,6 @@ nftnl_expr_target_set(struct nftnl_expr *e, uint16_t type, tg->data = data; tg->data_len = data_len; break; - default: - return -1; } return 0; } @@ -165,21 +163,12 @@ static int nftnl_expr_target_parse(struct nftnl_expr *e, struct nlattr *attr) } static int -nftnl_expr_target_snprintf(char *buf, size_t len, uint32_t type, +nftnl_expr_target_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_target *target = nftnl_expr_data(e); - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return snprintf(buf, len, "name %s rev %u ", - target->name, target->rev); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; + return snprintf(buf, len, "name %s rev %u ", target->name, target->rev); } static void nftnl_expr_target_free(const struct nftnl_expr *e) @@ -189,14 +178,21 @@ static void nftnl_expr_target_free(const struct nftnl_expr *e) xfree(target->data); } +static struct attr_policy target_attr_policy[__NFTNL_EXPR_TG_MAX] = { + [NFTNL_EXPR_TG_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN }, + [NFTNL_EXPR_TG_REV] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TG_INFO] = { .maxlen = 0 }, +}; + struct expr_ops expr_ops_target = { .name = "target", .alloc_len = sizeof(struct nftnl_expr_target), - .max_attr = NFTA_TARGET_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TG_MAX - 1, + .attr_policy = target_attr_policy, .free = nftnl_expr_target_free, .set = nftnl_expr_target_set, .get = nftnl_expr_target_get, .parse = nftnl_expr_target_parse, .build = nftnl_expr_target_build, - .snprintf = nftnl_expr_target_snprintf, + .output = nftnl_expr_target_snprintf, }; diff --git a/src/expr/tproxy.c b/src/expr/tproxy.c index 3827b75..9391ce8 100644 --- a/src/expr/tproxy.c +++ b/src/expr/tproxy.c @@ -34,16 +34,14 @@ nftnl_expr_tproxy_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_TPROXY_FAMILY: - memcpy(&tproxy->family, data, sizeof(tproxy->family)); + memcpy(&tproxy->family, data, data_len); break; case NFTNL_EXPR_TPROXY_REG_ADDR: - memcpy(&tproxy->sreg_addr, data, sizeof(tproxy->sreg_addr)); + memcpy(&tproxy->sreg_addr, data, data_len); break; case NFTNL_EXPR_TPROXY_REG_PORT: - memcpy(&tproxy->sreg_port, data, sizeof(tproxy->sreg_port)); + memcpy(&tproxy->sreg_port, data, data_len); break; - default: - return -1; } return 0; @@ -135,11 +133,11 @@ nftnl_expr_tproxy_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) } static int -nftnl_expr_tproxy_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_tproxy_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_tproxy *tproxy = nftnl_expr_data(e); - int remain = size, offset = 0, ret = 0; + int offset = 0, ret = 0; if (tproxy->family != NFTA_TPROXY_UNSPEC) { ret = snprintf(buf + offset, remain, "%s ", @@ -162,26 +160,20 @@ nftnl_expr_tproxy_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_tproxy_snprintf(char *buf, size_t size, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_tproxy_snprintf_default(buf, size, e); - default: - break; - } - return -1; -} +static struct attr_policy tproxy_attr_policy[__NFTNL_EXPR_TPROXY_MAX] = { + [NFTNL_EXPR_TPROXY_FAMILY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TPROXY_REG_ADDR] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TPROXY_REG_PORT] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_tproxy = { .name = "tproxy", .alloc_len = sizeof(struct nftnl_expr_tproxy), - .max_attr = NFTA_TPROXY_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TPROXY_MAX - 1, + .attr_policy = tproxy_attr_policy, .set = nftnl_expr_tproxy_set, .get = nftnl_expr_tproxy_get, .parse = nftnl_expr_tproxy_parse, .build = nftnl_expr_tproxy_build, - .snprintf = nftnl_expr_tproxy_snprintf, + .output = nftnl_expr_tproxy_snprintf, }; diff --git a/src/expr/tunnel.c b/src/expr/tunnel.c index b2b8d72..861e56d 100644 --- a/src/expr/tunnel.c +++ b/src/expr/tunnel.c @@ -31,13 +31,11 @@ static int nftnl_expr_tunnel_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_TUNNEL_KEY: - memcpy(&tunnel->key, data, sizeof(tunnel->key)); + memcpy(&tunnel->key, data, data_len); break; case NFTNL_EXPR_TUNNEL_DREG: - memcpy(&tunnel->dreg, data, sizeof(tunnel->dreg)); + memcpy(&tunnel->dreg, data, data_len); break; - default: - return -1; } return 0; } @@ -124,22 +122,9 @@ static const char *tunnel_key2str(uint8_t key) return "unknown"; } -static inline int str2tunnel_key(const char *str) -{ - int i; - - for (i = 0; i <= NFT_TUNNEL_MAX; i++) { - if (strcmp(str, tunnel_key2str_array[i]) == 0) - return i; - } - - errno = EINVAL; - return -1; -} - static int -nftnl_expr_tunnel_snprintf_default(char *buf, size_t len, - const struct nftnl_expr *e) +nftnl_expr_tunnel_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e); @@ -150,28 +135,19 @@ nftnl_expr_tunnel_snprintf_default(char *buf, size_t len, return 0; } -static int -nftnl_expr_tunnel_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_tunnel_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy tunnel_attr_policy[__NFTNL_EXPR_TUNNEL_MAX] = { + [NFTNL_EXPR_TUNNEL_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_TUNNEL_DREG] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_tunnel = { .name = "tunnel", .alloc_len = sizeof(struct nftnl_expr_tunnel), - .max_attr = NFTA_TUNNEL_MAX, + .nftnl_max_attr = __NFTNL_EXPR_TUNNEL_MAX - 1, + .attr_policy = tunnel_attr_policy, .set = nftnl_expr_tunnel_set, .get = nftnl_expr_tunnel_get, .parse = nftnl_expr_tunnel_parse, .build = nftnl_expr_tunnel_build, - .snprintf = nftnl_expr_tunnel_snprintf, + .output = nftnl_expr_tunnel_snprintf, }; diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c index 8fe5438..2585579 100644 --- a/src/expr/xfrm.c +++ b/src/expr/xfrm.c @@ -33,16 +33,16 @@ nftnl_expr_xfrm_set(struct nftnl_expr *e, uint16_t type, switch(type) { case NFTNL_EXPR_XFRM_KEY: - memcpy(&x->key, data, sizeof(x->key)); + memcpy(&x->key, data, data_len); break; case NFTNL_EXPR_XFRM_DIR: - memcpy(&x->dir, data, sizeof(x->dir)); + memcpy(&x->dir, data, data_len); break; case NFTNL_EXPR_XFRM_SPNUM: - memcpy(&x->spnum, data, sizeof(x->spnum)); + memcpy(&x->spnum, data, data_len); break; case NFTNL_EXPR_XFRM_DREG: - memcpy(&x->dreg, data, sizeof(x->dreg)); + memcpy(&x->dreg, data, data_len); break; default: return -1; @@ -171,40 +171,12 @@ static const char *xfrmdir2str(uint8_t dir) return xfrmdir2str_array[dir]; } -#ifdef JSON_PARSING -static uint32_t str2xfrmkey(const char *s) -{ - int i; - - for (i = 0; - i < sizeof(xfrmkey2str_array) / sizeof(xfrmkey2str_array[0]); - i++) { - if (strcmp(xfrmkey2str_array[i], s) == 0) - return i; - } - return -1; -} - -static int str2xfmrdir(const char *s) -{ - int i; - - for (i = 0; - i < sizeof(xfrmdir2str_array) / sizeof(xfrmdir2str_array[0]); - i++) { - if (strcmp(xfrmkey2str_array[i], s) == 0) - return i; - } - return -1; -} -#endif - static int -nftnl_expr_xfrm_snprintf_default(char *buf, size_t size, - const struct nftnl_expr *e) +nftnl_expr_xfrm_snprintf(char *buf, size_t remain, + uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_xfrm *x = nftnl_expr_data(e); - int ret, remain = size, offset = 0; + int ret, offset = 0; if (e->flags & (1 << NFTNL_EXPR_XFRM_DREG)) { ret = snprintf(buf, remain, "load %s %u %s => reg %u ", @@ -216,28 +188,22 @@ nftnl_expr_xfrm_snprintf_default(char *buf, size_t size, return offset; } -static int -nftnl_expr_xfrm_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_expr *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_expr_xfrm_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy xfrm_attr_policy[__NFTNL_EXPR_XFRM_MAX] = { + [NFTNL_EXPR_XFRM_DREG] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_XFRM_SREG] = { .maxlen = 0 }, + [NFTNL_EXPR_XFRM_KEY] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_EXPR_XFRM_DIR] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_XFRM_SPNUM] = { .maxlen = sizeof(uint32_t) }, +}; struct expr_ops expr_ops_xfrm = { .name = "xfrm", .alloc_len = sizeof(struct nftnl_expr_xfrm), - .max_attr = NFTA_XFRM_MAX, + .nftnl_max_attr = __NFTNL_EXPR_XFRM_MAX - 1, + .attr_policy = xfrm_attr_policy, .set = nftnl_expr_xfrm_set, .get = nftnl_expr_xfrm_get, .parse = nftnl_expr_xfrm_parse, .build = nftnl_expr_xfrm_build, - .snprintf = nftnl_expr_xfrm_snprintf, + .output = nftnl_expr_xfrm_snprintf, }; diff --git a/src/expr_ops.c b/src/expr_ops.c index 3538dd6..b85f472 100644 --- a/src/expr_ops.c +++ b/src/expr_ops.c @@ -14,6 +14,8 @@ extern struct expr_ops expr_ops_dup; extern struct expr_ops expr_ops_exthdr; extern struct expr_ops expr_ops_fwd; extern struct expr_ops expr_ops_immediate; +extern struct expr_ops expr_ops_inner; +extern struct expr_ops expr_ops_last; extern struct expr_ops expr_ops_limit; extern struct expr_ops expr_ops_log; extern struct expr_ops expr_ops_lookup; @@ -57,6 +59,8 @@ static struct expr_ops *expr_ops[] = { &expr_ops_exthdr, &expr_ops_fwd, &expr_ops_immediate, + &expr_ops_inner, + &expr_ops_last, &expr_ops_limit, &expr_ops_log, &expr_ops_lookup, diff --git a/src/flowtable.c b/src/flowtable.c index 658115d..41a1456 100644 --- a/src/flowtable.c +++ b/src/flowtable.c @@ -102,6 +102,7 @@ static uint32_t nftnl_flowtable_validate[NFTNL_FLOWTABLE_MAX + 1] = { [NFTNL_FLOWTABLE_HOOKNUM] = sizeof(uint32_t), [NFTNL_FLOWTABLE_PRIO] = sizeof(int32_t), [NFTNL_FLOWTABLE_FAMILY] = sizeof(uint32_t), + [NFTNL_FLOWTABLE_SIZE] = sizeof(uint32_t), [NFTNL_FLOWTABLE_FLAGS] = sizeof(uint32_t), [NFTNL_FLOWTABLE_HANDLE] = sizeof(uint64_t), }; @@ -118,20 +119,11 @@ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr, switch(attr) { case NFTNL_FLOWTABLE_NAME: - if (c->flags & (1 << NFTNL_FLOWTABLE_NAME)) - xfree(c->name); - - c->name = strdup(data); - if (!c->name) - return -1; - break; + return nftnl_set_str_attr(&c->name, &c->flags, + attr, data, data_len); case NFTNL_FLOWTABLE_TABLE: - if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE)) - xfree(c->table); - - c->table = strdup(data); - if (!c->table) - return -1; + return nftnl_set_str_attr(&c->table, &c->flags, + attr, data, data_len); break; case NFTNL_FLOWTABLE_HOOKNUM: memcpy(&c->hooknum, data, sizeof(c->hooknum)); @@ -591,10 +583,10 @@ int nftnl_flowtable_parse_file(struct nftnl_flowtable *c, return -1; } -static int nftnl_flowtable_snprintf_default(char *buf, size_t size, +static int nftnl_flowtable_snprintf_default(char *buf, size_t remain, const struct nftnl_flowtable *c) { - int ret, remain = size, offset = 0, i; + int ret, offset = 0, i; ret = snprintf(buf, remain, "flow table %s %s use %u size %u flags %x", c->table, c->name, c->use, c->size, c->ft_flags); @@ -623,25 +615,18 @@ static int nftnl_flowtable_snprintf_default(char *buf, size_t size, return offset; } -static int nftnl_flowtable_cmd_snprintf(char *buf, size_t size, +static int nftnl_flowtable_cmd_snprintf(char *buf, size_t remain, const struct nftnl_flowtable *c, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_flowtable_snprintf_default(buf + offset, remain, c); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - break; - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + ret = nftnl_flowtable_snprintf_default(buf + offset, remain, c); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } @@ -156,21 +156,17 @@ int nftnl_gen_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_gen *gen) return 0; } -static int nftnl_gen_cmd_snprintf(char *buf, size_t size, +static int nftnl_gen_cmd_snprintf(char *buf, size_t remain, const struct nftnl_gen *gen, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - ret = snprintf(buf, size, "ruleset generation ID %u", gen->id); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + ret = snprintf(buf, remain, "ruleset generation ID %u", gen->id); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } diff --git a/src/libnftnl.map b/src/libnftnl.map index 6042479..8fffff1 100644 --- a/src/libnftnl.map +++ b/src/libnftnl.map @@ -47,8 +47,6 @@ global: nftnl_chain_get_s32; nftnl_chain_get_u64; nftnl_chain_get_str; - nftnl_chain_parse; - nftnl_chain_parse_file; nftnl_chain_snprintf; nftnl_chain_fprintf; nftnl_chain_nlmsg_build_payload; @@ -174,8 +172,6 @@ global: nftnl_set_elems_nlmsg_build_payload; nftnl_set_elems_nlmsg_parse; - nftnl_set_elems_foreach; - nftnl_set_elems_iter_create; nftnl_set_elems_iter_cur; nftnl_set_elems_iter_next; @@ -368,3 +364,22 @@ LIBNFTNL_14 { nftnl_flowtable_set_array; nftnl_flowtable_get_array; } LIBNFTNL_13; + +LIBNFTNL_15 { + nftnl_obj_get_data; + nftnl_expr_build_payload; + nftnl_rule_del_expr; +} LIBNFTNL_14; + +LIBNFTNL_16 { + nftnl_set_add_expr; + nftnl_set_expr_foreach; + nftnl_set_elem_add_expr; + nftnl_set_elem_expr_foreach; + nftnl_expr_add_expr; + nftnl_expr_expr_foreach; +} LIBNFTNL_15; + +LIBNFTNL_17 { + nftnl_set_elem_nlmsg_build; +} LIBNFTNL_16; diff --git a/src/obj/counter.c b/src/obj/counter.c index 1baba4e..19e09ed 100644 --- a/src/obj/counter.c +++ b/src/obj/counter.c @@ -29,13 +29,11 @@ nftnl_obj_counter_set(struct nftnl_obj *e, uint16_t type, switch(type) { case NFTNL_OBJ_CTR_BYTES: - memcpy(&ctr->bytes, data, sizeof(ctr->bytes)); + memcpy(&ctr->bytes, data, data_len); break; case NFTNL_OBJ_CTR_PKTS: - memcpy(&ctr->pkts, data, sizeof(ctr->pkts)); + memcpy(&ctr->pkts, data, data_len); break; - default: - return -1; } return 0; } @@ -109,8 +107,8 @@ nftnl_obj_counter_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_counter_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_counter *ctr = nftnl_obj_data(e); @@ -118,32 +116,20 @@ static int nftnl_obj_counter_snprintf_default(char *buf, size_t len, ctr->pkts, ctr->bytes); } -static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_counter_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_ctr_attr_policy[__NFTNL_OBJ_CTR_MAX] = { + [NFTNL_OBJ_CTR_BYTES] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_OBJ_CTR_PKTS] = { .maxlen = sizeof(uint64_t) }, +}; struct obj_ops obj_ops_counter = { .name = "counter", .type = NFT_OBJECT_COUNTER, .alloc_len = sizeof(struct nftnl_obj_counter), - .max_attr = NFTA_COUNTER_MAX, + .nftnl_max_attr = __NFTNL_OBJ_CTR_MAX - 1, + .attr_policy = obj_ctr_attr_policy, .set = nftnl_obj_counter_set, .get = nftnl_obj_counter_get, .parse = nftnl_obj_counter_parse, .build = nftnl_obj_counter_build, - .snprintf = nftnl_obj_counter_snprintf, + .output = nftnl_obj_counter_snprintf, }; diff --git a/src/obj/ct_expect.c b/src/obj/ct_expect.c index c0bb5ba..b4d6faa 100644 --- a/src/obj/ct_expect.c +++ b/src/obj/ct_expect.c @@ -21,22 +21,20 @@ static int nftnl_obj_ct_expect_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_CT_EXPECT_L3PROTO: - memcpy(&exp->l3proto, data, sizeof(exp->l3proto)); + memcpy(&exp->l3proto, data, data_len); break; case NFTNL_OBJ_CT_EXPECT_L4PROTO: - memcpy(&exp->l4proto, data, sizeof(exp->l4proto)); + memcpy(&exp->l4proto, data, data_len); break; case NFTNL_OBJ_CT_EXPECT_DPORT: - memcpy(&exp->dport, data, sizeof(exp->dport)); + memcpy(&exp->dport, data, data_len); break; case NFTNL_OBJ_CT_EXPECT_TIMEOUT: - memcpy(&exp->timeout, data, sizeof(exp->timeout)); + memcpy(&exp->timeout, data, data_len); break; case NFTNL_OBJ_CT_EXPECT_SIZE: - memcpy(&exp->size, data, sizeof(exp->size)); + memcpy(&exp->size, data, data_len); break; - default: - return -1; } return 0; } @@ -151,31 +149,35 @@ nftnl_obj_ct_expect_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_ct_expect_snprintf(char *buf, size_t remain, + uint32_t flags, + const struct nftnl_obj *e) { - int ret = 0; - int offset = 0, remain = len; struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e); + int ret = 0, offset = 0; if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) { - ret = snprintf(buf + offset, len, "family %d ", exp->l3proto); + ret = snprintf(buf + offset, remain, + "family %d ", exp->l3proto); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) { - ret = snprintf(buf + offset, len, "protocol %d ", exp->l4proto); + ret = snprintf(buf + offset, remain, + "protocol %d ", exp->l4proto); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT)) { - ret = snprintf(buf + offset, len, "dport %d ", exp->dport); + ret = snprintf(buf + offset, remain, + "dport %d ", exp->dport); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) { - ret = snprintf(buf + offset, len, "timeout %d ", exp->timeout); + ret = snprintf(buf + offset, remain, + "timeout %d ", exp->timeout); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE)) { - ret = snprintf(buf + offset, len, "size %d ", exp->size); + ret = snprintf(buf + offset, remain, "size %d ", exp->size); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -183,31 +185,24 @@ static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len, return offset; } -static int nftnl_obj_ct_expect_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_ct_expect_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy +obj_ct_expect_attr_policy[__NFTNL_OBJ_CT_EXPECT_MAX] = { + [NFTNL_OBJ_CT_EXPECT_L3PROTO] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_CT_EXPECT_L4PROTO] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_CT_EXPECT_DPORT] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_CT_EXPECT_TIMEOUT] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_CT_EXPECT_SIZE] = { .maxlen = sizeof(uint8_t) }, +}; struct obj_ops obj_ops_ct_expect = { .name = "ct_expect", .type = NFT_OBJECT_CT_EXPECT, .alloc_len = sizeof(struct nftnl_obj_ct_expect), - .max_attr = NFTA_CT_EXPECT_MAX, + .nftnl_max_attr = __NFTNL_OBJ_CT_EXPECT_MAX - 1, + .attr_policy = obj_ct_expect_attr_policy, .set = nftnl_obj_ct_expect_set, .get = nftnl_obj_ct_expect_get, .parse = nftnl_obj_ct_expect_parse, .build = nftnl_obj_ct_expect_build, - .snprintf = nftnl_obj_ct_expect_snprintf, + .output = nftnl_obj_ct_expect_snprintf, }; diff --git a/src/obj/ct_helper.c b/src/obj/ct_helper.c index d91f636..1feccf2 100644 --- a/src/obj/ct_helper.c +++ b/src/obj/ct_helper.c @@ -32,13 +32,11 @@ static int nftnl_obj_ct_helper_set(struct nftnl_obj *e, uint16_t type, snprintf(helper->name, sizeof(helper->name), "%s", (const char *)data); break; case NFTNL_OBJ_CT_HELPER_L3PROTO: - memcpy(&helper->l3proto, data, sizeof(helper->l3proto)); + memcpy(&helper->l3proto, data, data_len); break; case NFTNL_OBJ_CT_HELPER_L4PROTO: - memcpy(&helper->l4proto, data, sizeof(helper->l4proto)); + memcpy(&helper->l4proto, data, data_len); break; - default: - return -1; } return 0; } @@ -131,8 +129,9 @@ nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e); @@ -140,31 +139,25 @@ static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len, helper->name, helper->l3proto, helper->l4proto); } -static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; +/* from kernel's include/net/netfilter/nf_conntrack_helper.h */ +#define NF_CT_HELPER_NAME_LEN 16 - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_ct_helper_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy +obj_ct_helper_attr_policy[__NFTNL_OBJ_CT_HELPER_MAX] = { + [NFTNL_OBJ_CT_HELPER_NAME] = { .maxlen = NF_CT_HELPER_NAME_LEN }, + [NFTNL_OBJ_CT_HELPER_L3PROTO] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_CT_HELPER_L4PROTO] = { .maxlen = sizeof(uint8_t) }, +}; struct obj_ops obj_ops_ct_helper = { .name = "ct_helper", .type = NFT_OBJECT_CT_HELPER, .alloc_len = sizeof(struct nftnl_obj_ct_helper), - .max_attr = NFTA_CT_HELPER_MAX, + .nftnl_max_attr = __NFTNL_OBJ_CT_HELPER_MAX - 1, + .attr_policy = obj_ct_helper_attr_policy, .set = nftnl_obj_ct_helper_set, .get = nftnl_obj_ct_helper_get, .parse = nftnl_obj_ct_helper_parse, .build = nftnl_obj_ct_helper_build, - .snprintf = nftnl_obj_ct_helper_snprintf, + .output = nftnl_obj_ct_helper_snprintf, }; diff --git a/src/obj/ct_timeout.c b/src/obj/ct_timeout.c index 2662cac..b9b688e 100644 --- a/src/obj/ct_timeout.c +++ b/src/obj/ct_timeout.c @@ -21,7 +21,7 @@ #include "obj.h" -static const char *const tcp_state_to_name[] = { +static const char *const tcp_state_to_name[NFTNL_CTTIMEOUT_TCP_MAX] = { [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = "SYN_SENT", [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = "SYN_RECV", [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = "ESTABLISHED", @@ -35,7 +35,7 @@ static const char *const tcp_state_to_name[] = { [NFTNL_CTTIMEOUT_TCP_UNACK] = "UNACKNOWLEDGED", }; -static uint32_t tcp_dflt_timeout[] = { +static uint32_t tcp_dflt_timeout[NFTNL_CTTIMEOUT_TCP_MAX] = { [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = 120, [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = 60, [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 432000, @@ -49,12 +49,12 @@ static uint32_t tcp_dflt_timeout[] = { [NFTNL_CTTIMEOUT_TCP_UNACK] = 300, }; -static const char *const udp_state_to_name[] = { +static const char *const udp_state_to_name[NFTNL_CTTIMEOUT_UDP_MAX] = { [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "UNREPLIED", [NFTNL_CTTIMEOUT_UDP_REPLIED] = "REPLIED", }; -static uint32_t udp_dflt_timeout[] = { +static uint32_t udp_dflt_timeout[NFTNL_CTTIMEOUT_UDP_MAX] = { [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30, [NFTNL_CTTIMEOUT_UDP_REPLIED] = 180, }; @@ -150,17 +150,18 @@ static int nftnl_obj_ct_timeout_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_CT_TIMEOUT_L3PROTO: - memcpy(&timeout->l3proto, data, sizeof(timeout->l3proto)); + memcpy(&timeout->l3proto, data, data_len); break; case NFTNL_OBJ_CT_TIMEOUT_L4PROTO: - memcpy(&timeout->l4proto, data, sizeof(timeout->l4proto)); + memcpy(&timeout->l4proto, data, data_len); break; case NFTNL_OBJ_CT_TIMEOUT_ARRAY: + if (data_len < sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX) + return -1; + memcpy(timeout->timeout, data, sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX); break; - default: - return -1; } return 0; } @@ -257,21 +258,21 @@ nftnl_obj_ct_timeout_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t remain, + uint32_t flags, + const struct nftnl_obj *e) { - int ret = 0; - int offset = 0, remain = len; + int ret = 0, offset = 0; struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) { - ret = snprintf(buf + offset, len, "family %d ", + ret = snprintf(buf + offset, remain, "family %d ", timeout->l3proto); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) { - ret = snprintf(buf + offset, len, "protocol %d ", + ret = snprintf(buf + offset, remain, "protocol %d ", timeout->l4proto); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -283,7 +284,7 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len, if (timeout_protocol[timeout->l4proto].attr_max == 0) l4num = IPPROTO_RAW; - ret = snprintf(buf + offset, len, "policy = {"); + ret = snprintf(buf + offset, remain, "policy = {"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); for (i = 0; i < timeout_protocol[l4num].attr_max; i++) { @@ -293,13 +294,13 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len, "UNKNOWN"; if (timeout->timeout[i] != timeout_protocol[l4num].dflt_timeout[i]) { - ret = snprintf(buf + offset, len, + ret = snprintf(buf + offset, remain, "%s = %u,", state_name, timeout->timeout[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } } - ret = snprintf(buf + offset, len, "}"); + ret = snprintf(buf + offset, remain, "}"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } buf[offset] = '\0'; @@ -307,31 +308,21 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len, return offset; } -static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_ct_timeout_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy +obj_ct_timeout_attr_policy[__NFTNL_OBJ_CT_TIMEOUT_MAX] = { + [NFTNL_OBJ_CT_TIMEOUT_L3PROTO] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_CT_TIMEOUT_L4PROTO] = { .maxlen = sizeof(uint8_t) }, +}; struct obj_ops obj_ops_ct_timeout = { .name = "ct_timeout", .type = NFT_OBJECT_CT_TIMEOUT, .alloc_len = sizeof(struct nftnl_obj_ct_timeout), - .max_attr = NFTA_CT_TIMEOUT_MAX, + .nftnl_max_attr = __NFTNL_OBJ_CT_TIMEOUT_MAX - 1, + .attr_policy = obj_ct_timeout_attr_policy, .set = nftnl_obj_ct_timeout_set, .get = nftnl_obj_ct_timeout_get, .parse = nftnl_obj_ct_timeout_parse, .build = nftnl_obj_ct_timeout_build, - .snprintf = nftnl_obj_ct_timeout_snprintf, + .output = nftnl_obj_ct_timeout_snprintf, }; diff --git a/src/obj/limit.c b/src/obj/limit.c index 60b0159..cbf30b4 100644 --- a/src/obj/limit.c +++ b/src/obj/limit.c @@ -28,22 +28,20 @@ static int nftnl_obj_limit_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_LIMIT_RATE: - memcpy(&limit->rate, data, sizeof(limit->rate)); + memcpy(&limit->rate, data, data_len); break; case NFTNL_OBJ_LIMIT_UNIT: - memcpy(&limit->unit, data, sizeof(limit->unit)); + memcpy(&limit->unit, data, data_len); break; case NFTNL_OBJ_LIMIT_BURST: - memcpy(&limit->burst, data, sizeof(limit->burst)); + memcpy(&limit->burst, data, data_len); break; case NFTNL_OBJ_LIMIT_TYPE: - memcpy(&limit->type, data, sizeof(limit->type)); + memcpy(&limit->type, data, data_len); break; case NFTNL_OBJ_LIMIT_FLAGS: - memcpy(&limit->flags, data, sizeof(limit->flags)); + memcpy(&limit->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -148,8 +146,9 @@ static int nftnl_obj_limit_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_limit_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_limit_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_limit *limit = nftnl_obj_data(e); @@ -158,32 +157,23 @@ static int nftnl_obj_limit_snprintf_default(char *buf, size_t len, limit->burst, limit->type, limit->flags); } -static int nftnl_obj_limit_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_limit_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_limit_attr_policy[__NFTNL_OBJ_LIMIT_MAX] = { + [NFTNL_OBJ_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_OBJ_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_OBJ_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct obj_ops obj_ops_limit = { .name = "limit", .type = NFT_OBJECT_LIMIT, .alloc_len = sizeof(struct nftnl_obj_limit), - .max_attr = NFTA_LIMIT_MAX, + .nftnl_max_attr = __NFTNL_OBJ_LIMIT_MAX - 1, + .attr_policy = obj_limit_attr_policy, .set = nftnl_obj_limit_set, .get = nftnl_obj_limit_get, .parse = nftnl_obj_limit_parse, .build = nftnl_obj_limit_build, - .snprintf = nftnl_obj_limit_snprintf, + .output = nftnl_obj_limit_snprintf, }; diff --git a/src/obj/quota.c b/src/obj/quota.c index 1914037..526db8e 100644 --- a/src/obj/quota.c +++ b/src/obj/quota.c @@ -28,16 +28,14 @@ static int nftnl_obj_quota_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_QUOTA_BYTES: - memcpy("a->bytes, data, sizeof(quota->bytes)); + memcpy("a->bytes, data, data_len); break; case NFTNL_OBJ_QUOTA_CONSUMED: - memcpy("a->consumed, data, sizeof(quota->consumed)); + memcpy("a->consumed, data, data_len); break; case NFTNL_OBJ_QUOTA_FLAGS: - memcpy("a->flags, data, sizeof(quota->flags)); + memcpy("a->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -125,8 +123,9 @@ nftnl_obj_quota_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_quota_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_quota_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_quota *quota = nftnl_obj_data(e); @@ -134,32 +133,21 @@ static int nftnl_obj_quota_snprintf_default(char *buf, size_t len, quota->bytes, quota->flags); } -static int nftnl_obj_quota_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_quota_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_quota_attr_policy[__NFTNL_OBJ_QUOTA_MAX] = { + [NFTNL_OBJ_QUOTA_BYTES] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_OBJ_QUOTA_CONSUMED] = { .maxlen = sizeof(uint64_t) }, + [NFTNL_OBJ_QUOTA_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct obj_ops obj_ops_quota = { .name = "quota", .type = NFT_OBJECT_QUOTA, .alloc_len = sizeof(struct nftnl_obj_quota), - .max_attr = NFTA_QUOTA_MAX, + .nftnl_max_attr = __NFTNL_OBJ_QUOTA_MAX - 1, + .attr_policy = obj_quota_attr_policy, .set = nftnl_obj_quota_set, .get = nftnl_obj_quota_get, .parse = nftnl_obj_quota_parse, .build = nftnl_obj_quota_build, - .snprintf = nftnl_obj_quota_snprintf, + .output = nftnl_obj_quota_snprintf, }; diff --git a/src/obj/secmark.c b/src/obj/secmark.c index e27b5fa..eea9664 100644 --- a/src/obj/secmark.c +++ b/src/obj/secmark.c @@ -30,8 +30,6 @@ static int nftnl_obj_secmark_set(struct nftnl_obj *e, uint16_t type, case NFTNL_OBJ_SECMARK_CTX: snprintf(secmark->ctx, sizeof(secmark->ctx), "%s", (const char *)data); break; - default: - return -1; } return 0; } @@ -98,40 +96,28 @@ nftnl_obj_secmark_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_secmark_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_secmark_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_secmark *secmark = nftnl_obj_data(e); return snprintf(buf, len, "context %s ", secmark->ctx); } -static int nftnl_obj_secmark_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_secmark_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_secmark_attr_policy[__NFTNL_OBJ_SECMARK_MAX] = { + [NFTNL_OBJ_SECMARK_CTX] = { .maxlen = NFT_SECMARK_CTX_MAXLEN }, +}; struct obj_ops obj_ops_secmark = { .name = "secmark", .type = NFT_OBJECT_SECMARK, .alloc_len = sizeof(struct nftnl_obj_secmark), - .max_attr = NFTA_SECMARK_MAX, + .nftnl_max_attr = __NFTNL_OBJ_SECMARK_MAX - 1, + .attr_policy = obj_secmark_attr_policy, .set = nftnl_obj_secmark_set, .get = nftnl_obj_secmark_get, .parse = nftnl_obj_secmark_parse, .build = nftnl_obj_secmark_build, - .snprintf = nftnl_obj_secmark_snprintf, + .output = nftnl_obj_secmark_snprintf, }; diff --git a/src/obj/synproxy.c b/src/obj/synproxy.c index 56ebc85..65fbcf7 100644 --- a/src/obj/synproxy.c +++ b/src/obj/synproxy.c @@ -19,16 +19,14 @@ static int nftnl_obj_synproxy_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_SYNPROXY_MSS: - synproxy->mss = *((uint16_t *)data); + memcpy(&synproxy->mss, data, data_len); break; case NFTNL_OBJ_SYNPROXY_WSCALE: - synproxy->wscale = *((uint8_t *)data); + memcpy(&synproxy->wscale, data, data_len); break; case NFTNL_OBJ_SYNPROXY_FLAGS: - synproxy->flags = *((uint32_t *)data); + memcpy(&synproxy->flags, data, data_len); break; - default: - return -1; } return 0; } @@ -117,11 +115,12 @@ static int nftnl_obj_synproxy_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size, - const struct nftnl_obj *e) +static int nftnl_obj_synproxy_snprintf(char *buf, size_t len, + uint32_t flags, + const struct nftnl_obj *e) { struct nftnl_obj_synproxy *synproxy = nftnl_obj_data(e); - int ret, offset = 0, len = size; + int ret, offset = 0; if (e->flags & (1 << NFTNL_OBJ_SYNPROXY_MSS) && e->flags & (1 << NFTNL_OBJ_SYNPROXY_WSCALE)) { @@ -133,29 +132,21 @@ static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size, return offset; } -static int nftnl_obj_synproxy_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, - const struct nftnl_obj *e) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_synproxy_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_synproxy_attr_policy[__NFTNL_OBJ_SYNPROXY_MAX] = { + [NFTNL_OBJ_SYNPROXY_MSS] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_SYNPROXY_WSCALE] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_SYNPROXY_FLAGS] = { .maxlen = sizeof(uint32_t) }, +}; struct obj_ops obj_ops_synproxy = { .name = "synproxy", .type = NFT_OBJECT_SYNPROXY, .alloc_len = sizeof(struct nftnl_obj_synproxy), - .max_attr = NFTA_SYNPROXY_MAX, + .nftnl_max_attr = __NFTNL_OBJ_SYNPROXY_MAX - 1, + .attr_policy = obj_synproxy_attr_policy, .set = nftnl_obj_synproxy_set, .get = nftnl_obj_synproxy_get, .parse = nftnl_obj_synproxy_parse, .build = nftnl_obj_synproxy_build, - .snprintf = nftnl_obj_synproxy_snprintf, + .output = nftnl_obj_synproxy_snprintf, }; diff --git a/src/obj/tunnel.c b/src/obj/tunnel.c index 100aa09..0309410 100644 --- a/src/obj/tunnel.c +++ b/src/obj/tunnel.c @@ -29,55 +29,53 @@ nftnl_obj_tunnel_set(struct nftnl_obj *e, uint16_t type, switch (type) { case NFTNL_OBJ_TUNNEL_ID: - memcpy(&tun->id, data, sizeof(tun->id)); + memcpy(&tun->id, data, data_len); break; case NFTNL_OBJ_TUNNEL_IPV4_SRC: - memcpy(&tun->src_v4, data, sizeof(tun->src_v4)); + memcpy(&tun->src_v4, data, data_len); break; case NFTNL_OBJ_TUNNEL_IPV4_DST: - memcpy(&tun->dst_v4, data, sizeof(tun->dst_v4)); + memcpy(&tun->dst_v4, data, data_len); break; case NFTNL_OBJ_TUNNEL_IPV6_SRC: - memcpy(&tun->src_v6, data, sizeof(struct in6_addr)); + memcpy(&tun->src_v6, data, data_len); break; case NFTNL_OBJ_TUNNEL_IPV6_DST: - memcpy(&tun->dst_v6, data, sizeof(struct in6_addr)); + memcpy(&tun->dst_v6, data, data_len); break; case NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL: - memcpy(&tun->flowlabel, data, sizeof(tun->flowlabel)); + memcpy(&tun->flowlabel, data, data_len); break; case NFTNL_OBJ_TUNNEL_SPORT: - memcpy(&tun->sport, data, sizeof(tun->sport)); + memcpy(&tun->sport, data, data_len); break; case NFTNL_OBJ_TUNNEL_DPORT: - memcpy(&tun->dport, data, sizeof(tun->dport)); + memcpy(&tun->dport, data, data_len); break; case NFTNL_OBJ_TUNNEL_FLAGS: - memcpy(&tun->tun_flags, data, sizeof(tun->tun_flags)); + memcpy(&tun->tun_flags, data, data_len); break; case NFTNL_OBJ_TUNNEL_TOS: - memcpy(&tun->tun_tos, data, sizeof(tun->tun_tos)); + memcpy(&tun->tun_tos, data, data_len); break; case NFTNL_OBJ_TUNNEL_TTL: - memcpy(&tun->tun_ttl, data, sizeof(tun->tun_ttl)); + memcpy(&tun->tun_ttl, data, data_len); break; case NFTNL_OBJ_TUNNEL_VXLAN_GBP: - memcpy(&tun->u.tun_vxlan.gbp, data, sizeof(tun->u.tun_vxlan.gbp)); + memcpy(&tun->u.tun_vxlan.gbp, data, data_len); break; case NFTNL_OBJ_TUNNEL_ERSPAN_VERSION: - memcpy(&tun->u.tun_erspan.version, data, sizeof(tun->u.tun_erspan.version)); + memcpy(&tun->u.tun_erspan.version, data, data_len); break; case NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX: - memcpy(&tun->u.tun_erspan.u.v1_index, data, sizeof(tun->u.tun_erspan.u.v1_index)); + memcpy(&tun->u.tun_erspan.u.v1_index, data, data_len); break; case NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID: - memcpy(&tun->u.tun_erspan.u.v2.hwid, data, sizeof(tun->u.tun_erspan.u.v2.hwid)); + memcpy(&tun->u.tun_erspan.u.v2.hwid, data, data_len); break; case NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR: - memcpy(&tun->u.tun_erspan.u.v2.dir, data, sizeof(tun->u.tun_erspan.u.v2.dir)); + memcpy(&tun->u.tun_erspan.u.v2.dir, data, data_len); break; - default: - return -1; } return 0; } @@ -530,39 +528,42 @@ nftnl_obj_tunnel_parse(struct nftnl_obj *e, struct nlattr *attr) return 0; } -static int nftnl_obj_tunnel_snprintf_default(char *buf, size_t len, - const struct nftnl_obj *e) +static int nftnl_obj_tunnel_snprintf(char *buf, size_t len, + uint32_t flags, const struct nftnl_obj *e) { struct nftnl_obj_tunnel *tun = nftnl_obj_data(e); return snprintf(buf, len, "id %u ", tun->id); } -static int nftnl_obj_tunnel_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, const struct nftnl_obj *e) -{ - if (len) - buf[0] = '\0'; - - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_obj_tunnel_snprintf_default(buf, len, e); - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: - break; - } - return -1; -} +static struct attr_policy obj_tunnel_attr_policy[__NFTNL_OBJ_TUNNEL_MAX] = { + [NFTNL_OBJ_TUNNEL_ID] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_IPV4_SRC] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_IPV4_DST] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_IPV6_SRC] = { .maxlen = sizeof(struct in6_addr) }, + [NFTNL_OBJ_TUNNEL_IPV6_DST] = { .maxlen = sizeof(struct in6_addr) }, + [NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_SPORT] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_TUNNEL_DPORT] = { .maxlen = sizeof(uint16_t) }, + [NFTNL_OBJ_TUNNEL_FLAGS] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_TOS] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_TUNNEL_TTL] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_TUNNEL_VXLAN_GBP] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_ERSPAN_VERSION] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX] = { .maxlen = sizeof(uint32_t) }, + [NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR] = { .maxlen = sizeof(uint8_t) }, +}; struct obj_ops obj_ops_tunnel = { .name = "tunnel", .type = NFT_OBJECT_TUNNEL, .alloc_len = sizeof(struct nftnl_obj_tunnel), - .max_attr = NFTA_TUNNEL_KEY_MAX, + .nftnl_max_attr = __NFTNL_OBJ_TUNNEL_MAX - 1, + .attr_policy = obj_tunnel_attr_policy, .set = nftnl_obj_tunnel_set, .get = nftnl_obj_tunnel_get, .parse = nftnl_obj_tunnel_parse, .build = nftnl_obj_tunnel_build, - .snprintf = nftnl_obj_tunnel_snprintf, + .output = nftnl_obj_tunnel_snprintf, }; diff --git a/src/object.c b/src/object.c index 4f58272..19cb7d0 100644 --- a/src/object.c +++ b/src/object.c @@ -57,6 +57,8 @@ void nftnl_obj_free(const struct nftnl_obj *obj) xfree(obj->table); if (obj->flags & (1 << NFTNL_OBJ_NAME)) xfree(obj->name); + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + xfree(obj->user.data); xfree(obj); } @@ -67,32 +69,60 @@ bool nftnl_obj_is_set(const struct nftnl_obj *obj, uint16_t attr) return obj->flags & (1 << attr); } +EXPORT_SYMBOL(nftnl_obj_unset); +void nftnl_obj_unset(struct nftnl_obj *obj, uint16_t attr) +{ + if (!(obj->flags & (1 << attr))) + return; + + switch (attr) { + case NFTNL_OBJ_TABLE: + xfree(obj->table); + break; + case NFTNL_OBJ_NAME: + xfree(obj->name); + break; + case NFTNL_OBJ_USERDATA: + xfree(obj->user.data); + break; + case NFTNL_OBJ_TYPE: + case NFTNL_OBJ_FAMILY: + case NFTNL_OBJ_USE: + case NFTNL_OBJ_HANDLE: + break; + default: + break; + } + + obj->flags &= ~(1 << attr); +} + static uint32_t nftnl_obj_validate[NFTNL_OBJ_MAX + 1] = { + [NFTNL_OBJ_TYPE] = sizeof(uint32_t), [NFTNL_OBJ_FAMILY] = sizeof(uint32_t), [NFTNL_OBJ_USE] = sizeof(uint32_t), [NFTNL_OBJ_HANDLE] = sizeof(uint64_t), }; EXPORT_SYMBOL(nftnl_obj_set_data); -void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, - const void *data, uint32_t data_len) +int nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, + const void *data, uint32_t data_len) { if (attr < NFTNL_OBJ_MAX) nftnl_assert_validate(data, nftnl_obj_validate, attr, data_len); switch (attr) { case NFTNL_OBJ_TABLE: - xfree(obj->table); - obj->table = strdup(data); + return nftnl_set_str_attr(&obj->table, &obj->flags, + attr, data, data_len); break; case NFTNL_OBJ_NAME: - xfree(obj->name); - obj->name = strdup(data); - break; + return nftnl_set_str_attr(&obj->name, &obj->flags, + attr, data, data_len); case NFTNL_OBJ_TYPE: obj->ops = nftnl_obj_ops_lookup(*((uint32_t *)data)); if (!obj->ops) - return; + return -1; break; case NFTNL_OBJ_FAMILY: memcpy(&obj->family, data, sizeof(obj->family)); @@ -103,12 +133,32 @@ void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr, case NFTNL_OBJ_HANDLE: memcpy(&obj->handle, data, sizeof(obj->handle)); break; - default: - if (obj->ops) - obj->ops->set(obj, attr, data, data_len); + case NFTNL_OBJ_USERDATA: + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + xfree(obj->user.data); + + obj->user.data = malloc(data_len); + if (!obj->user.data) + return -1; + memcpy(obj->user.data, data, data_len); + obj->user.len = data_len; break; + default: + if (!obj->ops || + attr < NFTNL_OBJ_BASE || + attr > obj->ops->nftnl_max_attr || + !obj->ops->attr_policy) + return -1; + + if (obj->ops->attr_policy[attr].maxlen && + obj->ops->attr_policy[attr].maxlen < data_len) + return -1; + + if (obj->ops->set(obj, attr, data, data_len) < 0) + return -1; } obj->flags |= (1 << attr); + return 0; } void nftnl_obj_set(struct nftnl_obj *obj, uint16_t attr, const void *data) __visible; @@ -118,37 +168,37 @@ void nftnl_obj_set(struct nftnl_obj *obj, uint16_t attr, const void *data) } EXPORT_SYMBOL(nftnl_obj_set_u8); -void nftnl_obj_set_u8(struct nftnl_obj *obj, uint16_t attr, uint8_t val) +int nftnl_obj_set_u8(struct nftnl_obj *obj, uint16_t attr, uint8_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint8_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint8_t)); } EXPORT_SYMBOL(nftnl_obj_set_u16); -void nftnl_obj_set_u16(struct nftnl_obj *obj, uint16_t attr, uint16_t val) +int nftnl_obj_set_u16(struct nftnl_obj *obj, uint16_t attr, uint16_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint16_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint16_t)); } EXPORT_SYMBOL(nftnl_obj_set_u32); -void nftnl_obj_set_u32(struct nftnl_obj *obj, uint16_t attr, uint32_t val) +int nftnl_obj_set_u32(struct nftnl_obj *obj, uint16_t attr, uint32_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint32_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint32_t)); } EXPORT_SYMBOL(nftnl_obj_set_u64); -void nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val) +int nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val) { - nftnl_obj_set_data(obj, attr, &val, sizeof(uint64_t)); + return nftnl_obj_set_data(obj, attr, &val, sizeof(uint64_t)); } EXPORT_SYMBOL(nftnl_obj_set_str); -void nftnl_obj_set_str(struct nftnl_obj *obj, uint16_t attr, const char *str) +int nftnl_obj_set_str(struct nftnl_obj *obj, uint16_t attr, const char *str) { - nftnl_obj_set_data(obj, attr, str, 0); + return nftnl_obj_set_data(obj, attr, str, strlen(str) + 1); } EXPORT_SYMBOL(nftnl_obj_get_data); -const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, +const void *nftnl_obj_get_data(const struct nftnl_obj *obj, uint16_t attr, uint32_t *data_len) { if (!(obj->flags & (1 << attr))) @@ -174,6 +224,9 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, case NFTNL_OBJ_HANDLE: *data_len = sizeof(uint64_t); return &obj->handle; + case NFTNL_OBJ_USERDATA: + *data_len = obj->user.len; + return obj->user.data; default: if (obj->ops) return obj->ops->get(obj, attr, data_len); @@ -183,42 +236,42 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr, } EXPORT_SYMBOL(nftnl_obj_get); -const void *nftnl_obj_get(struct nftnl_obj *obj, uint16_t attr) +const void *nftnl_obj_get(const struct nftnl_obj *obj, uint16_t attr) { uint32_t data_len; return nftnl_obj_get_data(obj, attr, &data_len); } EXPORT_SYMBOL(nftnl_obj_get_u8); -uint8_t nftnl_obj_get_u8(struct nftnl_obj *obj, uint16_t attr) +uint8_t nftnl_obj_get_u8(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint8_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u16); -uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr) +uint16_t nftnl_obj_get_u16(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint16_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u32); -uint32_t nftnl_obj_get_u32(struct nftnl_obj *obj, uint16_t attr) +uint32_t nftnl_obj_get_u32(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint32_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_u64); -uint64_t nftnl_obj_get_u64(struct nftnl_obj *obj, uint16_t attr) +uint64_t nftnl_obj_get_u64(const struct nftnl_obj *obj, uint16_t attr) { const void *ret = nftnl_obj_get(obj, attr); return ret == NULL ? 0 : *((uint64_t *)ret); } EXPORT_SYMBOL(nftnl_obj_get_str); -const char *nftnl_obj_get_str(struct nftnl_obj *obj, uint16_t attr) +const char *nftnl_obj_get_str(const struct nftnl_obj *obj, uint16_t attr) { return nftnl_obj_get(obj, attr); } @@ -235,6 +288,8 @@ void nftnl_obj_nlmsg_build_payload(struct nlmsghdr *nlh, mnl_attr_put_u32(nlh, NFTA_OBJ_TYPE, htonl(obj->ops->type)); if (obj->flags & (1 << NFTNL_OBJ_HANDLE)) mnl_attr_put_u64(nlh, NFTA_OBJ_HANDLE, htobe64(obj->handle)); + if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) + mnl_attr_put(nlh, NFTA_OBJ_USERDATA, obj->user.len, obj->user.data); if (obj->ops) { struct nlattr *nest = mnl_attr_nest_start(nlh, NFTA_OBJ_DATA); @@ -269,6 +324,10 @@ static int nftnl_obj_parse_attr_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) abi_breakage(); break; + case NFTA_OBJ_USERDATA: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -315,6 +374,11 @@ int nftnl_obj_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_obj *obj) obj->handle = be64toh(mnl_attr_get_u64(tb[NFTA_OBJ_HANDLE])); obj->flags |= (1 << NFTNL_OBJ_HANDLE); } + if (tb[NFTA_OBJ_USERDATA]) { + nftnl_obj_set_data(obj, NFTNL_OBJ_USERDATA, + mnl_attr_get_payload(tb[NFTA_OBJ_USERDATA]), + mnl_attr_get_payload_len(tb[NFTA_OBJ_USERDATA])); + } obj->family = nfg->nfgen_family; obj->flags |= (1 << NFTNL_OBJ_FAMILY); @@ -358,46 +422,38 @@ int nftnl_obj_parse_file(struct nftnl_obj *obj, enum nftnl_parse_type type, return nftnl_obj_do_parse(obj, type, fp, err, NFTNL_PARSE_FILE); } -static int nftnl_obj_snprintf_dflt(char *buf, size_t size, +static int nftnl_obj_snprintf_dflt(char *buf, size_t remain, const struct nftnl_obj *obj, uint32_t type, uint32_t flags) { const char *name = obj->ops ? obj->ops->name : "(unknown)"; - int ret, remain = size, offset = 0; + int ret, offset = 0; - ret = snprintf(buf, size, "table %s name %s use %u [ %s ", + ret = snprintf(buf, remain, "table %s name %s use %u [ %s ", obj->table, obj->name, obj->use, name); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (obj->ops) { - ret = obj->ops->snprintf(buf + offset, offset, type, flags, - obj); + ret = obj->ops->output(buf + offset, remain, flags, obj); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, offset, "]"); + ret = snprintf(buf + offset, remain, "]"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } -static int nftnl_obj_cmd_snprintf(char *buf, size_t size, +static int nftnl_obj_cmd_snprintf(char *buf, size_t remain, const struct nftnl_obj *obj, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_obj_snprintf_dflt(buf + offset, remain, obj, type, - flags); - break; - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_obj_snprintf_dflt(buf + offset, remain, obj, type, flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } @@ -115,21 +115,11 @@ int nftnl_rule_set_data(struct nftnl_rule *r, uint16_t attr, switch(attr) { case NFTNL_RULE_TABLE: - if (r->flags & (1 << NFTNL_RULE_TABLE)) - xfree(r->table); - - r->table = strdup(data); - if (!r->table) - return -1; - break; + return nftnl_set_str_attr(&r->table, &r->flags, + attr, data, data_len); case NFTNL_RULE_CHAIN: - if (r->flags & (1 << NFTNL_RULE_CHAIN)) - xfree(r->chain); - - r->chain = strdup(data); - if (!r->chain) - return -1; - break; + return nftnl_set_str_attr(&r->chain, &r->flags, + attr, data, data_len); case NFTNL_RULE_HANDLE: memcpy(&r->handle, data, sizeof(r->handle)); break; @@ -330,6 +320,12 @@ void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr) list_add_tail(&expr->head, &r->expr_list); } +EXPORT_SYMBOL(nftnl_rule_del_expr); +void nftnl_rule_del_expr(struct nftnl_expr *expr) +{ + list_del(&expr->head); +} + static int nftnl_rule_parse_attr_cb(const struct nlattr *attr, void *data) { const struct nlattr **tb = data; @@ -539,50 +535,59 @@ int nftnl_rule_parse_file(struct nftnl_rule *r, enum nftnl_parse_type type, return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE); } -static int nftnl_rule_snprintf_default(char *buf, size_t size, +static int nftnl_rule_snprintf_default(char *buf, size_t remain, const struct nftnl_rule *r, uint32_t type, uint32_t flags) { struct nftnl_expr *expr; - int ret, remain = size, offset = 0, i; + int ret, offset = 0, i; + const char *sep = ""; if (r->flags & (1 << NFTNL_RULE_FAMILY)) { - ret = snprintf(buf + offset, remain, "%s ", + ret = snprintf(buf + offset, remain, "%s%s", sep, nftnl_family2str(r->family)); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_TABLE)) { - ret = snprintf(buf + offset, remain, "%s ", + ret = snprintf(buf + offset, remain, "%s%s", sep, r->table); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_CHAIN)) { - ret = snprintf(buf + offset, remain, "%s ", + ret = snprintf(buf + offset, remain, "%s%s", sep, r->chain); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_HANDLE)) { - ret = snprintf(buf + offset, remain, "%llu ", - (unsigned long long)r->handle); + ret = snprintf(buf + offset, remain, "%s%" PRIu64, sep, + r->handle); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_POSITION)) { - ret = snprintf(buf + offset, remain, "%llu ", - (unsigned long long)r->position); + ret = snprintf(buf + offset, remain, "%s%" PRIu64, sep, + r->position); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_ID)) { - ret = snprintf(buf + offset, remain, "%u ", r->id); + ret = snprintf(buf + offset, remain, "%s%u", sep, r->id); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } if (r->flags & (1 << NFTNL_RULE_POSITION_ID)) { - ret = snprintf(buf + offset, remain, "%u ", r->position_id); + ret = snprintf(buf + offset, remain, "%s%u", sep, + r->position_id); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; } ret = snprintf(buf + offset, remain, "\n"); @@ -607,12 +612,13 @@ static int nftnl_rule_snprintf_default(char *buf, size_t size, for (i = 0; i < r->user.len; i++) { char *c = r->user.data; - ret = snprintf(buf + offset, remain, "%c", - isalnum(c[i]) ? c[i] : 0); + ret = snprintf(buf + offset, remain, + isprint(c[i]) ? "%c" : "\\x%02hhx", + c[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, remain, " }\n"); + ret = snprintf(buf + offset, remain, " }"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -620,27 +626,21 @@ static int nftnl_rule_snprintf_default(char *buf, size_t size, return offset; } -static int nftnl_rule_cmd_snprintf(char *buf, size_t size, +static int nftnl_rule_cmd_snprintf(char *buf, size_t remain, const struct nftnl_rule *r, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; uint32_t inner_flags = flags; + int ret, offset = 0; inner_flags &= ~NFTNL_OF_EVENT_ANY; - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type, - inner_flags); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type, + inner_flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } diff --git a/src/ruleset.c b/src/ruleset.c index 2468bd4..185aa48 100644 --- a/src/ruleset.c +++ b/src/ruleset.c @@ -305,51 +305,15 @@ int nftnl_ruleset_parse_file(struct nftnl_ruleset *rs, enum nftnl_parse_type typ return nftnl_ruleset_parse_file_cb(type, fp, err, rs, nftnl_ruleset_cb); } -static const char *nftnl_ruleset_o_opentag(uint32_t type) -{ - switch (type) { - case NFTNL_OUTPUT_JSON: - return "{\"nftables\":["; - case NFTNL_OUTPUT_XML: - default: - return ""; - } -} - -static const char *nftnl_ruleset_o_separator(void *obj, uint32_t type) -{ - if (obj == NULL) - return ""; - - switch (type) { - case NFTNL_OUTPUT_JSON: - return ","; - case NFTNL_OUTPUT_DEFAULT: - return "\n"; - default: - return ""; - } -} - -static const char *nftnl_ruleset_o_closetag(uint32_t type) -{ - switch (type) { - case NFTNL_OUTPUT_JSON: - return "]}"; - case NFTNL_OUTPUT_XML: - default: - return ""; - } -} - static int -nftnl_ruleset_snprintf_table(char *buf, size_t size, +nftnl_ruleset_snprintf_table(char *buf, size_t remain, const struct nftnl_ruleset *rs, uint32_t type, uint32_t flags) { struct nftnl_table *t; struct nftnl_table_list_iter *ti; - int ret, remain = size, offset = 0; + const char *sep = ""; + int ret, offset = 0; ti = nftnl_table_list_iter_create(rs->table_list); if (ti == NULL) @@ -357,14 +321,14 @@ nftnl_ruleset_snprintf_table(char *buf, size_t size, t = nftnl_table_list_iter_next(ti); while (t != NULL) { + ret = snprintf(buf + offset, remain, "%s", sep); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_table_snprintf(buf + offset, remain, t, type, flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); t = nftnl_table_list_iter_next(ti); - - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(t, type)); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = "\n"; } nftnl_table_list_iter_destroy(ti); @@ -372,13 +336,14 @@ nftnl_ruleset_snprintf_table(char *buf, size_t size, } static int -nftnl_ruleset_snprintf_chain(char *buf, size_t size, +nftnl_ruleset_snprintf_chain(char *buf, size_t remain, const struct nftnl_ruleset *rs, uint32_t type, uint32_t flags) { struct nftnl_chain *c; struct nftnl_chain_list_iter *ci; - int ret, remain = size, offset = 0; + const char *sep = ""; + int ret, offset = 0; ci = nftnl_chain_list_iter_create(rs->chain_list); if (ci == NULL) @@ -386,14 +351,14 @@ nftnl_ruleset_snprintf_chain(char *buf, size_t size, c = nftnl_chain_list_iter_next(ci); while (c != NULL) { + ret = snprintf(buf + offset, remain, "%s", sep); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_chain_snprintf(buf + offset, remain, c, type, flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); c = nftnl_chain_list_iter_next(ci); - - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(c, type)); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = "\n"; } nftnl_chain_list_iter_destroy(ci); @@ -401,13 +366,14 @@ nftnl_ruleset_snprintf_chain(char *buf, size_t size, } static int -nftnl_ruleset_snprintf_set(char *buf, size_t size, +nftnl_ruleset_snprintf_set(char *buf, size_t remain, const struct nftnl_ruleset *rs, uint32_t type, uint32_t flags) { struct nftnl_set *s; struct nftnl_set_list_iter *si; - int ret, remain = size, offset = 0; + const char *sep = ""; + int ret, offset = 0; si = nftnl_set_list_iter_create(rs->set_list); if (si == NULL) @@ -415,14 +381,14 @@ nftnl_ruleset_snprintf_set(char *buf, size_t size, s = nftnl_set_list_iter_next(si); while (s != NULL) { + ret = snprintf(buf + offset, remain, "%s", sep); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_set_snprintf(buf + offset, remain, s, type, flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); s = nftnl_set_list_iter_next(si); - - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(s, type)); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = "\n"; } nftnl_set_list_iter_destroy(si); @@ -430,13 +396,14 @@ nftnl_ruleset_snprintf_set(char *buf, size_t size, } static int -nftnl_ruleset_snprintf_rule(char *buf, size_t size, +nftnl_ruleset_snprintf_rule(char *buf, size_t remain, const struct nftnl_ruleset *rs, uint32_t type, uint32_t flags) { struct nftnl_rule *r; struct nftnl_rule_list_iter *ri; - int ret, remain = size, offset = 0; + const char *sep = ""; + int ret, offset = 0; ri = nftnl_rule_list_iter_create(rs->rule_list); if (ri == NULL) @@ -444,14 +411,14 @@ nftnl_ruleset_snprintf_rule(char *buf, size_t size, r = nftnl_rule_list_iter_next(ri); while (r != NULL) { + ret = snprintf(buf + offset, remain, "%s", sep); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + ret = nftnl_rule_snprintf(buf + offset, remain, r, type, flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); r = nftnl_rule_list_iter_next(ri); - - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(r, type)); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = "\n"; } nftnl_rule_list_iter_destroy(ri); @@ -459,12 +426,13 @@ nftnl_ruleset_snprintf_rule(char *buf, size_t size, } static int -nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs, - uint32_t cmd, uint32_t type, uint32_t flags) +nftnl_ruleset_do_snprintf(char *buf, size_t remain, + const struct nftnl_ruleset *rs, + uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; - void *prev = NULL; uint32_t inner_flags = flags; + const char *sep = ""; + int ret, offset = 0; /* dont pass events flags to child calls of _snprintf() */ inner_flags &= ~NFTNL_OF_EVENT_ANY; @@ -476,13 +444,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (ret > 0) - prev = rs->table_list; + sep = "\n"; } if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST) && (!nftnl_chain_list_is_empty(rs->chain_list))) { - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(prev, type)); + ret = snprintf(buf + offset, remain, "%s", sep); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_ruleset_snprintf_chain(buf + offset, remain, rs, @@ -490,13 +457,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (ret > 0) - prev = rs->chain_list; + sep = "\n"; } if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST) && (!nftnl_set_list_is_empty(rs->set_list))) { - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(prev, type)); + ret = snprintf(buf + offset, remain, "%s", sep); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_ruleset_snprintf_set(buf + offset, remain, rs, @@ -504,13 +470,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (ret > 0) - prev = rs->set_list; + sep = "\n"; } if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST) && (!nftnl_rule_list_is_empty(rs->rule_list))) { - ret = snprintf(buf + offset, remain, "%s", - nftnl_ruleset_o_separator(prev, type)); + ret = snprintf(buf + offset, remain, "%s", sep); SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_ruleset_snprintf_rule(buf + offset, remain, rs, @@ -521,21 +486,6 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs return offset; } -static int nftnl_ruleset_cmd_snprintf(char *buf, size_t size, - const struct nftnl_ruleset *r, uint32_t cmd, - uint32_t type, uint32_t flags) -{ - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - case NFTNL_OUTPUT_JSON: - return nftnl_ruleset_do_snprintf(buf, size, r, cmd, type, flags); - case NFTNL_OUTPUT_XML: - default: - errno = EOPNOTSUPP; - return -1; - } -} - EXPORT_SYMBOL(nftnl_ruleset_snprintf); int nftnl_ruleset_snprintf(char *buf, size_t size, const struct nftnl_ruleset *r, uint32_t type, uint32_t flags) @@ -543,17 +493,12 @@ int nftnl_ruleset_snprintf(char *buf, size_t size, const struct nftnl_ruleset *r if (size) buf[0] = '\0'; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - case NFTNL_OUTPUT_JSON: - return nftnl_ruleset_cmd_snprintf(buf, size, r, - nftnl_flag2cmd(flags), type, - flags); - case NFTNL_OUTPUT_XML: - default: + if (type != NFTNL_OUTPUT_DEFAULT) { errno = EOPNOTSUPP; return -1; } + return nftnl_ruleset_do_snprintf(buf, size, r, nftnl_flag2cmd(flags), + type, flags); } static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs, @@ -562,6 +507,7 @@ static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs int len = 0, ret = 0; struct nftnl_table *t; struct nftnl_table_list_iter *ti; + const char *sep = ""; ti = nftnl_table_list_iter_create(rs->table_list); if (ti == NULL) @@ -569,19 +515,21 @@ static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs t = nftnl_table_list_iter_next(ti); while (t != NULL) { - ret = nftnl_table_fprintf(fp, t, type, flags); + ret = fprintf(fp, "%s", sep); if (ret < 0) goto err; len += ret; - t = nftnl_table_list_iter_next(ti); - - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(t, type)); + ret = nftnl_table_fprintf(fp, t, type, flags); if (ret < 0) goto err; len += ret; + + t = nftnl_table_list_iter_next(ti); + sep = "\n"; + } nftnl_table_list_iter_destroy(ti); @@ -597,6 +545,7 @@ static int nftnl_ruleset_fprintf_chains(FILE *fp, const struct nftnl_ruleset *rs int len = 0, ret = 0; struct nftnl_chain *o; struct nftnl_chain_list_iter *i; + const char *sep = ""; i = nftnl_chain_list_iter_create(rs->chain_list); if (i == NULL) @@ -604,19 +553,20 @@ static int nftnl_ruleset_fprintf_chains(FILE *fp, const struct nftnl_ruleset *rs o = nftnl_chain_list_iter_next(i); while (o != NULL) { - ret = nftnl_chain_fprintf(fp, o, type, flags); + ret = fprintf(fp, "%s", sep); if (ret < 0) goto err; len += ret; - o = nftnl_chain_list_iter_next(i); - - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type)); + ret = nftnl_chain_fprintf(fp, o, type, flags); if (ret < 0) goto err; len += ret; + + o = nftnl_chain_list_iter_next(i); + sep = "\n"; } nftnl_chain_list_iter_destroy(i); @@ -632,6 +582,7 @@ static int nftnl_ruleset_fprintf_sets(FILE *fp, const struct nftnl_ruleset *rs, int len = 0, ret = 0; struct nftnl_set *o; struct nftnl_set_list_iter *i; + const char *sep = ""; i = nftnl_set_list_iter_create(rs->set_list); if (i == NULL) @@ -639,19 +590,20 @@ static int nftnl_ruleset_fprintf_sets(FILE *fp, const struct nftnl_ruleset *rs, o = nftnl_set_list_iter_next(i); while (o != NULL) { - ret = nftnl_set_fprintf(fp, o, type, flags); + ret = fprintf(fp, "%s", sep); if (ret < 0) goto err; len += ret; - o = nftnl_set_list_iter_next(i); - - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type)); + ret = nftnl_set_fprintf(fp, o, type, flags); if (ret < 0) goto err; len += ret; + + o = nftnl_set_list_iter_next(i); + sep = "\n"; } nftnl_set_list_iter_destroy(i); @@ -667,6 +619,7 @@ static int nftnl_ruleset_fprintf_rules(FILE *fp, const struct nftnl_ruleset *rs, int len = 0, ret = 0; struct nftnl_rule *o; struct nftnl_rule_list_iter *i; + const char *sep = ""; i = nftnl_rule_list_iter_create(rs->rule_list); if (i == NULL) @@ -674,19 +627,20 @@ static int nftnl_ruleset_fprintf_rules(FILE *fp, const struct nftnl_ruleset *rs, o = nftnl_rule_list_iter_next(i); while (o != NULL) { - ret = nftnl_rule_fprintf(fp, o, type, flags); + ret = fprintf(fp, "%s", sep); if (ret < 0) goto err; len += ret; - o = nftnl_rule_list_iter_next(i); - - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type)); + ret = nftnl_rule_fprintf(fp, o, type, flags); if (ret < 0) goto err; len += ret; + + o = nftnl_rule_list_iter_next(i); + sep = "\n"; } nftnl_rule_list_iter_destroy(i); @@ -705,60 +659,54 @@ static int nftnl_ruleset_cmd_fprintf(FILE *fp, const struct nftnl_ruleset *rs, uint32_t cmd, uint32_t type, uint32_t flags) { int len = 0, ret = 0; - void *prev = NULL; uint32_t inner_flags = flags; + const char *sep = ""; /* dont pass events flags to child calls of _snprintf() */ inner_flags &= ~NFTNL_OF_EVENT_ANY; - ret = fprintf(fp, "%s", nftnl_ruleset_o_opentag(type)); - NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); - if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_TABLELIST)) && (!nftnl_table_list_is_empty(rs->table_list))) { ret = nftnl_ruleset_fprintf_tables(fp, rs, type, inner_flags); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) - prev = rs->table_list; + sep = "\n"; } if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST)) && (!nftnl_chain_list_is_empty(rs->chain_list))) { - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type)); + ret = fprintf(fp, "%s", sep); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); ret = nftnl_ruleset_fprintf_chains(fp, rs, type, inner_flags); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) - prev = rs->chain_list; + sep = "\n"; } if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST)) && (!nftnl_set_list_is_empty(rs->set_list))) { - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type)); + ret = fprintf(fp, "%s", sep); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); ret = nftnl_ruleset_fprintf_sets(fp, rs, type, inner_flags); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) - prev = rs->set_list; + sep = "\n"; } if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST)) && (!nftnl_rule_list_is_empty(rs->rule_list))) { - ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type)); + ret = fprintf(fp, "%s", sep); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); ret = nftnl_ruleset_fprintf_rules(fp, rs, type, inner_flags); NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); } - ret = fprintf(fp, "%s", nftnl_ruleset_o_closetag(type)); - NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len); - return len; } @@ -37,6 +37,7 @@ struct nftnl_set *nftnl_set_alloc(void) return NULL; INIT_LIST_HEAD(&s->element_list); + INIT_LIST_HEAD(&s->expr_list); return s; } @@ -44,6 +45,7 @@ EXPORT_SYMBOL(nftnl_set_free); void nftnl_set_free(const struct nftnl_set *s) { struct nftnl_set_elem *elem, *tmp; + struct nftnl_expr *expr, *next; if (s->flags & (1 << NFTNL_SET_TABLE)) xfree(s->table); @@ -51,8 +53,11 @@ void nftnl_set_free(const struct nftnl_set *s) xfree(s->name); if (s->flags & (1 << NFTNL_SET_USERDATA)) xfree(s->user.data); - if (s->flags & (1 << NFTNL_SET_EXPR)) - nftnl_expr_free(s->expr); + + list_for_each_entry_safe(expr, next, &s->expr_list, head) { + list_del(&expr->head); + nftnl_expr_free(expr); + } list_for_each_entry_safe(elem, tmp, &s->element_list, head) { list_del(&elem->head); @@ -70,6 +75,8 @@ bool nftnl_set_is_set(const struct nftnl_set *s, uint16_t attr) EXPORT_SYMBOL(nftnl_set_unset); void nftnl_set_unset(struct nftnl_set *s, uint16_t attr) { + struct nftnl_expr *expr, *tmp; + if (!(s->flags & (1 << attr))) return; @@ -99,7 +106,11 @@ void nftnl_set_unset(struct nftnl_set *s, uint16_t attr) xfree(s->user.data); break; case NFTNL_SET_EXPR: - nftnl_expr_free(s->expr); + case NFTNL_SET_EXPRESSIONS: + list_for_each_entry_safe(expr, tmp, &s->expr_list, head) { + list_del(&expr->head); + nftnl_expr_free(expr); + } break; default: return; @@ -117,6 +128,7 @@ static uint32_t nftnl_set_validate[NFTNL_SET_MAX + 1] = { [NFTNL_SET_DATA_LEN] = sizeof(uint32_t), [NFTNL_SET_OBJ_TYPE] = sizeof(uint32_t), [NFTNL_SET_FAMILY] = sizeof(uint32_t), + [NFTNL_SET_ID] = sizeof(uint32_t), [NFTNL_SET_POLICY] = sizeof(uint32_t), [NFTNL_SET_DESC_SIZE] = sizeof(uint32_t), [NFTNL_SET_TIMEOUT] = sizeof(uint64_t), @@ -127,26 +139,18 @@ EXPORT_SYMBOL(nftnl_set_set_data); int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data, uint32_t data_len) { + struct nftnl_expr *expr, *tmp; + nftnl_assert_attr_exists(attr, NFTNL_SET_MAX); nftnl_assert_validate(data, nftnl_set_validate, attr, data_len); switch(attr) { case NFTNL_SET_TABLE: - if (s->flags & (1 << NFTNL_SET_TABLE)) - xfree(s->table); - - s->table = strdup(data); - if (!s->table) - return -1; - break; + return nftnl_set_str_attr(&s->table, &s->flags, + attr, data, data_len); case NFTNL_SET_NAME: - if (s->flags & (1 << NFTNL_SET_NAME)) - xfree(s->name); - - s->name = strdup(data); - if (!s->name) - return -1; - break; + return nftnl_set_str_attr(&s->name, &s->flags, + attr, data, data_len); case NFTNL_SET_HANDLE: memcpy(&s->handle, data, sizeof(s->handle)); break; @@ -181,8 +185,14 @@ int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data, memcpy(&s->desc.size, data, sizeof(s->desc.size)); break; case NFTNL_SET_DESC_CONCAT: + if (data_len > sizeof(s->desc.field_len)) + return -1; + memcpy(&s->desc.field_len, data, data_len); - while (s->desc.field_len[++s->desc.field_count]); + while (s->desc.field_len[++s->desc.field_count]) { + if (s->desc.field_count >= NFT_REG32_COUNT) + break; + } break; case NFTNL_SET_TIMEOUT: memcpy(&s->timeout, data, sizeof(s->timeout)); @@ -201,10 +211,13 @@ int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data, s->user.len = data_len; break; case NFTNL_SET_EXPR: - if (s->flags & (1 << NFTNL_SET_EXPR)) - nftnl_expr_free(s->expr); + list_for_each_entry_safe(expr, tmp, &s->expr_list, head) { + list_del(&expr->head); + nftnl_expr_free(expr); + } - s->expr = (void *)data; + expr = (void *)data; + list_add(&expr->head, &s->expr_list); break; } s->flags |= (1 << attr); @@ -239,6 +252,8 @@ EXPORT_SYMBOL(nftnl_set_get_data); const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr, uint32_t *data_len) { + struct nftnl_expr *expr; + if (!(s->flags & (1 << attr))) return NULL; @@ -295,7 +310,9 @@ const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr, *data_len = s->user.len; return s->user.data; case NFTNL_SET_EXPR: - return s->expr; + list_for_each_entry(expr, &s->expr_list, head) + break; + return expr; } return NULL; } @@ -414,6 +431,8 @@ nftnl_set_nlmsg_build_desc_payload(struct nlmsghdr *nlh, struct nftnl_set *s) EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload); void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s) { + int num_exprs = 0; + if (s->flags & (1 << NFTNL_SET_TABLE)) mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table); if (s->flags & (1 << NFTNL_SET_NAME)) @@ -445,15 +464,55 @@ void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s) mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval)); if (s->flags & (1 << NFTNL_SET_USERDATA)) mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data); - if (s->flags & (1 << NFTNL_SET_EXPR)) { - struct nlattr *nest1; - - nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR); - nftnl_expr_build_payload(nlh, s->expr); - mnl_attr_nest_end(nlh, nest1); + if (!list_empty(&s->expr_list)) { + struct nftnl_expr *expr; + + list_for_each_entry(expr, &s->expr_list, head) + num_exprs++; + + if (num_exprs == 1) { + struct nlattr *nest1; + + nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR); + list_for_each_entry(expr, &s->expr_list, head) + nftnl_expr_build_payload(nlh, expr); + + mnl_attr_nest_end(nlh, nest1); + } else if (num_exprs > 1) { + struct nlattr *nest1, *nest2; + + nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS); + list_for_each_entry(expr, &s->expr_list, head) { + nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM); + nftnl_expr_build_payload(nlh, expr); + mnl_attr_nest_end(nlh, nest2); + } + mnl_attr_nest_end(nlh, nest1); + } } } +EXPORT_SYMBOL(nftnl_set_add_expr); +void nftnl_set_add_expr(struct nftnl_set *s, struct nftnl_expr *expr) +{ + list_add_tail(&expr->head, &s->expr_list); +} + +EXPORT_SYMBOL(nftnl_set_expr_foreach); +int nftnl_set_expr_foreach(const struct nftnl_set *s, + int (*cb)(struct nftnl_expr *e, void *data), + void *data) +{ + struct nftnl_expr *cur, *tmp; + int ret; + + list_for_each_entry_safe(cur, tmp, &s->expr_list, head) { + ret = cb(cur, data); + if (ret < 0) + return ret; + } + return 0; +} static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data) { @@ -493,6 +552,8 @@ static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data) abi_breakage(); break; case NFTA_SET_DESC: + case NFTA_SET_EXPR: + case NFTA_SET_EXPRESSIONS: if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) abi_breakage(); break; @@ -578,6 +639,7 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s) { struct nlattr *tb[NFTA_SET_MAX+1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); + struct nftnl_expr *expr, *next; int ret; if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0) @@ -656,17 +718,39 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s) return ret; } if (tb[NFTA_SET_EXPR]) { - s->expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]); - if (!s->expr) - return -1; + expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]); + if (!expr) + goto out_set_expr; + list_add(&expr->head, &s->expr_list); s->flags |= (1 << NFTNL_SET_EXPR); + } else if (tb[NFTA_SET_EXPRESSIONS]) { + struct nlattr *attr; + + mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) { + if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) + goto out_set_expr; + + expr = nftnl_expr_parse(attr); + if (expr == NULL) + goto out_set_expr; + + list_add_tail(&expr->head, &s->expr_list); + } + s->flags |= (1 << NFTNL_SET_EXPRESSIONS); } s->family = nfg->nfgen_family; s->flags |= (1 << NFTNL_SET_FAMILY); return 0; +out_set_expr: + list_for_each_entry_safe(expr, next, &s->expr_list, head) { + list_del(&expr->head); + nftnl_expr_free(expr); + } + + return -1; } static int nftnl_set_do_parse(struct nftnl_set *s, enum nftnl_parse_type type, @@ -705,13 +789,12 @@ int nftnl_set_parse_file(struct nftnl_set *s, enum nftnl_parse_type type, return nftnl_set_do_parse(s, type, fp, err, NFTNL_PARSE_FILE); } -static int nftnl_set_snprintf_default(char *buf, size_t size, +static int nftnl_set_snprintf_default(char *buf, size_t remain, const struct nftnl_set *s, uint32_t type, uint32_t flags) { - int ret; - int remain = size, offset = 0; struct nftnl_set_elem *elem; + int ret, offset = 0; ret = snprintf(buf, remain, "%s %s %x", s->name, s->table, s->set_flags); @@ -750,37 +833,30 @@ static int nftnl_set_snprintf_default(char *buf, size_t size, ret = snprintf(buf + offset, remain, "\t"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); - ret = nftnl_set_elem_snprintf(buf + offset, remain, elem, type, - flags); + ret = nftnl_set_elem_snprintf_default(buf + offset, remain, + elem); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } return offset; } -static int nftnl_set_cmd_snprintf(char *buf, size_t size, +static int nftnl_set_cmd_snprintf(char *buf, size_t remain, const struct nftnl_set *s, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; uint32_t inner_flags = flags; + int ret, offset = 0; - if (type == NFTNL_OUTPUT_XML) - return 0; + if (type != NFTNL_OUTPUT_DEFAULT) + return -1; /* prevent set_elems to print as events */ inner_flags &= ~NFTNL_OF_EVENT_ANY; - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_set_snprintf_default(buf + offset, remain, s, type, - inner_flags); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - default: - return -1; - } - + ret = nftnl_set_snprintf_default(buf + offset, remain, s, type, + inner_flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } diff --git a/src/set_elem.c b/src/set_elem.c index e82684b..9207a0d 100644 --- a/src/set_elem.c +++ b/src/set_elem.c @@ -36,17 +36,21 @@ struct nftnl_set_elem *nftnl_set_elem_alloc(void) if (s == NULL) return NULL; + INIT_LIST_HEAD(&s->expr_list); + return s; } EXPORT_SYMBOL(nftnl_set_elem_free); void nftnl_set_elem_free(struct nftnl_set_elem *s) { + struct nftnl_expr *e, *tmp; + if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN)) xfree(s->data.chain); - if (s->flags & (1 << NFTNL_SET_ELEM_EXPR)) - nftnl_expr_free(s->expr); + list_for_each_entry_safe(e, tmp, &s->expr_list, head) + nftnl_expr_free(e); if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA)) xfree(s->user.data); @@ -66,6 +70,8 @@ bool nftnl_set_elem_is_set(const struct nftnl_set_elem *s, uint16_t attr) EXPORT_SYMBOL(nftnl_set_elem_unset); void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr) { + struct nftnl_expr *expr, *tmp; + if (!(s->flags & (1 << attr))) return; @@ -85,7 +91,9 @@ void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr) xfree(s->user.data); break; case NFTNL_SET_ELEM_EXPR: - nftnl_expr_free(s->expr); + case NFTNL_SET_ELEM_EXPRESSIONS: + list_for_each_entry_safe(expr, tmp, &s->expr_list, head) + nftnl_expr_free(expr); break; case NFTNL_SET_ELEM_OBJREF: xfree(s->objref); @@ -108,6 +116,8 @@ EXPORT_SYMBOL(nftnl_set_elem_set); int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr, const void *data, uint32_t data_len) { + struct nftnl_expr *expr, *tmp; + nftnl_assert_attr_exists(attr, NFTNL_SET_ELEM_MAX); nftnl_assert_validate(data, nftnl_set_elem_validate, attr, data_len); @@ -116,12 +126,12 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr, memcpy(&s->set_elem_flags, data, sizeof(s->set_elem_flags)); break; case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */ - memcpy(&s->key.val, data, data_len); - s->key.len = data_len; + if (nftnl_data_cpy(&s->key, data, data_len) < 0) + return -1; break; case NFTNL_SET_ELEM_KEY_END: /* NFTA_SET_ELEM_KEY_END */ - memcpy(&s->key_end.val, data, data_len); - s->key_end.len = data_len; + if (nftnl_data_cpy(&s->key_end, data, data_len) < 0) + return -1; break; case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */ memcpy(&s->data.verdict, data, sizeof(s->data.verdict)); @@ -135,8 +145,8 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr, return -1; break; case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */ - memcpy(s->data.val, data, data_len); - s->data.len = data_len; + if (nftnl_data_cpy(&s->data, data, data_len) < 0) + return -1; break; case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */ memcpy(&s->timeout, data, sizeof(s->timeout)); @@ -163,10 +173,11 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr, return -1; break; case NFTNL_SET_ELEM_EXPR: - if (s->flags & (1 << NFTNL_SET_ELEM_EXPR)) - nftnl_expr_free(s->expr); + list_for_each_entry_safe(expr, tmp, &s->expr_list, head) + nftnl_expr_free(expr); - s->expr = (void *)data; + expr = (void *)data; + list_add(&expr->head, &s->expr_list); break; } s->flags |= (1 << attr); @@ -194,6 +205,8 @@ int nftnl_set_elem_set_str(struct nftnl_set_elem *s, uint16_t attr, const char * EXPORT_SYMBOL(nftnl_set_elem_get); const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len) { + struct nftnl_expr *expr; + if (!(s->flags & (1 << attr))) return NULL; @@ -226,7 +239,9 @@ const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len = s->user.len; return s->user.data; case NFTNL_SET_ELEM_EXPR: - return s->expr; + list_for_each_entry(expr, &s->expr_list, head) + break; + return expr; case NFTNL_SET_ELEM_OBJREF: *data_len = strlen(s->objref) + 1; return s->objref; @@ -285,9 +300,13 @@ err: return NULL; } +EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build_payload); void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set_elem *e) { + struct nftnl_expr *expr; + int num_exprs = 0; + if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags)); if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT)) @@ -332,12 +351,30 @@ void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data); if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF)) mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref); - if (e->flags & (1 << NFTNL_SET_ELEM_EXPR)) { - struct nlattr *nest1; - nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR); - nftnl_expr_build_payload(nlh, e->expr); - mnl_attr_nest_end(nlh, nest1); + if (!list_empty(&e->expr_list)) { + list_for_each_entry(expr, &e->expr_list, head) + num_exprs++; + + if (num_exprs == 1) { + struct nlattr *nest1; + + nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR); + list_for_each_entry(expr, &e->expr_list, head) + nftnl_expr_build_payload(nlh, expr); + + mnl_attr_nest_end(nlh, nest1); + } else if (num_exprs > 1) { + struct nlattr *nest1, *nest2; + + nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPRESSIONS); + list_for_each_entry(expr, &e->expr_list, head) { + nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM); + nftnl_expr_build_payload(nlh, expr); + mnl_attr_nest_end(nlh, nest2); + } + mnl_attr_nest_end(nlh, nest1); + } } } @@ -352,8 +389,9 @@ static void nftnl_set_elem_nlmsg_build_def(struct nlmsghdr *nlh, mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table); } -static struct nlattr *nftnl_set_elem_build(struct nlmsghdr *nlh, - struct nftnl_set_elem *elem, int i) +EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build); +struct nlattr *nftnl_set_elem_nlmsg_build(struct nlmsghdr *nlh, + struct nftnl_set_elem *elem, int i) { struct nlattr *nest2; @@ -378,11 +416,33 @@ void nftnl_set_elems_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS); list_for_each_entry(elem, &s->element_list, head) - nftnl_set_elem_build(nlh, elem, ++i); + nftnl_set_elem_nlmsg_build(nlh, elem, ++i); mnl_attr_nest_end(nlh, nest1); } +EXPORT_SYMBOL(nftnl_set_elem_add_expr); +void nftnl_set_elem_add_expr(struct nftnl_set_elem *e, struct nftnl_expr *expr) +{ + list_add_tail(&expr->head, &e->expr_list); +} + +EXPORT_SYMBOL(nftnl_set_elem_expr_foreach); +int nftnl_set_elem_expr_foreach(struct nftnl_set_elem *e, + int (*cb)(struct nftnl_expr *e, void *data), + void *data) +{ + struct nftnl_expr *cur, *tmp; + int ret; + + list_for_each_entry_safe(cur, tmp, &e->expr_list, head) { + ret = cb(cur, data); + if (ret < 0) + return ret; + } + return 0; +} + static int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr, void *data) { const struct nlattr **tb = data; @@ -405,6 +465,7 @@ static int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr, void *data) case NFTA_SET_ELEM_KEY_END: case NFTA_SET_ELEM_DATA: case NFTA_SET_ELEM_EXPR: + case NFTA_SET_ELEM_EXPRESSIONS: if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) abi_breakage(); break; @@ -476,12 +537,32 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest } } if (tb[NFTA_SET_ELEM_EXPR]) { - e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]); - if (e->expr == NULL) { + struct nftnl_expr *expr; + + expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]); + if (expr == NULL) { ret = -1; goto out_set_elem; } + list_add_tail(&expr->head, &e->expr_list); e->flags |= (1 << NFTNL_SET_ELEM_EXPR); + } else if (tb[NFTA_SET_ELEM_EXPRESSIONS]) { + struct nftnl_expr *expr; + struct nlattr *attr; + + mnl_attr_for_each_nested(attr, tb[NFTA_SET_ELEM_EXPRESSIONS]) { + if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) { + ret = -1; + goto out_set_elem; + } + expr = nftnl_expr_parse(attr); + if (expr == NULL) { + ret = -1; + goto out_set_elem; + } + list_add_tail(&expr->head, &e->expr_list); + } + e->flags |= (1 << NFTNL_SET_ELEM_EXPRESSIONS); } if (tb[NFTA_SET_ELEM_USERDATA]) { const void *udata = @@ -494,7 +575,7 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest e->user.data = malloc(e->user.len); if (e->user.data == NULL) { ret = -1; - goto out_expr; + goto out_set_elem; } memcpy(e->user.data, udata, e->user.len); e->flags |= (1 << NFTNL_RULE_USERDATA); @@ -512,8 +593,6 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest list_add_tail(&e->head, &s->element_list); return 0; -out_expr: - nftnl_expr_free(e->expr); out_set_elem: nftnl_set_elem_free(e); return ret; @@ -621,67 +700,72 @@ int nftnl_set_elem_parse_file(struct nftnl_set_elem *e, enum nftnl_parse_type ty return -1; } -static int nftnl_set_elem_snprintf_default(char *buf, size_t size, - const struct nftnl_set_elem *e) +int nftnl_set_elem_snprintf_default(char *buf, size_t remain, + const struct nftnl_set_elem *e) { - int ret, remain = size, offset = 0, i; + int ret, dregtype = DATA_VALUE, offset = 0, i; ret = snprintf(buf, remain, "element "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); - for (i = 0; i < div_round_up(e->key.len, sizeof(uint32_t)); i++) { - ret = snprintf(buf + offset, remain, "%.8x ", e->key.val[i]); + ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key, + DATA_F_NOPFX, DATA_VALUE); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) { + ret = snprintf(buf + offset, remain, " - "); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key_end, + DATA_F_NOPFX, DATA_VALUE); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } ret = snprintf(buf + offset, remain, " : "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); - for (i = 0; i < div_round_up(e->data.len, sizeof(uint32_t)); i++) { - ret = snprintf(buf + offset, remain, "%.8x ", e->data.val[i]); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - } + if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) + dregtype = DATA_VERDICT; + + ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data, + DATA_F_NOPFX, dregtype); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = snprintf(buf + offset, remain, "%u [end]", e->set_elem_flags); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (e->user.len) { - ret = snprintf(buf + offset, remain, " userdata = {"); + ret = snprintf(buf + offset, remain, " userdata = { "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); for (i = 0; i < e->user.len; i++) { char *c = e->user.data; - ret = snprintf(buf + offset, remain, "%c", - isalnum(c[i]) ? c[i] : 0); + ret = snprintf(buf + offset, remain, + isprint(c[i]) ? "%c" : "\\x%02hhx", + c[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, remain, " }\n"); + ret = snprintf(buf + offset, remain, " }"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } return offset; } -static int nftnl_set_elem_cmd_snprintf(char *buf, size_t size, +static int nftnl_set_elem_cmd_snprintf(char *buf, size_t remain, const struct nftnl_set_elem *e, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch(type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - break; - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + + ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } @@ -818,7 +902,7 @@ int nftnl_set_elems_nlmsg_build_payload_iter(struct nlmsghdr *nlh, nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS); elem = nftnl_set_elems_iter_next(iter); while (elem != NULL) { - nest2 = nftnl_set_elem_build(nlh, elem, ++i); + nest2 = nftnl_set_elem_nlmsg_build(nlh, elem, ++i); if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) { /* Go back to previous not to miss this element */ iter->cur = list_entry(iter->cur->head.prev, diff --git a/src/table.c b/src/table.c index 731c818..13f01cf 100644 --- a/src/table.c +++ b/src/table.c @@ -34,6 +34,7 @@ struct nftnl_table { uint64_t handle; uint32_t use; uint32_t flags; + uint32_t owner; struct { void *data; uint32_t len; @@ -76,8 +77,8 @@ void nftnl_table_unset(struct nftnl_table *t, uint16_t attr) case NFTNL_TABLE_FLAGS: case NFTNL_TABLE_HANDLE: case NFTNL_TABLE_FAMILY: - break; case NFTNL_TABLE_USE: + case NFTNL_TABLE_OWNER: break; } t->flags &= ~(1 << attr); @@ -87,6 +88,8 @@ static uint32_t nftnl_table_validate[NFTNL_TABLE_MAX + 1] = { [NFTNL_TABLE_FLAGS] = sizeof(uint32_t), [NFTNL_TABLE_FAMILY] = sizeof(uint32_t), [NFTNL_TABLE_HANDLE] = sizeof(uint64_t), + [NFTNL_TABLE_USE] = sizeof(uint32_t), + [NFTNL_TABLE_OWNER] = sizeof(uint32_t), }; EXPORT_SYMBOL(nftnl_table_set_data); @@ -98,13 +101,8 @@ int nftnl_table_set_data(struct nftnl_table *t, uint16_t attr, switch (attr) { case NFTNL_TABLE_NAME: - if (t->flags & (1 << NFTNL_TABLE_NAME)) - xfree(t->name); - - t->name = strdup(data); - if (!t->name) - return -1; - break; + return nftnl_set_str_attr(&t->name, &t->flags, + attr, data, data_len); case NFTNL_TABLE_HANDLE: memcpy(&t->handle, data, sizeof(t->handle)); break; @@ -127,6 +125,9 @@ int nftnl_table_set_data(struct nftnl_table *t, uint16_t attr, memcpy(t->user.data, data, data_len); t->user.len = data_len; break; + case NFTNL_TABLE_OWNER: + memcpy(&t->owner, data, sizeof(t->owner)); + break; } t->flags |= (1 << attr); return 0; @@ -188,6 +189,9 @@ const void *nftnl_table_get_data(const struct nftnl_table *t, uint16_t attr, case NFTNL_TABLE_USERDATA: *data_len = t->user.len; return t->user.data; + case NFTNL_TABLE_OWNER: + *data_len = sizeof(uint32_t); + return &t->owner; } return NULL; } @@ -258,6 +262,7 @@ static int nftnl_table_parse_attr_cb(const struct nlattr *attr, void *data) break; case NFTA_TABLE_FLAGS: case NFTA_TABLE_USE: + case NFTA_TABLE_OWNER: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) abi_breakage(); break; @@ -308,6 +313,10 @@ int nftnl_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_table *t) if (ret < 0) return ret; } + if (tb[NFTA_TABLE_OWNER]) { + t->owner = ntohl(mnl_attr_get_u32(tb[NFTA_TABLE_OWNER])); + t->flags |= (1 << NFTNL_TABLE_OWNER); + } t->family = nfg->nfgen_family; t->flags |= (1 << NFTNL_TABLE_FAMILY); @@ -355,23 +364,17 @@ static int nftnl_table_snprintf_default(char *buf, size_t size, t->table_flags, t->use, (unsigned long long)t->handle); } -static int nftnl_table_cmd_snprintf(char *buf, size_t size, +static int nftnl_table_cmd_snprintf(char *buf, size_t remain, const struct nftnl_table *t, uint32_t cmd, uint32_t type, uint32_t flags) { - int ret, remain = size, offset = 0; + int ret, offset = 0; - switch (type) { - case NFTNL_OUTPUT_DEFAULT: - ret = nftnl_table_snprintf_default(buf + offset, remain, t); - SNPRINTF_BUFFER_SIZE(ret, remain, offset); - break; - case NFTNL_OUTPUT_XML: - case NFTNL_OUTPUT_JSON: - default: + if (type != NFTNL_OUTPUT_DEFAULT) return -1; - } + ret = nftnl_table_snprintf_default(buf + offset, remain, t); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; } diff --git a/src/udata.c b/src/udata.c index 0cc3520..e9bfc35 100644 --- a/src/udata.c +++ b/src/udata.c @@ -42,6 +42,11 @@ uint32_t nftnl_udata_buf_len(const struct nftnl_udata_buf *buf) return (uint32_t)(buf->end - buf->data); } +static uint32_t nftnl_udata_buf_space(const struct nftnl_udata_buf *buf) +{ + return buf->size - nftnl_udata_buf_len(buf); +} + EXPORT_SYMBOL(nftnl_udata_buf_data); void *nftnl_udata_buf_data(const struct nftnl_udata_buf *buf) { @@ -74,7 +79,8 @@ bool nftnl_udata_put(struct nftnl_udata_buf *buf, uint8_t type, uint32_t len, { struct nftnl_udata *attr; - if (len > UINT8_MAX || buf->size < len + sizeof(struct nftnl_udata)) + if (len > UINT8_MAX || + nftnl_udata_buf_space(buf) < len + sizeof(struct nftnl_udata)) return false; attr = (struct nftnl_udata *)buf->end; diff --git a/src/utils.c b/src/utils.c index 3617837..2f1ffd6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -39,146 +39,6 @@ const char *nftnl_family2str(uint32_t family) return nftnl_family_str[family]; } -int nftnl_str2family(const char *family) -{ - int i; - - for (i = 0; i < NFPROTO_NUMPROTO; i++) { - if (nftnl_family_str[i] == NULL) - continue; - - if (strcmp(nftnl_family_str[i], family) == 0) - return i; - } - - errno = EAFNOSUPPORT; - return -1; -} - -static struct { - int len; - int64_t min; - uint64_t max; -} basetype[] = { - [NFTNL_TYPE_U8] = { .len = sizeof(uint8_t), .max = UINT8_MAX }, - [NFTNL_TYPE_U16] = { .len = sizeof(uint16_t), .max = UINT16_MAX }, - [NFTNL_TYPE_U32] = { .len = sizeof(uint32_t), .max = UINT32_MAX }, - [NFTNL_TYPE_U64] = { .len = sizeof(uint64_t), .max = UINT64_MAX }, - [NFTNL_TYPE_S8] = { .len = sizeof(int8_t), .min = INT8_MIN, .max = INT8_MAX }, - [NFTNL_TYPE_S16] = { .len = sizeof(int16_t), .min = INT16_MIN, .max = INT16_MAX }, - [NFTNL_TYPE_S32] = { .len = sizeof(int32_t), .min = INT32_MIN, .max = INT32_MAX }, - [NFTNL_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX }, -}; - -int nftnl_get_value(enum nftnl_type type, void *val, void *out) -{ - union { - uint8_t u8; - uint16_t u16; - uint32_t u32; - int8_t s8; - int16_t s16; - int32_t s32; - } values; - void *valuep = NULL; - int64_t sval; - uint64_t uval; - - switch (type) { - case NFTNL_TYPE_U8: - case NFTNL_TYPE_U16: - case NFTNL_TYPE_U32: - case NFTNL_TYPE_U64: - memcpy(&uval, val, sizeof(uval)); - if (uval > basetype[type].max) { - errno = ERANGE; - return -1; - } - break; - case NFTNL_TYPE_S8: - case NFTNL_TYPE_S16: - case NFTNL_TYPE_S32: - case NFTNL_TYPE_S64: - memcpy(&sval, val, sizeof(sval)); - if (sval < basetype[type].min || - sval > (int64_t)basetype[type].max) { - errno = ERANGE; - return -1; - } - break; - } - - switch (type) { - case NFTNL_TYPE_U8: - values.u8 = uval; - valuep = &values.u8; - break; - case NFTNL_TYPE_U16: - values.u16 = uval; - valuep = &values.u16; - break; - case NFTNL_TYPE_U32: - values.u32 = uval; - valuep = &values.u32; - break; - case NFTNL_TYPE_U64: - valuep = &uval; - break; - case NFTNL_TYPE_S8: - values.s8 = sval; - valuep = &values.s8; - break; - case NFTNL_TYPE_S16: - values.s16 = sval; - valuep = &values.s16; - break; - case NFTNL_TYPE_S32: - values.s32 = sval; - valuep = &values.s32; - break; - case NFTNL_TYPE_S64: - valuep = &sval; - break; - } - memcpy(out, valuep, basetype[type].len); - return 0; -} - -int nftnl_strtoi(const char *string, int base, void *out, enum nftnl_type type) -{ - int ret; - int64_t sval = 0; - uint64_t uval = -1; - char *endptr; - - switch (type) { - case NFTNL_TYPE_U8: - case NFTNL_TYPE_U16: - case NFTNL_TYPE_U32: - case NFTNL_TYPE_U64: - uval = strtoll(string, &endptr, base); - ret = nftnl_get_value(type, &uval, out); - break; - case NFTNL_TYPE_S8: - case NFTNL_TYPE_S16: - case NFTNL_TYPE_S32: - case NFTNL_TYPE_S64: - sval = strtoull(string, &endptr, base); - ret = nftnl_get_value(type, &sval, out); - break; - default: - errno = EINVAL; - return -1; - } - - if (*endptr) { - errno = EINVAL; - return -1; - } - - return ret; -} - const char *nftnl_verdict2str(uint32_t verdict) { switch (verdict) { @@ -209,28 +69,6 @@ const char *nftnl_verdict2str(uint32_t verdict) } } -int nftnl_str2verdict(const char *verdict, int *verdict_num) -{ - if (strcmp(verdict, "accept") == 0) { - *verdict_num = NF_ACCEPT; - return 0; - } else if (strcmp(verdict, "drop") == 0) { - *verdict_num = NF_DROP; - return 0; - } else if (strcmp(verdict, "return") == 0) { - *verdict_num = NFT_RETURN; - return 0; - } else if (strcmp(verdict, "jump") == 0) { - *verdict_num = NFT_JUMP; - return 0; - } else if (strcmp(verdict, "goto") == 0) { - *verdict_num = NFT_GOTO; - return 0; - } - - return -1; -} - enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags) { if (flags & NFTNL_OF_EVENT_NEW) @@ -241,38 +79,6 @@ enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags) return NFTNL_CMD_UNSPEC; } -static const char *cmd2tag[NFTNL_CMD_MAX] = { - [NFTNL_CMD_ADD] = "add", - [NFTNL_CMD_INSERT] = "insert", - [NFTNL_CMD_DELETE] = "delete", - [NFTNL_CMD_REPLACE] = "replace", - [NFTNL_CMD_FLUSH] = "flush", -}; - -const char *nftnl_cmd2tag(enum nftnl_cmd_type cmd) -{ - if (cmd >= NFTNL_CMD_MAX) - return "unknown"; - - return cmd2tag[cmd]; -} - -uint32_t nftnl_str2cmd(const char *cmd) -{ - if (strcmp(cmd, "add") == 0) - return NFTNL_CMD_ADD; - else if (strcmp(cmd, "insert") == 0) - return NFTNL_CMD_INSERT; - else if (strcmp(cmd, "delete") == 0) - return NFTNL_CMD_DELETE; - else if (strcmp(cmd, "replace") == 0) - return NFTNL_CMD_REPLACE; - else if (strcmp(cmd, "flush") == 0) - return NFTNL_CMD_FLUSH; - - return NFTNL_CMD_UNSPEC; -} - int nftnl_fprintf(FILE *fp, const void *obj, uint32_t cmd, uint32_t type, uint32_t flags, int (*snprintf_cb)(char *buf, size_t bufsiz, const void *obj, @@ -330,3 +136,17 @@ void __noreturn __abi_breakage(const char *file, int line, const char *reason) "%s:%d reason: %s\n", file, line, reason); exit(EXIT_FAILURE); } + +int nftnl_set_str_attr(const char **dptr, uint32_t *flags, + uint16_t attr, const void *data, uint32_t data_len) +{ + if (*flags & (1 << attr)) + xfree(*dptr); + + *dptr = strndup(data, data_len); + if (!*dptr) + return -1; + + *flags |= (1 << attr); + return 0; +} diff --git a/tests/nft-chain-test.c b/tests/nft-chain-test.c index d678d46..35a65be 100644 --- a/tests/nft-chain-test.c +++ b/tests/nft-chain-test.c @@ -89,8 +89,7 @@ int main(int argc, char *argv[]) nftnl_chain_set_str(a, NFTNL_CHAIN_DEV, "eth0"); /* cmd extracted from include/linux/netfilter/nf_tables.h */ - nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET, - 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET, 0, 1234); nftnl_chain_nlmsg_build_payload(nlh, a); if (nftnl_chain_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_bitwise-test.c b/tests/nft-expr_bitwise-test.c index f134728..44c4bf0 100644 --- a/tests/nft-expr_bitwise-test.c +++ b/tests/nft-expr_bitwise-test.c @@ -129,7 +129,7 @@ static void test_bool(void) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) @@ -183,7 +183,7 @@ static void test_lshift(void) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) @@ -237,7 +237,7 @@ static void test_rshift(void) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_byteorder-test.c b/tests/nft-expr_byteorder-test.c index 5994e5b..30e64c0 100644 --- a/tests/nft-expr_byteorder-test.c +++ b/tests/nft-expr_byteorder-test.c @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_cmp-test.c b/tests/nft-expr_cmp-test.c index ec00bb9..0bab67b 100644 --- a/tests/nft-expr_cmp-test.c +++ b/tests/nft-expr_cmp-test.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_counter-test.c b/tests/nft-expr_counter-test.c index 519bc1f..81c3fe1 100644 --- a/tests/nft-expr_counter-test.c +++ b/tests/nft-expr_counter-test.c @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) nftnl_expr_set_u64(ex, NFTNL_EXPR_CTR_PACKETS, 0xf0123456789abcde); nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_ct-test.c b/tests/nft-expr_ct-test.c index e98fbab..548a426 100644 --- a/tests/nft-expr_ct-test.c +++ b/tests/nft-expr_ct-test.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_dup-test.c b/tests/nft-expr_dup-test.c index 3c37d4a..0c5df9a 100644 --- a/tests/nft-expr_dup-test.c +++ b/tests/nft-expr_dup-test.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_exthdr-test.c b/tests/nft-expr_exthdr-test.c index fef2dd0..b2c72b7 100644 --- a/tests/nft-expr_exthdr-test.c +++ b/tests/nft-expr_exthdr-test.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_fwd-test.c b/tests/nft-expr_fwd-test.c index 4fdf53d..825dad3 100644 --- a/tests/nft-expr_fwd-test.c +++ b/tests/nft-expr_fwd-test.c @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_hash-test.c b/tests/nft-expr_hash-test.c index 7be6e9e..6644bb7 100644 --- a/tests/nft-expr_hash-test.c +++ b/tests/nft-expr_hash-test.c @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_immediate-test.c b/tests/nft-expr_immediate-test.c index c25eedb..5027813 100644 --- a/tests/nft-expr_immediate-test.c +++ b/tests/nft-expr_immediate-test.c @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex_val); nftnl_rule_add_expr(a, ex_ver); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_limit-test.c b/tests/nft-expr_limit-test.c index 2838941..38aaf56 100644 --- a/tests/nft-expr_limit-test.c +++ b/tests/nft-expr_limit-test.c @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_log-test.c b/tests/nft-expr_log-test.c index b7aa302..275ffae 100644 --- a/tests/nft-expr_log-test.c +++ b/tests/nft-expr_log-test.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_lookup-test.c b/tests/nft-expr_lookup-test.c index 9e6e051..9b70525 100644 --- a/tests/nft-expr_lookup-test.c +++ b/tests/nft-expr_lookup-test.c @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_masq-test.c b/tests/nft-expr_masq-test.c index 3f9903d..0917914 100644 --- a/tests/nft-expr_masq-test.c +++ b/tests/nft-expr_masq-test.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_match-test.c b/tests/nft-expr_match-test.c index 39a49d8..fdeacc4 100644 --- a/tests/nft-expr_match-test.c +++ b/tests/nft-expr_match-test.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) nftnl_expr_set(ex, NFTNL_EXPR_MT_INFO, strdup(data), sizeof(data)); nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_meta-test.c b/tests/nft-expr_meta-test.c index 8fb7873..2f03fb1 100644 --- a/tests/nft-expr_meta-test.c +++ b/tests/nft-expr_meta-test.c @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_nat-test.c b/tests/nft-expr_nat-test.c index fd3a488..3a365dd 100644 --- a/tests/nft-expr_nat-test.c +++ b/tests/nft-expr_nat-test.c @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_numgen-test.c b/tests/nft-expr_numgen-test.c index 0d0a3bb..94df50f 100644 --- a/tests/nft-expr_numgen-test.c +++ b/tests/nft-expr_numgen-test.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_objref-test.c b/tests/nft-expr_objref-test.c index 08e27ce..9e698df 100644 --- a/tests/nft-expr_objref-test.c +++ b/tests/nft-expr_objref-test.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) b = nftnl_rule_alloc(); if (a == NULL || b == NULL) print_err("OOM"); - ex = nftnl_expr_alloc("lookup"); + ex = nftnl_expr_alloc("objref"); if (ex == NULL) print_err("OOM"); diff --git a/tests/nft-expr_payload-test.c b/tests/nft-expr_payload-test.c index 371372c..aec1710 100644 --- a/tests/nft-expr_payload-test.c +++ b/tests/nft-expr_payload-test.c @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) print_err("parsing problems"); diff --git a/tests/nft-expr_queue-test.c b/tests/nft-expr_queue-test.c index 81d7dd2..d007b98 100644 --- a/tests/nft-expr_queue-test.c +++ b/tests/nft-expr_queue-test.c @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_quota-test.c b/tests/nft-expr_quota-test.c index 2320551..a3eb2e3 100644 --- a/tests/nft-expr_quota-test.c +++ b/tests/nft-expr_quota-test.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) nftnl_expr_set_u32(ex, NFTNL_EXPR_QUOTA_FLAGS, 0x12345678); nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_range-test.c b/tests/nft-expr_range-test.c index b92dfc0..6ef896b 100644 --- a/tests/nft-expr_range-test.c +++ b/tests/nft-expr_range-test.c @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_redir-test.c b/tests/nft-expr_redir-test.c index 6c8caec..8e1f30c 100644 --- a/tests/nft-expr_redir-test.c +++ b/tests/nft-expr_redir-test.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_reject-test.c b/tests/nft-expr_reject-test.c index d8189ea..049401d 100644 --- a/tests/nft-expr_reject-test.c +++ b/tests/nft-expr_reject-test.c @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-expr_target-test.c b/tests/nft-expr_target-test.c index ba56b27..a517206 100644 --- a/tests/nft-expr_target-test.c +++ b/tests/nft-expr_target-test.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) nftnl_expr_set(ex, NFTNL_EXPR_TG_INFO, strdup(data), sizeof(data)); nftnl_rule_add_expr(a, ex); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-rule-test.c b/tests/nft-rule-test.c index dee3530..3a92223 100644 --- a/tests/nft-rule-test.c +++ b/tests/nft-rule-test.c @@ -48,6 +48,12 @@ static void cmp_nftnl_rule(struct nftnl_rule *a, struct nftnl_rule *b) if (nftnl_rule_get_u32(a, NFTNL_RULE_COMPAT_FLAGS) != nftnl_rule_get_u32(b, NFTNL_RULE_COMPAT_FLAGS)) print_err("Rule compat_flags mismatches"); + if (nftnl_rule_get_u32(a, NFTNL_RULE_ID) != + nftnl_rule_get_u32(b, NFTNL_RULE_ID)) + print_err("Rule id mismatches"); + if (nftnl_rule_get_u32(a, NFTNL_RULE_POSITION_ID) != + nftnl_rule_get_u32(b, NFTNL_RULE_POSITION_ID)) + print_err("Rule position_id mismatches"); if (nftnl_rule_get_u64(a, NFTNL_RULE_POSITION) != nftnl_rule_get_u64(b, NFTNL_RULE_POSITION)) print_err("Rule compat_position mismatches"); @@ -84,13 +90,15 @@ int main(int argc, char *argv[]) nftnl_rule_set_u64(a, NFTNL_RULE_HANDLE, 0x1234567812345678); nftnl_rule_set_u32(a, NFTNL_RULE_COMPAT_PROTO, 0x12345678); nftnl_rule_set_u32(a, NFTNL_RULE_COMPAT_FLAGS, 0x12345678); + nftnl_rule_set_u32(a, NFTNL_RULE_ID, 0x12345678); + nftnl_rule_set_u32(a, NFTNL_RULE_POSITION_ID, 0x12345678); nftnl_rule_set_u64(a, NFTNL_RULE_POSITION, 0x1234567812345678); nftnl_rule_set_data(a, NFTNL_RULE_USERDATA, nftnl_udata_buf_data(udata), nftnl_udata_buf_len(udata)); nftnl_udata_buf_free(udata); - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234); nftnl_rule_nlmsg_build_payload(nlh, a); if (nftnl_rule_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-set-test.c b/tests/nft-set-test.c index 173c17f..66916fe 100644 --- a/tests/nft-set-test.c +++ b/tests/nft-set-test.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) nftnl_set_set_str(a, NFTNL_SET_USERDATA, "testing user data"); /* cmd extracted from include/linux/netfilter/nf_tables.h */ - nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_NEWSET, AF_INET, 0, 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWSET, AF_INET, 0, 1234); nftnl_set_nlmsg_build_payload(nlh, a); if (nftnl_set_nlmsg_parse(nlh, b) < 0) diff --git a/tests/nft-table-test.c b/tests/nft-table-test.c index 1031ffe..53cf3d1 100644 --- a/tests/nft-table-test.c +++ b/tests/nft-table-test.c @@ -34,7 +34,7 @@ static void cmp_nftnl_table(struct nftnl_table *a, struct nftnl_table *b) print_err("table flags mismatches"); if (nftnl_table_get_u32(a, NFTNL_TABLE_FAMILY) != nftnl_table_get_u32(b, NFTNL_TABLE_FAMILY)) - print_err("tabke family mismatches"); + print_err("table family mismatches"); } int main(int argc, char *argv[]) @@ -55,8 +55,7 @@ int main(int argc, char *argv[]) nftnl_table_set_u32(a, NFTNL_TABLE_FLAGS, 0); /* cmd extracted from include/linux/netfilter/nf_tables.h */ - nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET, 0, - 1234); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET, 0, 1234); nftnl_table_nlmsg_build_payload(nlh, a); if (nftnl_table_nlmsg_parse(nlh, b) < 0) |