Cancel existing list and restart in case that netlink dump hits EINTR. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- iptables/nft.c | 41 +++++++++++++++++++++++++++++++++++++++-- iptables/nft.h | 1 + 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/iptables/nft.c b/iptables/nft.c index b3d9646d5d7c..d4b1a9f80603 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -761,6 +761,22 @@ err: return ret; } +int nft_restart(struct nft_handle *h) +{ + mnl_socket_close(h->nl); + + h->nl = mnl_socket_open(NETLINK_NETFILTER); + if (h->nl == NULL) + return -1; + + if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) + return -1; + + h->portid = mnl_socket_get_portid(h->nl); + + return 0; +} + int nft_init(struct nft_handle *h, struct builtin_table *t) { h->nl = mnl_socket_open(NETLINK_NETFILTER); @@ -1191,7 +1207,9 @@ static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct nftnl_chain_list *list; + int ret; +retry: list = nftnl_chain_list_alloc(); if (list == NULL) { errno = ENOMEM; @@ -1201,7 +1219,12 @@ static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h) nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, NLM_F_DUMP, h->seq); - mnl_talk(h, nlh, nftnl_chain_list_cb, list); + ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list); + if (ret < 0 && errno == EINTR) { + nft_restart(h); + nftnl_chain_list_free(list); + goto retry; + } return list; } @@ -1299,6 +1322,7 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) if (h->rule_cache) return h->rule_cache; +retry: list = nftnl_rule_list_alloc(); if (list == NULL) return 0; @@ -1308,6 +1332,12 @@ static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list); if (ret < 0) { + if (errno == EINTR) { + nft_restart(h); + nftnl_rule_list_free(list); + goto retry; + } + nftnl_rule_list_free(list); return NULL; } @@ -1658,7 +1688,9 @@ static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; struct nftnl_table_list *list; + int ret; +retry: list = nftnl_table_list_alloc(); if (list == NULL) return 0; @@ -1666,7 +1698,12 @@ static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, NLM_F_DUMP, h->seq); - mnl_talk(h, nlh, nftnl_table_list_cb, list); + ret = mnl_talk(h, nlh, nftnl_table_list_cb, list); + if (ret < 0 && errno == EINTR) { + nft_restart(h); + nftnl_table_list_free(list); + goto retry; + } return list; } diff --git a/iptables/nft.h b/iptables/nft.h index 310cedeca730..e72255811c8f 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -49,6 +49,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, void *data); int nft_init(struct nft_handle *h, struct builtin_table *t); void nft_fini(struct nft_handle *h); +int nft_restart(struct nft_handle *h); /* * Operations with tables. -- 2.11.0 -- 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