Let's update the mnl source code to match the latest in nft. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> --- include/linux/netfilter/nf_tables.h | 125 +++++++++++++++++++++- include/mnl.h | 2 include/utils.h | 9 ++ src/main.c | 2 src/mnl.c | 198 ++++++++++++++++++++++------------- src/utils.c | 7 + 6 files changed, 261 insertions(+), 82 deletions(-) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 11d5937..832bc46 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -1,7 +1,8 @@ #ifndef _LINUX_NF_TABLES_H #define _LINUX_NF_TABLES_H -#define NFT_CHAIN_MAXNAMELEN 32 +#define NFT_CHAIN_MAXNAMELEN 32 +#define NFT_USERDATA_MAXLEN 256 enum nft_registers { NFT_REG_VERDICT, @@ -50,6 +51,8 @@ enum nft_verdicts { * @NFT_MSG_NEWSETELEM: create a new set element (enum nft_set_elem_attributes) * @NFT_MSG_GETSETELEM: get a set element (enum nft_set_elem_attributes) * @NFT_MSG_DELSETELEM: delete a set element (enum nft_set_elem_attributes) + * @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes) + * @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes) */ enum nf_tables_msg_types { NFT_MSG_NEWTABLE, @@ -67,6 +70,8 @@ enum nf_tables_msg_types { NFT_MSG_NEWSETELEM, NFT_MSG_GETSETELEM, NFT_MSG_DELSETELEM, + NFT_MSG_NEWGEN, + NFT_MSG_GETGEN, NFT_MSG_MAX, }; @@ -156,6 +161,7 @@ enum nft_chain_attributes { * @NFTA_RULE_EXPRESSIONS: list of expressions (NLA_NESTED: nft_expr_attributes) * @NFTA_RULE_COMPAT: compatibility specifications of the rule (NLA_NESTED: nft_rule_compat_attributes) * @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64) + * @NFTA_RULE_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN) */ enum nft_rule_attributes { NFTA_RULE_UNSPEC, @@ -165,6 +171,7 @@ enum nft_rule_attributes { NFTA_RULE_EXPRESSIONS, NFTA_RULE_COMPAT, NFTA_RULE_POSITION, + NFTA_RULE_USERDATA, __NFTA_RULE_MAX }; #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) @@ -209,6 +216,29 @@ enum nft_set_flags { }; /** + * enum nft_set_policies - set selection policy + * + * @NFT_SET_POL_PERFORMANCE: prefer high performance over low memory use + * @NFT_SET_POL_MEMORY: prefer low memory use over high performance + */ +enum nft_set_policies { + NFT_SET_POL_PERFORMANCE, + NFT_SET_POL_MEMORY, +}; + +/** + * enum nft_set_desc_attributes - set element description + * + * @NFTA_SET_DESC_SIZE: number of elements in set (NLA_U32) + */ +enum nft_set_desc_attributes { + NFTA_SET_DESC_UNSPEC, + NFTA_SET_DESC_SIZE, + __NFTA_SET_DESC_MAX +}; +#define NFTA_SET_DESC_MAX (__NFTA_SET_DESC_MAX - 1) + +/** * enum nft_set_attributes - nf_tables set netlink attributes * * @NFTA_SET_TABLE: table name (NLA_STRING) @@ -218,6 +248,9 @@ enum nft_set_flags { * @NFTA_SET_KEY_LEN: key data length (NLA_U32) * @NFTA_SET_DATA_TYPE: mapping data type (NLA_U32) * @NFTA_SET_DATA_LEN: mapping data length (NLA_U32) + * @NFTA_SET_POLICY: selection policy (NLA_U32) + * @NFTA_SET_DESC: set description (NLA_NESTED) + * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32) */ enum nft_set_attributes { NFTA_SET_UNSPEC, @@ -228,6 +261,9 @@ enum nft_set_attributes { NFTA_SET_KEY_LEN, NFTA_SET_DATA_TYPE, NFTA_SET_DATA_LEN, + NFTA_SET_POLICY, + NFTA_SET_DESC, + NFTA_SET_ID, __NFTA_SET_MAX }; #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) @@ -263,12 +299,14 @@ enum nft_set_elem_attributes { * @NFTA_SET_ELEM_LIST_TABLE: table of the set to be changed (NLA_STRING) * @NFTA_SET_ELEM_LIST_SET: name of the set to be changed (NLA_STRING) * @NFTA_SET_ELEM_LIST_ELEMENTS: list of set elements (NLA_NESTED: nft_set_elem_attributes) + * @NFTA_SET_ELEM_LIST_SET_ID: uniquely identifies a set in a transaction (NLA_U32) */ enum nft_set_elem_list_attributes { NFTA_SET_ELEM_LIST_UNSPEC, NFTA_SET_ELEM_LIST_TABLE, NFTA_SET_ELEM_LIST_SET, NFTA_SET_ELEM_LIST_ELEMENTS, + NFTA_SET_ELEM_LIST_SET_ID, __NFTA_SET_ELEM_LIST_MAX }; #define NFTA_SET_ELEM_LIST_MAX (__NFTA_SET_ELEM_LIST_MAX - 1) @@ -454,12 +492,14 @@ enum nft_cmp_attributes { * @NFTA_LOOKUP_SET: name of the set where to look for (NLA_STRING) * @NFTA_LOOKUP_SREG: source register of the data to look for (NLA_U32: nft_registers) * @NFTA_LOOKUP_DREG: destination register (NLA_U32: nft_registers) + * @NFTA_LOOKUP_SET_ID: uniquely identifies a set in a transaction (NLA_U32) */ enum nft_lookup_attributes { NFTA_LOOKUP_UNSPEC, NFTA_LOOKUP_SET, NFTA_LOOKUP_SREG, NFTA_LOOKUP_DREG, + NFTA_LOOKUP_SET_ID, __NFTA_LOOKUP_MAX }; #define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1) @@ -535,6 +575,11 @@ enum nft_exthdr_attributes { * @NFT_META_L4PROTO: layer 4 protocol number * @NFT_META_BRI_IIFNAME: packet input bridge interface name * @NFT_META_BRI_OIFNAME: packet output bridge interface name + * @NFT_META_PKTTYPE: packet type (skb->pkt_type), special handling for loopback + * @NFT_META_CPU: cpu id through smp_processor_id() + * @NFT_META_IIFGROUP: packet input interface group + * @NFT_META_OIFGROUP: packet output interface group + * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) */ enum nft_meta_keys { NFT_META_LEN, @@ -556,6 +601,11 @@ enum nft_meta_keys { NFT_META_L4PROTO, NFT_META_BRI_IIFNAME, NFT_META_BRI_OIFNAME, + NFT_META_PKTTYPE, + NFT_META_CPU, + NFT_META_IIFGROUP, + NFT_META_OIFGROUP, + NFT_META_CGROUP, }; /** @@ -590,7 +640,6 @@ enum nft_meta_attributes { * @NFT_CT_PROTOCOL: conntrack layer 4 protocol * @NFT_CT_PROTO_SRC: conntrack layer 4 protocol source * @NFT_CT_PROTO_DST: conntrack layer 4 protocol destination - * @NFT_CT_LABELS: conntrack label bitset (stored in conntrack extension) */ enum nft_ct_keys { NFT_CT_STATE, @@ -606,7 +655,7 @@ enum nft_ct_keys { NFT_CT_PROTOCOL, NFT_CT_PROTO_SRC, NFT_CT_PROTO_DST, - NFT_CT_LABEL, + NFT_CT_LABELS, }; /** @@ -615,12 +664,14 @@ enum nft_ct_keys { * @NFTA_CT_DREG: destination register (NLA_U32) * @NFTA_CT_KEY: conntrack data item to load (NLA_U32: nft_ct_keys) * @NFTA_CT_DIRECTION: direction in case of directional keys (NLA_U8) + * @NFTA_CT_SREG: source register (NLA_U32) */ enum nft_ct_attributes { NFTA_CT_UNSPEC, NFTA_CT_DREG, NFTA_CT_KEY, NFTA_CT_DIRECTION, + NFTA_CT_SREG, __NFTA_CT_MAX }; #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) @@ -660,6 +711,8 @@ enum nft_counter_attributes { * @NFTA_LOG_PREFIX: prefix to prepend to log messages (NLA_STRING) * @NFTA_LOG_SNAPLEN: length of payload to include in netlink message (NLA_U32) * @NFTA_LOG_QTHRESHOLD: queue threshold (NLA_U32) + * @NFTA_LOG_LEVEL: log level (NLA_U32) + * @NFTA_LOG_FLAGS: logging flags (NLA_U32) */ enum nft_log_attributes { NFTA_LOG_UNSPEC, @@ -667,6 +720,8 @@ enum nft_log_attributes { NFTA_LOG_PREFIX, NFTA_LOG_SNAPLEN, NFTA_LOG_QTHRESHOLD, + NFTA_LOG_LEVEL, + NFTA_LOG_FLAGS, __NFTA_LOG_MAX }; #define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1) @@ -696,11 +751,32 @@ enum nft_queue_attributes { * * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable * @NFT_REJECT_TCP_RST: reject using TCP RST + * @NFT_REJECT_ICMPX_UNREACH: abstracted ICMP unreachable for bridge and inet */ enum nft_reject_types { NFT_REJECT_ICMP_UNREACH, NFT_REJECT_TCP_RST, + NFT_REJECT_ICMPX_UNREACH, +}; + +/** + * enum nft_reject_code - Generic reject codes for IPv4/IPv6 + * + * @NFT_REJECT_ICMPX_NO_ROUTE: no route to host / network unreachable + * @NFT_REJECT_ICMPX_PORT_UNREACH: port unreachable + * @NFT_REJECT_ICMPX_HOST_UNREACH: host unreachable + * @NFT_REJECT_ICMPX_ADMIN_PROHIBITED: administratively prohibited + * + * These codes are mapped to real ICMP and ICMPv6 codes. + */ +enum nft_reject_inet_code { + NFT_REJECT_ICMPX_NO_ROUTE = 0, + NFT_REJECT_ICMPX_PORT_UNREACH, + NFT_REJECT_ICMPX_HOST_UNREACH, + NFT_REJECT_ICMPX_ADMIN_PROHIBITED, + __NFT_REJECT_ICMPX_MAX }; +#define NFT_REJECT_ICMPX_MAX (__NFT_REJECT_ICMPX_MAX - 1) /** * enum nft_reject_attributes - nf_tables reject expression netlink attributes @@ -736,6 +812,7 @@ enum nft_nat_types { * @NFTA_NAT_REG_ADDR_MAX: source register of address range end (NLA_U32: nft_registers) * @NFTA_NAT_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers) * @NFTA_NAT_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers) + * @NFTA_NAT_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) */ enum nft_nat_attributes { NFTA_NAT_UNSPEC, @@ -745,19 +822,49 @@ enum nft_nat_attributes { NFTA_NAT_REG_ADDR_MAX, NFTA_NAT_REG_PROTO_MIN, NFTA_NAT_REG_PROTO_MAX, + NFTA_NAT_FLAGS, __NFTA_NAT_MAX }; #define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1) /** - * enum nft_nfacct_attributes - nf_tables nfacct expression netlink attributes + * enum nft_masq_attributes - nf_tables masquerade expression attributes + * + * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) + */ +enum nft_masq_attributes { + NFTA_MASQ_UNSPEC, + NFTA_MASQ_FLAGS, + __NFTA_MASQ_MAX +}; +#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1) + +/** + * enum nft_redir_attributes - nf_tables redirect expression netlink attributes + * + * @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers) + * @NFTA_REDIR_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers) + * @NFTA_REDIR_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) + */ +enum nft_redir_attributes { + NFTA_REDIR_UNSPEC, + NFTA_REDIR_REG_PROTO_MIN, + NFTA_REDIR_REG_PROTO_MAX, + NFTA_REDIR_FLAGS, + __NFTA_REDIR_MAX +}; +#define NFTA_REDIR_MAX (__NFTA_REDIR_MAX - 1) + +/** + * enum nft_gen_attributes - nf_tables ruleset generation attributes * - * @NFTA_NFACCT_NAME: nfacct object name (NLA_STRING) + * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32) */ -enum nft_nfacct_attributes { - NFTA_NFACCT_NAME, - __NFTA_NFACCT_MAX, +enum nft_gen_attributes { + NFTA_GEN_UNSPEC, + NFTA_GEN_ID, + __NFTA_GEN_MAX }; -#define NFTA_NFACCT_MAX (__NFTA_NFACCT_MAX -1) +#define NFTA_GEN_MAX (__NFTA_GEN_MAX - 1) #endif /* _LINUX_NF_TABLES_H */ diff --git a/include/mnl.h b/include/mnl.h index cd146bd..db409c4 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -11,6 +11,8 @@ #include "config.h" +void mnl_genid_get(struct mnl_socket *nf_sock); + struct nft_rule_list *mnl_rule_dump(struct mnl_socket *nf_sock, int family); struct nft_chain_list *mnl_chain_dump(struct mnl_socket *nf_sock, int family); struct nft_table_list *mnl_table_dump(struct mnl_socket *nf_sock, int family); diff --git a/include/utils.h b/include/utils.h index 8d0eb38..d6be446 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,7 +1,16 @@ #ifndef _UTILS_H_ #define _UTILS_H_ +#include <stdint.h> + +#define __noreturn __attribute__((__noreturn__)) + void xfree(const void *ptr); +void __memory_allocation_error(const char *filename, uint32_t line) __noreturn; + +#define memory_allocation_error() \ + __memory_allocation_error(__FILE__, __LINE__); + #endif /* _UTILS_H_ */ diff --git a/src/main.c b/src/main.c index 0e6a8bc..e8f2dab 100644 --- a/src/main.c +++ b/src/main.c @@ -108,6 +108,8 @@ int main(int argc, char *argv[]) goto err; } + mnl_genid_get(nfts_inst.nl_query_sock); + nfts_log(NFTS_LOG_INFO, "listening at %s", inet_ntoa(nfts_inst.tcp.server.ipv4.inet_addr)); } diff --git a/src/mnl.c b/src/mnl.c index 3bb3ade..65ac4ea 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -14,27 +14,36 @@ #include <errno.h> #include <stdlib.h> +#include <fcntl.h> +#include "utils.h" #include "mnl.h" #include "linux/netfilter/nf_tables.h" #include "linux/netfilter.h" +#include <linux/netfilter/nfnetlink.h> +#include <libnftnl/ruleset.h> +#include <libnftnl/common.h> static int seq; +/* The largest nf_tables netlink message is the set element message, which + * contains the NFTA_SET_ELEM_LIST_ELEMENTS attribute. This attribute is + * a nest that describes the set elements. Given that the netlink attribute + * length (nla_len) is 16 bits, the largest message is a bit larger than + * 64 KBytes. + */ +#define NFT_NLMSG_MAXSIZE (UINT16_MAX + getpagesize()) + static int -nfts_mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len, +nfts_mnl_recv(struct mnl_socket *nf_sock, uint32_t seqnum, uint32_t portid, int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data) { - char buf[MNL_SOCKET_BUFFER_SIZE]; - uint32_t portid = mnl_socket_get_portid(nf_sock); + char buf[NFT_NLMSG_MAXSIZE]; int ret; - if (mnl_socket_sendto(nf_sock, data, len) < 0) - return -1; - ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf)); while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, cb, cb_data); + ret = mnl_cb_run(buf, ret, seqnum, portid, cb, cb_data); if (ret <= 0) goto out; @@ -47,6 +56,53 @@ out: return ret; } +static int +nfts_mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len, + int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data) +{ + uint32_t portid = mnl_socket_get_portid(nf_sock); + + if (mnl_socket_sendto(nf_sock, data, len) < 0) + return -1; + + return nfts_mnl_recv(nf_sock, seq, portid, cb, cb_data); +} + +/* + * Rule-set consistency check across several netlink dumps + */ +static uint16_t nfts_genid; + +static int genid_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nfgenmsg *nfh = mnl_nlmsg_get_payload(nlh); + + nfts_genid = ntohs(nfh->res_id); + + return MNL_CB_OK; +} + +void mnl_genid_get(struct mnl_socket *nf_sock) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + + nlh = nft_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, AF_UNSPEC, 0, seq); + /* Skip error checking, old kernels sets res_id field to zero. */ + nfts_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, genid_cb, NULL); +} + +static int check_genid(const struct nlmsghdr *nlh) +{ + struct nfgenmsg *nfh = mnl_nlmsg_get_payload(nlh); + + if (nfts_genid != ntohs(nfh->res_id)) { + errno = EINTR; + return -1; + } + return 0; +} + /* * Rule */ @@ -55,9 +111,12 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data) struct nft_rule_list *nlr_list = data; struct nft_rule *r; + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + r = nft_rule_alloc(); if (r == NULL) - return -1; + memory_allocation_error(); if (nft_rule_nlmsg_parse(nlh, r) < 0) goto err_free; @@ -102,9 +161,12 @@ static int chain_cb(const struct nlmsghdr *nlh, void *data) struct nft_chain_list *nlc_list = data; struct nft_chain *c; + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + c = nft_chain_alloc(); if (c == NULL) - return -1; + memory_allocation_error(); if (nft_chain_nlmsg_parse(nlh, c) < 0) goto err_free; @@ -150,9 +212,12 @@ static int table_cb(const struct nlmsghdr *nlh, void *data) struct nft_table_list *nlt_list = data; struct nft_table *t; + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + t = nft_table_alloc(); if (t == NULL) - return -1; + memory_allocation_error(); if (nft_table_nlmsg_parse(nlh, t) < 0) goto err_free; @@ -174,7 +239,7 @@ struct nft_table_list *mnl_table_dump(struct mnl_socket *nf_sock, int family) nlt_list = nft_table_list_alloc(); if (nlt_list == NULL) - return NULL; + memory_allocation_error(); nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, NLM_F_DUMP, seq); @@ -198,9 +263,12 @@ static int set_cb(const struct nlmsghdr *nlh, void *data) struct nft_set_list *nls_list = data; struct nft_set *s; + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + s = nft_set_alloc(); if (s == NULL) - return -1; + memory_allocation_error(); if (nft_set_nlmsg_parse(nlh, s) < 0) goto err_free; @@ -228,7 +296,10 @@ mnl_set_dump(struct mnl_socket *nf_sock, int family, const char *table) nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, NLM_F_DUMP|NLM_F_ACK, seq); - nft_set_attr_set(s, NFT_SET_ATTR_TABLE, table); + + if (table != NULL) + nft_set_attr_set(s, NFT_SET_ATTR_TABLE, table); + nft_set_nlmsg_build_payload(nlh, s); nft_set_free(s); @@ -246,32 +317,15 @@ err: return NULL; } -static void -nft_set_list_merge(struct nft_set_list *dest, struct nft_set_list *orig) -{ - struct nft_set_list_iter *it; - struct nft_set *o; - - it = nft_set_list_iter_create(orig); - if (it == NULL) - return; - - o = nft_set_list_iter_next(it); - while (o != NULL) { - nft_set_list_add_tail(o, dest); - o = nft_set_list_iter_next(it); - } - - nft_set_list_iter_destroy(it); -} - - /* * Set elements */ static int set_elem_cb(const struct nlmsghdr *nlh, void *data) { + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + nft_set_elems_nlmsg_parse(nlh, data); return MNL_CB_OK; } @@ -296,61 +350,57 @@ int mnl_setelem_get(struct mnl_socket *nf_sock, struct nft_set *nls) struct nft_ruleset *mnl_ruleset_dump(struct mnl_socket *nf_sock) { struct nft_ruleset *rs; - struct nft_rule_list *r; - struct nft_chain_list *c; - struct nft_set_list *complete_set_list = NULL, *s; struct nft_table_list *t; - struct nft_table_list_iter *it; - struct nft_table *o; - const char *table; - uint16_t family; - - t = mnl_table_dump(nf_sock, NFPROTO_UNSPEC); - if (t == NULL) - return NULL; + struct nft_chain_list *c; + struct nft_set_list *sl; + struct nft_set_list_iter *i; + struct nft_set *s; + struct nft_rule_list *r; + int ret = 0; rs = nft_ruleset_alloc(); if (rs == NULL) - return NULL; + memory_allocation_error(); + + t = mnl_table_dump(nf_sock, NFPROTO_UNSPEC); + if (t == NULL) + goto err; nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_TABLELIST, t); c = mnl_chain_dump(nf_sock, NFPROTO_UNSPEC); - if (c != NULL) - nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_CHAINLIST, c); - - r = mnl_rule_dump(nf_sock, NFPROTO_UNSPEC); - if (r != NULL) - nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_RULELIST, r); + if (c == NULL) + goto err; - it = nft_table_list_iter_create(t); - if (it == NULL) - return NULL; + nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_CHAINLIST, c); - o = nft_table_list_iter_next(it); - while (o != NULL) { - table = nft_table_attr_get_str(o, NFT_TABLE_ATTR_NAME); - family = nft_table_attr_get_u32(o, NFT_TABLE_ATTR_FAMILY); + sl = mnl_set_dump(nf_sock, NFPROTO_UNSPEC, NULL); + if (sl == NULL) + goto err; - s = mnl_set_dump(nf_sock, family, table); - if (s != NULL) { - if (complete_set_list == NULL) { - complete_set_list = nft_set_list_alloc(); - if (complete_set_list == NULL) - return NULL; - } + i = nft_set_list_iter_create(sl); + s = nft_set_list_iter_next(i); + while (s != NULL) { + ret = mnl_setelem_get(nf_sock, s); + if (ret < 0) + goto err; - nft_set_list_merge(complete_set_list, s); - } - o = nft_table_list_iter_next(it); + s = nft_set_list_iter_next(i); } - nft_table_list_iter_destroy(it); + nft_set_list_iter_destroy(i); + + nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_SETLIST, sl); + + r = mnl_rule_dump(nf_sock, NFPROTO_UNSPEC); + if (r == NULL) + goto err; - if (complete_set_list != NULL) - nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_SETLIST, - complete_set_list); + nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_RULELIST, r); return rs; +err: + nft_ruleset_free(rs); + return NULL; } /* @@ -365,7 +415,9 @@ int nfts_socket_open(struct nft_sync_inst *inst) { struct mnl_socket *s = netlink_socket_open(); if (s == NULL) - return -1; + memory_allocation_error(); + + fcntl(mnl_socket_get_fd(s), F_SETFL, O_NONBLOCK); inst->nl_query_sock = s; return 0; diff --git a/src/utils.c b/src/utils.c index f1886c4..da1e6ae 100644 --- a/src/utils.c +++ b/src/utils.c @@ -8,6 +8,7 @@ */ #include <stdlib.h> +#include <stdio.h> #include "utils.h" @@ -15,3 +16,9 @@ void xfree(const void *ptr) { free((void *)ptr); } + +void __noreturn __memory_allocation_error(const char *filename, uint32_t line) +{ + fprintf(stderr, "%s:%u: Memory allocation failure\n", filename, line); + exit(EXIT_FAILURE); +} -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html