Skip to content

Commit c7862a5

Browse files
committed
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 <[email protected]>
1 parent 5913bea commit c7862a5

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,20 +780,26 @@ enum nft_limit_type {
780780
NFT_LIMIT_PKT_BYTES
781781
};
782782

783+
enum nft_limit_flags {
784+
NFT_LIMIT_F_INV = (1 << 0),
785+
};
786+
783787
/**
784788
* enum nft_limit_attributes - nf_tables limit expression netlink attributes
785789
*
786790
* @NFTA_LIMIT_RATE: refill rate (NLA_U64)
787791
* @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
788792
* @NFTA_LIMIT_BURST: burst (NLA_U32)
789793
* @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type)
794+
* @NFTA_LIMIT_FLAGS: flags (NLA_U32: enum nft_limit_flags)
790795
*/
791796
enum nft_limit_attributes {
792797
NFTA_LIMIT_UNSPEC,
793798
NFTA_LIMIT_RATE,
794799
NFTA_LIMIT_UNIT,
795800
NFTA_LIMIT_BURST,
796801
NFTA_LIMIT_TYPE,
802+
NFTA_LIMIT_FLAGS,
797803
__NFTA_LIMIT_MAX
798804
};
799805
#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)

net/netfilter/nft_limit.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct nft_limit {
2626
u64 rate;
2727
u64 nsecs;
2828
u32 burst;
29+
bool invert;
2930
};
3031

3132
static 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)
4445
if (delta >= 0) {
4546
limit->tokens = delta;
4647
spin_unlock_bh(&limit_lock);
47-
return false;
48+
return limit->invert;
4849
}
4950
limit->tokens = tokens;
5051
spin_unlock_bh(&limit_lock);
51-
return true;
52+
return !limit->invert;
5253
}
5354

5455
static int nft_limit_init(struct nft_limit *limit,
@@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit,
7879

7980
limit->rate = rate;
8081
}
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+
}
8188
limit->last = ktime_get_ns();
8289

8390
return 0;
@@ -86,13 +93,15 @@ static int nft_limit_init(struct nft_limit *limit,
8693
static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,
8794
enum nft_limit_type type)
8895
{
96+
u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
8997
u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
9098
u64 rate = limit->rate - limit->burst;
9199

92100
if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) ||
93101
nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) ||
94102
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)))
96105
goto nla_put_failure;
97106
return 0;
98107

@@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
120129
[NFTA_LIMIT_UNIT] = { .type = NLA_U64 },
121130
[NFTA_LIMIT_BURST] = { .type = NLA_U32 },
122131
[NFTA_LIMIT_TYPE] = { .type = NLA_U32 },
132+
[NFTA_LIMIT_FLAGS] = { .type = NLA_U32 },
123133
};
124134

125135
static int nft_limit_pkts_init(const struct nft_ctx *ctx,

0 commit comments

Comments
 (0)