diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-24 13:41:54 +0300 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-26 18:30:20 +0300 |
commit | c016c7e45ddfa5085b35b644e659ec014969740d (patch) | |
tree | 5311ad15af134ee0839f59612f67796e3094b3a8 /net/netfilter/nft_set_hash.c | |
parent | 5ca8cc5bf11faed257c762018aea9106d529232f (diff) | |
download | linux-c016c7e45ddfa5085b35b644e659ec014969740d.tar.xz |
netfilter: nf_tables: honor NLM_F_EXCL flag in set element insertion
If the NLM_F_EXCL flag is set, then new elements that clash with an
existing one return EEXIST. In case you try to add an element whose
data area differs from what we have, then this returns EBUSY. If no
flag is specified at all, then this returns success to userspace.
This patch also update the set insert operation so we can fetch the
existing element that clashes with the one you want to add, we need
this to make sure the element data doesn't differ.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nft_set_hash.c')
-rw-r--r-- | net/netfilter/nft_set_hash.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 564fa7929ed5..3794cb2fc788 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -126,7 +126,8 @@ err1: } static int nft_hash_insert(const struct net *net, const struct nft_set *set, - const struct nft_set_elem *elem) + const struct nft_set_elem *elem, + struct nft_set_ext **ext) { struct nft_hash *priv = nft_set_priv(set); struct nft_hash_elem *he = elem->priv; @@ -135,9 +136,17 @@ static int nft_hash_insert(const struct net *net, const struct nft_set *set, .set = set, .key = elem->key.val.data, }; - - return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, - nft_hash_params); + struct nft_hash_elem *prev; + + prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node, + nft_hash_params); + if (IS_ERR(prev)) + return PTR_ERR(prev); + if (prev) { + *ext = &prev->ext; + return -EEXIST; + } + return 0; } static void nft_hash_activate(const struct net *net, const struct nft_set *set, |