summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2018-05-07 15:32:33 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-05-07 17:40:12 +0200
commitdf3d92bec600720b2fb50470212ed7cd1ef00c36 (patch)
tree4c354c4ed764231a01c2bb2da450c59253fc247b /iptables
parentca165845f7ec63522dbfc5ffd50589845f352d7b (diff)
xtables-compat-restore: flush user-defined chains with -n
-n still flushes user-defined chains and its content, the following snippet: iptables-compat -N FOO iptables-compat -I INPUT iptables-compat -I FOO iptables-compat -I FOO iptables-compat-save > A iptables-compat-restore < A iptables-compat -N BAR iptables-compat -A BAR iptables-compat-restore -n < A results in: iptables-compat-save # Generated by xtables-save v1.6.2 on Mon May 7 17:18:44 2018 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :BAR - [0:0] :FOO - [0:0] -A INPUT -A INPUT -A BAR -A FOO -A FOO COMMIT # Completed on Mon May 7 17:18:44 2018 Still, user-defined chains that are not re-defined, such as BAR, are left in place. Reported-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables')
-rw-r--r--iptables/nft-shared.h3
-rw-r--r--iptables/nft.c55
-rw-r--r--iptables/nft.h2
-rw-r--r--iptables/xtables-restore.c16
4 files changed, 74 insertions, 2 deletions
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 56b270e5..34027af9 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -248,6 +248,9 @@ struct nft_xt_restore_cb {
struct nftnl_chain_list *(*chain_list)(struct nft_handle *h);
void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable,
const char *chain);
+ int (*chain_user_flush)(struct nft_handle *h,
+ struct nftnl_chain_list *clist,
+ const char *table, const char *chain);
int (*chain_set)(struct nft_handle *h, const char *table,
const char *chain, const char *policy,
const struct xt_counters *counters);
diff --git a/iptables/nft.c b/iptables/nft.c
index 543e44d7..7f9eb7f0 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -255,6 +255,7 @@ enum obj_update_type {
NFT_COMPAT_CHAIN_ADD,
NFT_COMPAT_CHAIN_USER_ADD,
NFT_COMPAT_CHAIN_USER_DEL,
+ NFT_COMPAT_CHAIN_USER_FLUSH,
NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_CHAIN_RENAME,
NFT_COMPAT_RULE_APPEND,
@@ -1361,6 +1362,55 @@ err:
return ret == 0 ? 1 : 0;
}
+struct chain_user_flush_data {
+ struct nft_handle *handle;
+ const char *table;
+ const char *chain;
+};
+
+static int __nft_chain_user_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 chain_user_flush_data *d = data;
+ struct nft_handle *h = d->handle;
+ const char *table = d->table;
+ const char *chain = d->chain;
+ int ret;
+
+ if (strcmp(table, table_name) != 0)
+ return 0;
+
+ if (strcmp(chain, chain_name) != 0)
+ return 0;
+
+ if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_FLUSH, c);
+ if (ret < 0)
+ return ret;
+
+ nftnl_chain_list_del(c);
+ }
+
+ return 0;
+}
+
+int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
+ const char *table, const char *chain)
+{
+ struct chain_user_flush_data d = {
+ .handle = h,
+ .table = table,
+ .chain = chain,
+ };
+
+ nft_fn = nft_chain_user_flush;
+
+ nftnl_chain_list_foreach(list, __nft_chain_user_flush, &d);
+
+ return 1;
+}
+
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
{
int ret;
@@ -2275,6 +2325,11 @@ static int nft_action(struct nft_handle *h, int action)
NLM_F_NONREC, seq++,
n->chain);
break;
+ case NFT_COMPAT_CHAIN_USER_FLUSH:
+ nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
+ 0, seq++,
+ n->chain);
+ break;
case NFT_COMPAT_CHAIN_UPDATE:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
h->restore ?
diff --git a/iptables/nft.h b/iptables/nft.h
index 2d5c37e5..0c4beb99 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -71,6 +71,8 @@ struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const cha
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table);
+int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
+ const char *chain, const char *table);
int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname);
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 6e7652ff..ac753c43 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -196,6 +196,7 @@ struct nft_xt_restore_cb restore_cb = {
.commit = nft_commit,
.abort = nft_abort,
.table_flush = nft_table_flush,
+ .chain_user_flush = nft_chain_user_flush,
.chain_del = chain_delete,
.do_command = do_commandx,
.chain_set = nft_chain_set,
@@ -294,8 +295,19 @@ void xtables_restore_parse(struct nft_handle *h,
exit(1);
}
- if (cb->chain_del)
- cb->chain_del(chain_list, curtable, chain);
+ if (noflush == 0) {
+ if (cb->chain_del)
+ cb->chain_del(chain_list, curtable,
+ chain);
+ } else {
+ /* Apparently -n still flushes existing user
+ * defined chains that are redefined. Otherwise,
+ * leave them as is.
+ */
+ if (cb->chain_user_flush)
+ cb->chain_user_flush(h, chain_list,
+ curtable, chain);
+ }
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,