aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2015-12-28 12:21:44 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2016-01-03 14:58:52 -0500
commitc7862a5f0de5f521c545f3436f0aa190964342dd (patch)
treef128e6751c4e20198b973dda2fd257d803bd02a5 /net/netfilter
parent5913beaf0d70f97135ed7191c028fd88b3848864 (diff)
netfilter: nft_limit: allow to invert matching criteria
This patch allows you to invert the ratelimit matching criteria, so you can match packets over the ratelimit. This is required to support what hashlimit does. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nft_limit.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c
index 5d67938f8b2f..99d18578afc6 100644
--- a/net/netfilter/nft_limit.c
+++ b/net/netfilter/nft_limit.c
@@ -26,6 +26,7 @@ struct nft_limit {
26 u64 rate; 26 u64 rate;
27 u64 nsecs; 27 u64 nsecs;
28 u32 burst; 28 u32 burst;
29 bool invert;
29}; 30};
30 31
31static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost) 32static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
@@ -44,11 +45,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
44 if (delta >= 0) { 45 if (delta >= 0) {
45 limit->tokens = delta; 46 limit->tokens = delta;
46 spin_unlock_bh(&limit_lock); 47 spin_unlock_bh(&limit_lock);
47 return false; 48 return limit->invert;
48 } 49 }
49 limit->tokens = tokens; 50 limit->tokens = tokens;
50 spin_unlock_bh(&limit_lock); 51 spin_unlock_bh(&limit_lock);
51 return true; 52 return !limit->invert;
52} 53}
53 54
54static int nft_limit_init(struct nft_limit *limit, 55static int nft_limit_init(struct nft_limit *limit,
@@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit,
78 79
79 limit->rate = rate; 80 limit->rate = rate;
80 } 81 }
82 if (tb[NFTA_LIMIT_FLAGS]) {
83 u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
84
85 if (flags & NFT_LIMIT_F_INV)
86 limit->invert = true;
87 }
81 limit->last = ktime_get_ns(); 88 limit->last = ktime_get_ns();
82 89
83 return 0; 90 return 0;
@@ -86,13 +93,15 @@ static int nft_limit_init(struct nft_limit *limit,
86static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, 93static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,
87 enum nft_limit_type type) 94 enum nft_limit_type type)
88{ 95{
96 u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
89 u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); 97 u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
90 u64 rate = limit->rate - limit->burst; 98 u64 rate = limit->rate - limit->burst;
91 99
92 if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) || 100 if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) ||
93 nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) || 101 nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) ||
94 nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) || 102 nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) ||
95 nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type))) 103 nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) ||
104 nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags)))
96 goto nla_put_failure; 105 goto nla_put_failure;
97 return 0; 106 return 0;
98 107
@@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
120 [NFTA_LIMIT_UNIT] = { .type = NLA_U64 }, 129 [NFTA_LIMIT_UNIT] = { .type = NLA_U64 },
121 [NFTA_LIMIT_BURST] = { .type = NLA_U32 }, 130 [NFTA_LIMIT_BURST] = { .type = NLA_U32 },
122 [NFTA_LIMIT_TYPE] = { .type = NLA_U32 }, 131 [NFTA_LIMIT_TYPE] = { .type = NLA_U32 },
132 [NFTA_LIMIT_FLAGS] = { .type = NLA_U32 },
123}; 133};
124 134
125static int nft_limit_pkts_init(const struct nft_ctx *ctx, 135static int nft_limit_pkts_init(const struct nft_ctx *ctx,