diff options
author | Patrick McHardy <kaber@trash.net> | 2015-04-05 14:41:07 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-04-08 16:58:27 +0200 |
commit | 11113e190bf0ad73086884f87efccc994ff28b3d (patch) | |
tree | 295a3f9b12f40b61b2a1f3305fabab5f85a42ba8 /net | |
parent | 3dd0673ac3cd7d05cde103396ec7ec410a901de2 (diff) | |
download | linux-11113e190bf0ad73086884f87efccc994ff28b3d.tar.bz2 |
netfilter: nf_tables: support different set binding types
Currently a set binding is assumed to be related to a lookup and, in
case of maps, a data load.
In order to use bindings for set updates, the loop detection checks
must be restricted to map operations only. Add a flags member to the
binding struct to hold the set "action" flags such as NFT_SET_MAP,
and perform loop detection based on these.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_tables_api.c | 11 | ||||
-rw-r--r-- | net/netfilter/nft_lookup.c | 2 |
2 files changed, 10 insertions, 3 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 27d1bf55a581..90b898491da7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2811,12 +2811,13 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, if (!list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS) return -EBUSY; - if (set->flags & NFT_SET_MAP) { + if (binding->flags & NFT_SET_MAP) { /* If the set is already bound to the same chain all * jumps are already validated for that chain. */ list_for_each_entry(i, &set->bindings, list) { - if (i->chain == binding->chain) + if (binding->flags & NFT_SET_MAP && + i->chain == binding->chain) goto bind; } @@ -3312,6 +3313,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, .chain = (struct nft_chain *)binding->chain, }; + if (!(binding->flags & NFT_SET_MAP)) + continue; + err = nft_validate_data_load(&bind_ctx, dreg, &data, d2.type); if (err < 0) @@ -4063,7 +4067,8 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, continue; list_for_each_entry(binding, &set->bindings, list) { - if (binding->chain != chain) + if (!(binding->flags & NFT_SET_MAP) || + binding->chain != chain) continue; iter.skip = 0; diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index a5f30b8760ea..d8cf86fb30fc 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -92,6 +92,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx, } else if (set->flags & NFT_SET_MAP) return -EINVAL; + priv->binding.flags = set->flags & NFT_SET_MAP; + err = nf_tables_bind_set(ctx, set, &priv->binding); if (err < 0) return err; |