From 6a9ffb114ac67cf3c23ab5969153f9213492a07f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 8 May 2018 11:45:59 +0200 Subject: xtables-compat-restore: flush table and its content with no -n With no -n, semantics for *filter are to delete filter table and all its content. This restores the similar behaviour introduced in ca165845f7ec ("xtables-compat-restore: flush rules and delete user-defined chains"). Signed-off-by: Pablo Neira Ayuso --- iptables/nft.c | 122 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 66 insertions(+), 56 deletions(-) (limited to 'iptables') diff --git a/iptables/nft.c b/iptables/nft.c index 37c017f9..5f7e3ab2 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -252,6 +252,7 @@ static void mnl_nftnl_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq) enum obj_update_type { NFT_COMPAT_TABLE_ADD, + NFT_COMPAT_TABLE_FLUSH, NFT_COMPAT_CHAIN_ADD, NFT_COMPAT_CHAIN_USER_ADD, NFT_COMPAT_CHAIN_USER_DEL, @@ -1306,62 +1307,6 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain) nftnl_rule_free(r); } -struct flush_data { - struct nft_handle *handle; - const char *table; -}; - -static int __nft_table_flush(struct nftnl_chain *c, void *data) -{ - const char *table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); - const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); - struct flush_data *d = data; - struct nft_handle *h = d->handle; - const char *table = d->table; - int ret; - - if (strcmp(table, table_name) != 0) - return 0; - - __nft_rule_flush(h, table_name, chain_name); - - if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) { - ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); - if (ret < 0) - return ret; - - nftnl_chain_list_del(c); - } - - return 0; -} - -int nft_table_flush(struct nft_handle *h, const char *table) -{ - struct flush_data d = { - .handle = h, - .table = table, - }; - struct nftnl_chain_list *list; - int ret = 0; - - nft_fn = nft_table_flush; - - list = nftnl_chain_list_get(h); - if (list == NULL) { - ret = 0; - goto err; - } - - nftnl_chain_list_foreach(list, __nft_table_flush, &d); - flush_rule_cache(h); -err: - nftnl_chain_list_free(list); - - /* the core expects 1 for success and 0 for error */ - return ret == 0 ? 1 : 0; -} - struct chain_user_flush_data { struct nft_handle *handle; const char *table; @@ -1740,6 +1685,66 @@ int nft_for_each_table(struct nft_handle *h, return 0; } +static int __nft_table_flush(struct nft_handle *h, const char *table) +{ + struct nftnl_table *t; + + t = nftnl_table_alloc(); + if (t == NULL) + return -1; + + nftnl_table_set_str(t, NFTNL_TABLE_NAME, table); + + batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t); + + return 0; +} + +int nft_table_flush(struct nft_handle *h, const char *table) +{ + struct nftnl_table_list_iter *iter; + struct nftnl_table_list *list; + struct nftnl_table *t; + int ret = 0; + + nft_fn = nft_table_flush; + + list = nftnl_table_list_get(h); + if (list == NULL) { + ret = -1; + goto err_out; + } + + iter = nftnl_table_list_iter_create(list); + if (iter == NULL) { + ret = -1; + goto err_table_list; + } + + t = nftnl_table_list_iter_next(iter); + while (t != NULL) { + const char *table_name = + nftnl_table_get_str(t, NFTNL_TABLE_NAME); + + if (strcmp(table_name, table) != 0) + goto next; + + ret = __nft_table_flush(h, table); + if (ret < 0) + goto err_table_iter; +next: + t = nftnl_table_list_iter_next(iter); + } + +err_table_iter: + nftnl_table_list_iter_destroy(iter); +err_table_list: + nftnl_table_list_free(list); +err_out: + /* the core expects 1 for success and 0 for error */ + return ret == 0 ? 1 : 0; +} + static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list, struct nftnl_rule *r) { @@ -2310,6 +2315,11 @@ static int nft_action(struct nft_handle *h, int action) NLM_F_CREATE, seq++, n->table); break; + case NFT_COMPAT_TABLE_FLUSH: + nft_compat_table_batch_add(h, NFT_MSG_DELTABLE, + 0, + seq++, n->table); + break; case NFT_COMPAT_CHAIN_ADD: nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, NLM_F_CREATE, seq++, -- cgit v1.2.3