aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorArturo Borrero <arturo.borrero.glez@gmail.com>2016-06-23 06:24:08 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-06-24 05:03:29 -0400
commit0071e184a535e40ce487528cb04f4690cb0da881 (patch)
tree6267df19373697d545ba080be1f3ababaf9e6d5b /net/netfilter
parent82bec71d46b83f39860e2838ff8394e4fcd6efab (diff)
netfilter: nf_tables: add support for inverted logic in nft_lookup
Introduce a new configuration option for this expression, which allows users to invert the logic of set lookups. In _init() we will now return EINVAL if NFT_LOOKUP_F_INV is in anyway related to a map lookup. The code in the _eval() function has been untangled and updated to sopport the XOR of options, as we should consider 4 cases: * lookup false, invert false -> NFT_BREAK * lookup false, invert true -> return w/o NFT_BREAK * lookup true, invert false -> return w/o NFT_BREAK * lookup true, invert true -> NFT_BREAK Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nft_lookup.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index 8a102cf855d0..b8d18f598569 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -22,6 +22,7 @@ struct nft_lookup {
22 struct nft_set *set; 22 struct nft_set *set;
23 enum nft_registers sreg:8; 23 enum nft_registers sreg:8;
24 enum nft_registers dreg:8; 24 enum nft_registers dreg:8;
25 bool invert;
25 struct nft_set_binding binding; 26 struct nft_set_binding binding;
26}; 27};
27 28
@@ -32,14 +33,20 @@ static void nft_lookup_eval(const struct nft_expr *expr,
32 const struct nft_lookup *priv = nft_expr_priv(expr); 33 const struct nft_lookup *priv = nft_expr_priv(expr);
33 const struct nft_set *set = priv->set; 34 const struct nft_set *set = priv->set;
34 const struct nft_set_ext *ext; 35 const struct nft_set_ext *ext;
36 bool found;
35 37
36 if (set->ops->lookup(set, &regs->data[priv->sreg], &ext)) { 38 found = set->ops->lookup(set, &regs->data[priv->sreg], &ext) ^
37 if (set->flags & NFT_SET_MAP) 39 priv->invert;
38 nft_data_copy(&regs->data[priv->dreg], 40
39 nft_set_ext_data(ext), set->dlen); 41 if (!found) {
42 regs->verdict.code = NFT_BREAK;
40 return; 43 return;
41 } 44 }
42 regs->verdict.code = NFT_BREAK; 45
46 if (found && set->flags & NFT_SET_MAP)
47 nft_data_copy(&regs->data[priv->dreg],
48 nft_set_ext_data(ext), set->dlen);
49
43} 50}
44 51
45static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { 52static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
@@ -47,6 +54,7 @@ static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
47 [NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 }, 54 [NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 },
48 [NFTA_LOOKUP_SREG] = { .type = NLA_U32 }, 55 [NFTA_LOOKUP_SREG] = { .type = NLA_U32 },
49 [NFTA_LOOKUP_DREG] = { .type = NLA_U32 }, 56 [NFTA_LOOKUP_DREG] = { .type = NLA_U32 },
57 [NFTA_LOOKUP_FLAGS] = { .type = NLA_U32 },
50}; 58};
51 59
52static int nft_lookup_init(const struct nft_ctx *ctx, 60static int nft_lookup_init(const struct nft_ctx *ctx,
@@ -56,6 +64,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
56 struct nft_lookup *priv = nft_expr_priv(expr); 64 struct nft_lookup *priv = nft_expr_priv(expr);
57 u8 genmask = nft_genmask_next(ctx->net); 65 u8 genmask = nft_genmask_next(ctx->net);
58 struct nft_set *set; 66 struct nft_set *set;
67 u32 flags;
59 int err; 68 int err;
60 69
61 if (tb[NFTA_LOOKUP_SET] == NULL || 70 if (tb[NFTA_LOOKUP_SET] == NULL ||
@@ -81,7 +90,22 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
81 if (err < 0) 90 if (err < 0)
82 return err; 91 return err;
83 92
93 if (tb[NFTA_LOOKUP_FLAGS]) {
94 flags = ntohl(nla_get_be32(tb[NFTA_LOOKUP_FLAGS]));
95
96 if (flags & ~NFT_LOOKUP_F_INV)
97 return -EINVAL;
98
99 if (flags & NFT_LOOKUP_F_INV) {
100 if (set->flags & NFT_SET_MAP)
101 return -EINVAL;
102 priv->invert = true;
103 }
104 }
105
84 if (tb[NFTA_LOOKUP_DREG] != NULL) { 106 if (tb[NFTA_LOOKUP_DREG] != NULL) {
107 if (priv->invert)
108 return -EINVAL;
85 if (!(set->flags & NFT_SET_MAP)) 109 if (!(set->flags & NFT_SET_MAP))
86 return -EINVAL; 110 return -EINVAL;
87 111
@@ -114,6 +138,7 @@ static void nft_lookup_destroy(const struct nft_ctx *ctx,
114static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) 138static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr)
115{ 139{
116 const struct nft_lookup *priv = nft_expr_priv(expr); 140 const struct nft_lookup *priv = nft_expr_priv(expr);
141 u32 flags = priv->invert ? NFT_LOOKUP_F_INV : 0;
117 142
118 if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) 143 if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name))
119 goto nla_put_failure; 144 goto nla_put_failure;
@@ -122,6 +147,8 @@ static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr)
122 if (priv->set->flags & NFT_SET_MAP) 147 if (priv->set->flags & NFT_SET_MAP)
123 if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg)) 148 if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg))
124 goto nla_put_failure; 149 goto nla_put_failure;
150 if (nla_put_be32(skb, NFTA_LOOKUP_FLAGS, htonl(flags)))
151 goto nla_put_failure;
125 return 0; 152 return 0;
126 153
127nla_put_failure: 154nla_put_failure: