diff options
author | Phil Sutter <phil@nwl.cc> | 2019-02-07 22:08:55 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2019-02-08 17:15:06 +0100 |
commit | aff1162b3e4b7ef805425a40306044c7d7dddc67 (patch) | |
tree | 51968e578d73a439ade1ecee760d1c800ca9bfae /iptables/xtables-restore.c | |
parent | b06cc4e0f67f4beba7560fc329d20f108c87b5fb (diff) |
ebtables-nft: Support user-defined chain policies
Legacy ebtables supports policies for user-defined chains - and what's
worse, they default to ACCEPT unlike anywhere else. So lack of support
for this braindead feature in ebtables-nft is actually a change of
behaviour which very likely affects all ebtables users out there.
The solution implemented here uses an implicit (and transparent) last
rule in all user-defined ebtables-nft chains with policy other than
RETURN. This rule is identified by an nft comment
"XTABLES_EB_INTERNAL_POLICY_RULE" (since commit ccf154d7420c0 ("xtables:
Don't use native nftables comments") nft comments are not used
otherwise).
To minimize interference with existing code, this policy rule is removed
from chains during cache population and the policy is saved in
NFTNL_CHAIN_POLICY attribute. When committing changes to the kernel,
nft_commit() traverses through the list of chains and (re-)creates
policy rules if required.
In ebtables-nft-restore, table flushes are problematic. To avoid weird
kernel error responses, introduce a custom 'table_flush' callback which
removes any pending policy rule add/remove jobs prior to creating the
NFT_COMPAT_TABLE_FLUSH one.
I've hidden all this mess behind checks for h->family, so hopefully
impact on {ip,ip6,arp}tables-nft should be negligible.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'iptables/xtables-restore.c')
-rw-r--r-- | iptables/xtables-restore.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index 4e00ed86..6e6daffc 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -226,14 +226,20 @@ void xtables_restore_parse(struct nft_handle *h, curtable->name, chain); } else if (cb->chain_user_add && cb->chain_user_add(h, chain, - curtable->name) < 0) { - if (errno == EEXIST) - continue; - + curtable->name) < 0 && + errno != EEXIST) { xtables_error(PARAMETER_PROBLEM, "cannot create chain " "'%s' (%s)\n", chain, strerror(errno)); + } else if (h->family == NFPROTO_BRIDGE && + !ebt_set_user_chain_policy(h, curtable->name, + chain, policy)) { + xtables_error(OTHER_PROBLEM, + "Can't set policy `%s'" + " on `%s' line %u: %s\n", + policy, chain, line, + ops->strerror(errno)); } ret = 1; } else if (in_table) { @@ -462,11 +468,18 @@ int xtables_ip6_restore_main(int argc, char *argv[]) argc, argv); } +static int ebt_table_flush(struct nft_handle *h, const char *table) +{ + /* drop any pending policy rule add/removal jobs */ + nft_abort_policy_rule(h, table); + return nft_table_flush(h, table); +} + struct nft_xt_restore_cb ebt_restore_cb = { .chain_list = get_chain_list, .commit = nft_commit, .table_new = nft_table_new, - .table_flush = nft_table_flush, + .table_flush = ebt_table_flush, .chain_user_flush = nft_chain_user_flush, .do_command = do_commandeb, .chain_set = nft_chain_set, |