diff options
-rw-r--r-- | include/mnl.h | 69 | ||||
-rw-r--r-- | include/netlink.h | 4 | ||||
-rw-r--r-- | include/nftables.h | 1 | ||||
-rw-r--r-- | include/rule.h | 2 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/mnl.c | 187 | ||||
-rw-r--r-- | src/netlink.c | 54 | ||||
-rw-r--r-- | src/rule.c | 3 |
8 files changed, 177 insertions, 153 deletions
diff --git a/include/mnl.h b/include/mnl.h index 31dff2c2..7df08236 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -9,8 +9,8 @@ struct mnl_socket; struct mnl_socket *netlink_open_sock(void); void netlink_close_sock(struct mnl_socket *nf_sock); -uint32_t mnl_seqnum_alloc(void); -void mnl_genid_get(struct mnl_socket *nf_sock); +uint32_t mnl_seqnum_alloc(uint32_t *seqnum); +void mnl_genid_get(struct mnl_socket *nf_sock, uint32_t seqnum); struct mnl_err { struct list_head head; @@ -23,8 +23,8 @@ void mnl_err_list_free(struct mnl_err *err); struct nftnl_batch *mnl_batch_init(void); bool mnl_batch_ready(struct nftnl_batch *batch); void mnl_batch_reset(struct nftnl_batch *batch); -uint32_t mnl_batch_begin(struct nftnl_batch *batch); -void mnl_batch_end(struct nftnl_batch *batch); +uint32_t mnl_batch_begin(struct nftnl_batch *batch, uint32_t seqnum); +void mnl_batch_end(struct nftnl_batch *batch, uint32_t seqnum); int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list); int mnl_nft_rule_batch_add(struct nftnl_rule *nlr, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); @@ -34,76 +34,79 @@ int mnl_nft_rule_batch_replace(struct nftnl_rule *nlr, struct nftnl_batch *batch unsigned int flags, uint32_t seqnum); int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nftnl_rule *r, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_rule_delete(struct mnl_socket *nf_sock, struct nftnl_rule *r, - unsigned int flags); + unsigned int flags, uint32_t seqnum); struct nftnl_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock, - int family); + int family, uint32_t seqnum); int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_chain_batch_add(struct nftnl_chain *nlc, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_chain_batch_del(struct nftnl_chain *nlc, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); struct nftnl_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock, - int family); + int family, uint32_t seqnum); int mnl_nft_chain_get(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_table_add(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_table_batch_add(struct nftnl_table *nlt, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); int mnl_nft_table_delete(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_table_batch_del(struct nftnl_table *nlt, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); struct nftnl_table_list *mnl_nft_table_dump(struct mnl_socket *nf_sock, - int family); + int family, uint32_t seqnum); int mnl_nft_table_get(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_set_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_set_batch_add(struct nftnl_set *nls, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); int mnl_nft_set_delete(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_set_batch_del(struct nftnl_set *nls, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); struct nftnl_set_list *mnl_nft_set_dump(struct mnl_socket *nf_sock, int family, - const char *table); -int mnl_nft_set_get(struct mnl_socket *nf_sock, struct nftnl_set *nls); + const char *table, uint32_t seqnum); +int mnl_nft_set_get(struct mnl_socket *nf_sock, struct nftnl_set *nls, + uint32_t seqnum); int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_setelem_batch_add(struct nftnl_set *nls, struct nftnl_batch *batch, - unsigned int flags, uint32_t seq); + unsigned int flags, uint32_t seqnum); int mnl_nft_setelem_delete(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags); + unsigned int flags, uint32_t seqnum); int mnl_nft_setelem_batch_del(struct nftnl_set *nls, struct nftnl_batch *batch, unsigned int flags, uint32_t seq); int mnl_nft_setelem_batch_flush(struct nftnl_set *nls, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); -int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls); +int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls, + uint32_t seqnum); struct nftnl_obj_list *mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, - const char *table, const char *name, - uint32_t type, bool dump, bool reset); + uint32_t seqnum, const char *table, + const char *name, uint32_t type, + bool dump, bool reset); int mnl_nft_obj_batch_add(struct nftnl_obj *nln, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); int mnl_nft_obj_batch_del(struct nftnl_obj *nln, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); struct nftnl_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock, - uint32_t family); + uint32_t family, uint32_t seqnum); int mnl_nft_event_listener(struct mnl_socket *nf_sock, int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data); -bool mnl_batch_supported(struct mnl_socket *nf_sock); +bool mnl_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum); #endif /* _NFTABLES_MNL_H_ */ diff --git a/include/netlink.h b/include/netlink.h index 37261714..0e1d26b6 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -195,7 +195,7 @@ extern void netlink_dump_obj(struct nftnl_obj *nlo); extern int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list); -extern void netlink_genid_get(struct mnl_socket *nf_sock); +extern void netlink_genid_get(struct mnl_socket *nf_sock, uint32_t seqnum); extern void netlink_restart(struct mnl_socket *nf_sock); #define netlink_abi_error() \ __netlink_abi_error(__FILE__, __LINE__, strerror(errno)); @@ -224,7 +224,7 @@ struct netlink_mon_handler { extern int netlink_monitor(struct netlink_mon_handler *monhandler, struct mnl_socket *nf_sock); -bool netlink_batch_supported(struct mnl_socket *nf_sock); +bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum); int netlink_echo_callback(const struct nlmsghdr *nlh, void *data); diff --git a/include/nftables.h b/include/nftables.h index a88c86d1..a457aba6 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -40,6 +40,7 @@ struct nft_ctx { struct nft_cache { bool initialized; struct list_head list; + uint32_t seqnum; }; extern unsigned int max_errors; diff --git a/include/rule.h b/include/rule.h index 10ac0e26..f9de8367 100644 --- a/include/rule.h +++ b/include/rule.h @@ -470,6 +470,7 @@ extern void cmd_free(struct cmd *cmd); * @set: current set * @stmt: current statement * @cache: cache context + * @seqnum: netlink sequence number * @ectx: expression context * @pctx: payload context */ @@ -482,6 +483,7 @@ struct eval_ctx { struct set *set; struct stmt *stmt; struct nft_cache *cache; + uint32_t seqnum; struct expr_ctx ectx; struct proto_ctx pctx; }; @@ -191,22 +191,22 @@ static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache, struct parser_state *state, struct list_head *msgs, struct mnl_socket *nf_sock) { + uint32_t batch_seqnum, seqnum = 0; struct nftnl_batch *batch; struct netlink_ctx ctx; struct cmd *cmd; struct mnl_err *err, *tmp; LIST_HEAD(err_list); - uint32_t batch_seqnum; - bool batch_supported = netlink_batch_supported(nf_sock); + bool batch_supported = netlink_batch_supported(nf_sock, &seqnum); int ret = 0; batch = mnl_batch_init(); - batch_seqnum = mnl_batch_begin(batch); + batch_seqnum = mnl_batch_begin(batch, mnl_seqnum_alloc(&seqnum)); list_for_each_entry(cmd, &state->cmds, list) { memset(&ctx, 0, sizeof(ctx)); ctx.msgs = msgs; - ctx.seqnum = cmd->seqnum = mnl_seqnum_alloc(); + ctx.seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum); ctx.batch = batch; ctx.batch_supported = batch_supported; ctx.octx = &nft->output; @@ -218,7 +218,7 @@ static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache, goto out; } if (!nft->check) - mnl_batch_end(batch); + mnl_batch_end(batch, mnl_seqnum_alloc(&seqnum)); if (!mnl_batch_ready(batch)) goto out; @@ -30,11 +30,9 @@ #include <utils.h> #include <nftables.h> -static int seq; - -uint32_t mnl_seqnum_alloc(void) +uint32_t mnl_seqnum_alloc(unsigned int *seqnum) { - return seq++; + return *seqnum++; } /* The largest nf_tables netlink message is the set element message, which @@ -68,7 +66,8 @@ out: } static int -nft_mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len, +nft_mnl_talk(struct mnl_socket *nf_sock, const void *data, + unsigned int len, uint32_t seqnum, int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data) { uint32_t portid = mnl_socket_get_portid(nf_sock); @@ -81,7 +80,7 @@ nft_mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len, if (mnl_socket_sendto(nf_sock, data, len) < 0) return -1; - return nft_mnl_recv(nf_sock, seq, portid, cb, cb_data); + return nft_mnl_recv(nf_sock, seqnum, portid, cb, cb_data); } /* @@ -98,14 +97,14 @@ static int genid_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_OK; } -void mnl_genid_get(struct mnl_socket *nf_sock) +void mnl_genid_get(struct mnl_socket *nf_sock, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; - nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, AF_UNSPEC, 0, seq); + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, AF_UNSPEC, 0, seqnum); /* Skip error checking, old kernels sets res_id field to zero. */ - nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, genid_cb, NULL); + nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, genid_cb, NULL); } static int check_genid(const struct nlmsghdr *nlh) @@ -146,19 +145,17 @@ static void mnl_nft_batch_continue(struct nftnl_batch *batch) memory_allocation_error(); } -uint32_t mnl_batch_begin(struct nftnl_batch *batch) +uint32_t mnl_batch_begin(struct nftnl_batch *batch, uint32_t seqnum) { - uint32_t seq = mnl_seqnum_alloc(); - - nftnl_batch_begin(nftnl_batch_buffer(batch), seq); + nftnl_batch_begin(nftnl_batch_buffer(batch), seqnum); mnl_nft_batch_continue(batch); - return seq; + return seqnum; } -void mnl_batch_end(struct nftnl_batch *batch) +void mnl_batch_end(struct nftnl_batch *batch, uint32_t seqnum) { - nftnl_batch_end(nftnl_batch_buffer(batch), mnl_seqnum_alloc()); + nftnl_batch_end(nftnl_batch_buffer(batch), seqnum); mnl_nft_batch_continue(batch); } @@ -340,31 +337,31 @@ int mnl_nft_rule_batch_del(struct nftnl_rule *nlr, struct nftnl_batch *batch, * Rule */ int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nftnl_rule *nlr, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY), - NLM_F_ACK | NLM_F_CREATE | flags, seq); + NLM_F_ACK | NLM_F_CREATE | flags, seqnum); nftnl_rule_nlmsg_build_payload(nlh, nlr); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_rule_delete(struct mnl_socket *nf_sock, struct nftnl_rule *nlr, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_rule_nlmsg_build_payload(nlh, nlr); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } static int rule_cb(const struct nlmsghdr *nlh, void *data) @@ -390,7 +387,8 @@ err_free: return MNL_CB_OK; } -struct nftnl_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock, int family) +struct nftnl_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock, + int family, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -402,9 +400,10 @@ struct nftnl_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock, int family memory_allocation_error(); nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, - NLM_F_DUMP, seq); + NLM_F_DUMP, seqnum); - ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, rule_cb, nlr_list); + ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, rule_cb, + nlr_list); if (ret < 0) goto err; @@ -418,7 +417,7 @@ err: * Chain */ int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -426,10 +425,10 @@ int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY), - NLM_F_CREATE | NLM_F_ACK | flags, seq); + NLM_F_CREATE | NLM_F_ACK | flags, seqnum); nftnl_chain_nlmsg_build_payload(nlh, nlc); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_chain_batch_add(struct nftnl_chain *nlc, struct nftnl_batch *batch, @@ -448,17 +447,17 @@ int mnl_nft_chain_batch_add(struct nftnl_chain *nlc, struct nftnl_batch *batch, } int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_chain_nlmsg_build_payload(nlh, nlc); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_chain_batch_del(struct nftnl_chain *nlc, struct nftnl_batch *batch, @@ -499,7 +498,8 @@ err_free: return MNL_CB_OK; } -struct nftnl_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock, int family) +struct nftnl_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock, + int family, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -511,9 +511,10 @@ struct nftnl_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock, int fami memory_allocation_error(); nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, - NLM_F_DUMP, seq); + NLM_F_DUMP, seqnum); - ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_cb, nlc_list); + ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, chain_cb, + nlc_list); if (ret < 0) goto err; @@ -530,34 +531,35 @@ static int chain_get_cb(const struct nlmsghdr *nlh, void *data) } int mnl_nft_chain_get(struct mnl_socket *nf_sock, struct nftnl_chain *nlc, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY), - NLM_F_ACK | flags, seq); + seqnum, NLM_F_ACK | flags); nftnl_chain_nlmsg_build_payload(nlh, nlc); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_get_cb, nlc); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, chain_get_cb, + nlc); } /* * Table */ int mnl_nft_table_add(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY), - NLM_F_ACK | flags, seq); + NLM_F_ACK | flags, seqnum); nftnl_table_nlmsg_build_payload(nlh, nlt); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_table_batch_add(struct nftnl_table *nlt, struct nftnl_batch *batch, @@ -576,17 +578,17 @@ int mnl_nft_table_batch_add(struct nftnl_table *nlt, struct nftnl_batch *batch, } int mnl_nft_table_delete(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_DELTABLE, nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_table_nlmsg_build_payload(nlh, nlt); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_table_batch_del(struct nftnl_table *nlt, struct nftnl_batch *batch, @@ -627,7 +629,8 @@ err_free: return MNL_CB_OK; } -struct nftnl_table_list *mnl_nft_table_dump(struct mnl_socket *nf_sock, int family) +struct nftnl_table_list *mnl_nft_table_dump(struct mnl_socket *nf_sock, + int family, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -639,9 +642,10 @@ struct nftnl_table_list *mnl_nft_table_dump(struct mnl_socket *nf_sock, int fami memory_allocation_error(); nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, - NLM_F_DUMP, seq); + NLM_F_DUMP, seqnum); - ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, table_cb, nlt_list); + ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, table_cb, + nlt_list); if (ret < 0) goto err; @@ -660,17 +664,18 @@ static int table_get_cb(const struct nlmsghdr *nlh, void *data) } int mnl_nft_table_get(struct mnl_socket *nf_sock, struct nftnl_table *nlt, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_table_nlmsg_build_payload(nlh, nlt); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, table_get_cb, nlt); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, table_get_cb, + nlt); } /* @@ -683,31 +688,32 @@ static int set_add_cb(const struct nlmsghdr *nlh, void *data) } int mnl_nft_set_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWSET, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), - NLM_F_CREATE | NLM_F_ACK | flags, seq); + NLM_F_CREATE | NLM_F_ACK | flags, seqnum); nftnl_set_nlmsg_build_payload(nlh, nls); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_add_cb, nls); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, + set_add_cb, nls); } int mnl_nft_set_delete(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_DELSET, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), - flags | NLM_F_ACK, seq); + flags | NLM_F_ACK, seqnum); nftnl_set_nlmsg_build_payload(nlh, nls); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } int mnl_nft_set_batch_add(struct nftnl_set *nls, struct nftnl_batch *batch, @@ -764,7 +770,8 @@ err_free: } struct nftnl_set_list * -mnl_nft_set_dump(struct mnl_socket *nf_sock, int family, const char *table) +mnl_nft_set_dump(struct mnl_socket *nf_sock, int family, const char *table, + uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -777,7 +784,7 @@ mnl_nft_set_dump(struct mnl_socket *nf_sock, int family, const char *table) memory_allocation_error(); nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family, - NLM_F_DUMP | NLM_F_ACK, seq); + NLM_F_DUMP | NLM_F_ACK, seqnum); if (table != NULL) nftnl_set_set(s, NFTNL_SET_TABLE, table); nftnl_set_nlmsg_build_payload(nlh, s); @@ -787,7 +794,8 @@ mnl_nft_set_dump(struct mnl_socket *nf_sock, int family, const char *table) if (nls_list == NULL) memory_allocation_error(); - ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_cb, nls_list); + ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, set_cb, + nls_list); if (ret < 0) goto err; @@ -852,8 +860,9 @@ err_free: struct nftnl_obj_list * -mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table, - const char *name, uint32_t type, bool dump, bool reset) +mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, uint32_t seqnum, + const char *table, const char *name, uint32_t type, bool dump, + bool reset) { uint16_t nl_flags = dump ? NLM_F_DUMP : 0; struct nftnl_obj_list *nln_list; @@ -872,7 +881,7 @@ mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table, memory_allocation_error(); nlh = nftnl_nlmsg_build_hdr(buf, msg_type, family, - nl_flags | NLM_F_ACK, seq); + nl_flags | NLM_F_ACK, seqnum); if (table != NULL) nftnl_obj_set_str(n, NFTNL_OBJ_TABLE, table); if (name != NULL) @@ -886,7 +895,8 @@ mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table, if (nln_list == NULL) memory_allocation_error(); - ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, obj_cb, nln_list); + ret = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, obj_cb, + nln_list); if (ret < 0) goto err; @@ -904,24 +914,26 @@ static int set_get_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_OK; } -int mnl_nft_set_get(struct mnl_socket *nf_sock, struct nftnl_set *nls) +int mnl_nft_set_get(struct mnl_socket *nf_sock, struct nftnl_set *nls, + uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_set_nlmsg_build_payload(nlh, nls); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_get_cb, nls); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, set_get_cb, + nls); } /* * Set elements */ int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[NFT_NLMSG_MAXSIZE]; struct nlmsghdr *nlh; @@ -936,9 +948,10 @@ int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_NEWSETELEM, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), NLM_F_CREATE | NLM_F_ACK | flags, - seq); + seqnum); ret = nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter); - err = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + err = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, + NULL, NULL); if (ret <= 0 || err < 0) break; } @@ -949,17 +962,17 @@ int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nftnl_set *nls, } int mnl_nft_setelem_delete(struct mnl_socket *nf_sock, struct nftnl_set *nls, - unsigned int flags) + unsigned int flags, uint32_t seqnum) { char buf[NFT_NLMSG_MAXSIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_DELSETELEM, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), - NLM_F_ACK, seq); + NLM_F_ACK, seqnum); nftnl_set_elems_nlmsg_build_payload(nlh, nls); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, NULL, NULL); } static int set_elem_cb(const struct nlmsghdr *nlh, void *data) @@ -1028,24 +1041,26 @@ int mnl_nft_setelem_batch_del(struct nftnl_set *nls, struct nftnl_batch *batch, seqnum); } -int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls) +int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls, + uint32_t seqnum) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY), - NLM_F_DUMP|NLM_F_ACK, seq); + NLM_F_DUMP|NLM_F_ACK, seqnum); nftnl_set_nlmsg_build_payload(nlh, nls); - return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_elem_cb, nls); + return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, seqnum, set_elem_cb, + nls); } /* * ruleset */ struct nftnl_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock, - uint32_t family) + uint32_t family, uint32_t seqnum) { struct nftnl_ruleset *rs; struct nftnl_table_list *t; @@ -1060,26 +1075,26 @@ struct nftnl_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock, if (rs == NULL) memory_allocation_error(); - t = mnl_nft_table_dump(nf_sock, family); + t = mnl_nft_table_dump(nf_sock, family, seqnum); if (t == NULL) goto err; nftnl_ruleset_set(rs, NFTNL_RULESET_TABLELIST, t); - c = mnl_nft_chain_dump(nf_sock, family); + c = mnl_nft_chain_dump(nf_sock, family, seqnum); if (c == NULL) goto err; nftnl_ruleset_set(rs, NFTNL_RULESET_CHAINLIST, c); - sl = mnl_nft_set_dump(nf_sock, family, NULL); + sl = mnl_nft_set_dump(nf_sock, family, NULL, seqnum); if (sl == NULL) goto err; i = nftnl_set_list_iter_create(sl); s = nftnl_set_list_iter_next(i); while (s != NULL) { - ret = mnl_nft_setelem_get(nf_sock, s); + ret = mnl_nft_setelem_get(nf_sock, s, seqnum); if (ret < 0) goto err; @@ -1089,7 +1104,7 @@ struct nftnl_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock, nftnl_ruleset_set(rs, NFTNL_RULESET_SETLIST, sl); - r = mnl_nft_rule_dump(nf_sock, family); + r = mnl_nft_rule_dump(nf_sock, family, seqnum); if (r == NULL) goto err; @@ -1164,7 +1179,7 @@ int mnl_nft_event_listener(struct mnl_socket *nf_sock, return ret; } -static void nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq) +static void nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seqnum) { struct nlmsghdr *nlh; struct nfgenmsg *nfg; @@ -1172,7 +1187,7 @@ static void nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq) nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST; - nlh->nlmsg_seq = seq; + nlh->nlmsg_seq = seqnum; nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); nfg->nfgen_family = AF_INET; @@ -1180,7 +1195,7 @@ static void nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq) nfg->res_id = NFNL_SUBSYS_NFTABLES; } -bool mnl_batch_supported(struct mnl_socket *nf_sock) +bool mnl_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum) { struct mnl_nlmsg_batch *b; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -1189,15 +1204,15 @@ bool mnl_batch_supported(struct mnl_socket *nf_sock) b = mnl_nlmsg_batch_start(buf, sizeof(buf)); nft_mnl_batch_put(mnl_nlmsg_batch_current(b), NFNL_MSG_BATCH_BEGIN, - seq++); + mnl_seqnum_alloc(seqnum)); mnl_nlmsg_batch_next(b); nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), NFT_MSG_NEWSET, - AF_INET, NLM_F_ACK, seq++); + AF_INET, NLM_F_ACK, mnl_seqnum_alloc(seqnum)); mnl_nlmsg_batch_next(b); nft_mnl_batch_put(mnl_nlmsg_batch_current(b), NFNL_MSG_BATCH_END, - seq++); + mnl_seqnum_alloc(seqnum)); mnl_nlmsg_batch_next(b); ret = mnl_socket_sendto(nf_sock, mnl_nlmsg_batch_head(b), diff --git a/src/netlink.c b/src/netlink.c index 68f33625..7311149f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -79,9 +79,9 @@ void netlink_restart(struct mnl_socket *nf_sock) nf_sock = netlink_open_sock(); } -void netlink_genid_get(struct mnl_socket *nf_sock) +void netlink_genid_get(struct mnl_socket *nf_sock, uint32_t seqnum) { - mnl_genid_get(nf_sock); + mnl_genid_get(nf_sock, seqnum); } void __noreturn __netlink_abi_error(const char *file, int line, @@ -570,7 +570,7 @@ static int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h, { struct nftnl_rule_list *rule_cache; - rule_cache = mnl_nft_rule_dump(ctx->nf_sock, h->family); + rule_cache = mnl_nft_rule_dump(ctx->nf_sock, h->family, ctx->seqnum); if (rule_cache == NULL) { if (errno == EINTR) return -1; @@ -627,7 +627,7 @@ static int netlink_add_chain_compat(struct netlink_ctx *ctx, } netlink_dump_chain(nlc); - err = mnl_nft_chain_add(ctx->nf_sock, nlc, flags); + err = mnl_nft_chain_add(ctx->nf_sock, nlc, flags, ctx->seqnum); nftnl_chain_free(nlc); if (err < 0) @@ -693,7 +693,7 @@ static int netlink_rename_chain_compat(struct netlink_ctx *ctx, nlc = alloc_nftnl_chain(h); nftnl_chain_set_str(nlc, NFTNL_CHAIN_NAME, name); netlink_dump_chain(nlc); - err = mnl_nft_chain_add(ctx->nf_sock, nlc, 0); + err = mnl_nft_chain_add(ctx->nf_sock, nlc, 0, ctx->seqnum); nftnl_chain_free(nlc); if (err < 0) @@ -740,7 +740,7 @@ static int netlink_del_chain_compat(struct netlink_ctx *ctx, nlc = alloc_nftnl_chain(h); netlink_dump_chain(nlc); - err = mnl_nft_chain_delete(ctx->nf_sock, nlc, 0); + err = mnl_nft_chain_delete(ctx->nf_sock, nlc, 0, ctx->seqnum); nftnl_chain_free(nlc); if (err < 0) @@ -843,7 +843,7 @@ int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h, struct nftnl_chain_list *chain_cache; struct chain *chain; - chain_cache = mnl_nft_chain_dump(ctx->nf_sock, h->family); + chain_cache = mnl_nft_chain_dump(ctx->nf_sock, h->family, ctx->seqnum); if (chain_cache == NULL) { if (errno == EINTR) return -1; @@ -879,7 +879,7 @@ int netlink_get_chain(struct netlink_ctx *ctx, const struct handle *h, int err; nlc = alloc_nftnl_chain(h); - err = mnl_nft_chain_get(ctx->nf_sock, nlc, 0); + err = mnl_nft_chain_get(ctx->nf_sock, nlc, 0, ctx->seqnum); if (err < 0) { netlink_io_error(ctx, loc, "Could not receive chain from kernel: %s", @@ -915,7 +915,7 @@ static int netlink_add_table_compat(struct netlink_ctx *ctx, int err; nlt = alloc_nftnl_table(h); - err = mnl_nft_table_add(ctx->nf_sock, nlt, flags); + err = mnl_nft_table_add(ctx->nf_sock, nlt, flags, ctx->seqnum); nftnl_table_free(nlt); if (err < 0) @@ -965,7 +965,7 @@ static int netlink_del_table_compat(struct netlink_ctx *ctx, int err; nlt = alloc_nftnl_table(h); - err = mnl_nft_table_delete(ctx->nf_sock, nlt, 0); + err = mnl_nft_table_delete(ctx->nf_sock, nlt, 0, ctx->seqnum); nftnl_table_free(nlt); if (err < 0) @@ -1042,7 +1042,7 @@ int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h, { struct nftnl_table_list *table_cache; - table_cache = mnl_nft_table_dump(ctx->nf_sock, h->family); + table_cache = mnl_nft_table_dump(ctx->nf_sock, h->family, ctx->seqnum); if (table_cache == NULL) { if (errno == EINTR) return -1; @@ -1063,7 +1063,7 @@ int netlink_get_table(struct netlink_ctx *ctx, const struct handle *h, int err; nlt = alloc_nftnl_table(h); - err = mnl_nft_table_get(ctx->nf_sock, nlt, 0); + err = mnl_nft_table_get(ctx->nf_sock, nlt, 0, ctx->seqnum); if (err < 0) { netlink_io_error(ctx, loc, "Could not receive table from kernel: %s", @@ -1254,7 +1254,8 @@ static int netlink_add_set_compat(struct netlink_ctx *ctx, } netlink_dump_set(nls); - err = mnl_nft_set_add(ctx->nf_sock, nls, NLM_F_ECHO | flags); + err = mnl_nft_set_add(ctx->nf_sock, nls, NLM_F_ECHO | flags, + ctx->seqnum); if (err < 0) netlink_io_error(ctx, &set->location, "Could not add set: %s", strerror(errno)); @@ -1350,7 +1351,7 @@ static int netlink_del_set_compat(struct netlink_ctx *ctx, int err; nls = alloc_nftnl_set(h); - err = mnl_nft_set_delete(ctx->nf_sock, nls, 0); + err = mnl_nft_set_delete(ctx->nf_sock, nls, 0, ctx->seqnum); nftnl_set_free(nls); if (err < 0) @@ -1403,7 +1404,8 @@ int netlink_list_sets(struct netlink_ctx *ctx, const struct handle *h, struct nftnl_set_list *set_cache; int err; - set_cache = mnl_nft_set_dump(ctx->nf_sock, h->family, h->table); + set_cache = mnl_nft_set_dump(ctx->nf_sock, h->family, h->table, + ctx->seqnum); if (set_cache == NULL) { if (errno == EINTR) return -1; @@ -1424,7 +1426,7 @@ int netlink_get_set(struct netlink_ctx *ctx, const struct handle *h, int err; nls = alloc_nftnl_set(h); - err = mnl_nft_set_get(ctx->nf_sock, nls); + err = mnl_nft_set_get(ctx->nf_sock, nls, ctx->seqnum); if (err < 0) { nftnl_set_free(nls); return netlink_io_error(ctx, loc, @@ -1483,7 +1485,7 @@ static int netlink_add_setelems_compat(struct netlink_ctx *ctx, alloc_setelem_cache(expr, nls); netlink_dump_set(nls); - err = mnl_nft_setelem_add(ctx->nf_sock, nls, flags); + err = mnl_nft_setelem_add(ctx->nf_sock, nls, flags, ctx->seqnum); nftnl_set_free(nls); if (err < 0) netlink_io_error(ctx, &expr->location, @@ -1533,7 +1535,7 @@ static int netlink_del_setelems_compat(struct netlink_ctx *ctx, alloc_setelem_cache(expr, nls); netlink_dump_set(nls); - err = mnl_nft_setelem_delete(ctx->nf_sock, nls, 0); + err = mnl_nft_setelem_delete(ctx->nf_sock, nls, 0, ctx->seqnum); nftnl_set_free(nls); if (err < 0) netlink_io_error(ctx, &expr->location, @@ -1733,7 +1735,7 @@ int netlink_get_setelems(struct netlink_ctx *ctx, const struct handle *h, nls = alloc_nftnl_set(h); - err = mnl_nft_setelem_get(ctx->nf_sock, nls); + err = mnl_nft_setelem_get(ctx->nf_sock, nls, ctx->seqnum); if (err < 0) { nftnl_set_free(nls); if (errno == EINTR) @@ -1869,8 +1871,8 @@ int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h, struct nftnl_obj_list *obj_cache; int err; - obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, h->table, NULL, - 0, true, false); + obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, ctx->seqnum, + h->table, NULL, 0, true, false); if (obj_cache == NULL) { if (errno == EINTR) return -1; @@ -1889,8 +1891,8 @@ int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h, struct nftnl_obj_list *obj_cache; int err; - obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, h->table, h->obj, - type, dump, true); + obj_cache = mnl_nft_obj_dump(ctx->nf_sock, h->family, ctx->seqnum, + h->table, h->obj, type, dump, true); if (obj_cache == NULL) { if (errno == EINTR) return -1; @@ -1935,7 +1937,7 @@ struct nftnl_ruleset *netlink_dump_ruleset(struct netlink_ctx *ctx, { struct nftnl_ruleset *rs; - rs = mnl_nft_ruleset_dump(ctx->nf_sock, h->family); + rs = mnl_nft_ruleset_dump(ctx->nf_sock, h->family, ctx->seqnum); if (rs == NULL) { if (errno == EINTR) return NULL; @@ -3127,7 +3129,7 @@ int netlink_monitor(struct netlink_mon_handler *monhandler, return mnl_nft_event_listener(nf_sock, netlink_events_cb, monhandler); } -bool netlink_batch_supported(struct mnl_socket *nf_sock) +bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum) { - return mnl_batch_supported(nf_sock); + return mnl_batch_supported(nf_sock, seqnum); } @@ -135,6 +135,7 @@ static int cache_init(struct mnl_socket *nf_sock, struct nft_cache *cache, ctx.nf_sock = nf_sock; ctx.cache = cache; ctx.msgs = msgs; + ctx.seqnum = cache->seqnum++; ret = cache_init_tables(&ctx, &handle, cache); if (ret < 0) @@ -154,7 +155,7 @@ int cache_update(struct mnl_socket *nf_sock, struct nft_cache *cache, if (cache->initialized) return 0; replay: - netlink_genid_get(nf_sock); + netlink_genid_get(nf_sock, cache->seqnum++); ret = cache_init(nf_sock, cache, cmd, msgs); if (ret < 0) { cache_release(cache); |