1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

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>
This commit is contained in:
Pablo Neira Ayuso 2015-12-28 18:21:44 +01:00
parent 5913beaf0d
commit c7862a5f0d
2 changed files with 19 additions and 3 deletions

View file

@ -780,6 +780,10 @@ enum nft_limit_type {
NFT_LIMIT_PKT_BYTES NFT_LIMIT_PKT_BYTES
}; };
enum nft_limit_flags {
NFT_LIMIT_F_INV = (1 << 0),
};
/** /**
* enum nft_limit_attributes - nf_tables limit expression netlink attributes * enum nft_limit_attributes - nf_tables limit expression netlink attributes
* *
@ -787,6 +791,7 @@ enum nft_limit_type {
* @NFTA_LIMIT_UNIT: refill unit (NLA_U64) * @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
* @NFTA_LIMIT_BURST: burst (NLA_U32) * @NFTA_LIMIT_BURST: burst (NLA_U32)
* @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type) * @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type)
* @NFTA_LIMIT_FLAGS: flags (NLA_U32: enum nft_limit_flags)
*/ */
enum nft_limit_attributes { enum nft_limit_attributes {
NFTA_LIMIT_UNSPEC, NFTA_LIMIT_UNSPEC,
@ -794,6 +799,7 @@ enum nft_limit_attributes {
NFTA_LIMIT_UNIT, NFTA_LIMIT_UNIT,
NFTA_LIMIT_BURST, NFTA_LIMIT_BURST,
NFTA_LIMIT_TYPE, NFTA_LIMIT_TYPE,
NFTA_LIMIT_FLAGS,
__NFTA_LIMIT_MAX __NFTA_LIMIT_MAX
}; };
#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1) #define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)

View file

@ -26,6 +26,7 @@ struct nft_limit {
u64 rate; u64 rate;
u64 nsecs; u64 nsecs;
u32 burst; u32 burst;
bool invert;
}; };
static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost) 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)
if (delta >= 0) { if (delta >= 0) {
limit->tokens = delta; limit->tokens = delta;
spin_unlock_bh(&limit_lock); spin_unlock_bh(&limit_lock);
return false; return limit->invert;
} }
limit->tokens = tokens; limit->tokens = tokens;
spin_unlock_bh(&limit_lock); spin_unlock_bh(&limit_lock);
return true; return !limit->invert;
} }
static int nft_limit_init(struct nft_limit *limit, static int nft_limit_init(struct nft_limit *limit,
@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit,
limit->rate = rate; limit->rate = rate;
} }
if (tb[NFTA_LIMIT_FLAGS]) {
u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
if (flags & NFT_LIMIT_F_INV)
limit->invert = true;
}
limit->last = ktime_get_ns(); limit->last = ktime_get_ns();
return 0; return 0;
@ -86,13 +93,15 @@ static int nft_limit_init(struct nft_limit *limit,
static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,
enum nft_limit_type type) enum nft_limit_type type)
{ {
u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
u64 rate = limit->rate - limit->burst; u64 rate = limit->rate - limit->burst;
if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) || if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) ||
nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) || nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) ||
nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) || nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) ||
nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type))) nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) ||
nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags)))
goto nla_put_failure; goto nla_put_failure;
return 0; return 0;
@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
[NFTA_LIMIT_UNIT] = { .type = NLA_U64 }, [NFTA_LIMIT_UNIT] = { .type = NLA_U64 },
[NFTA_LIMIT_BURST] = { .type = NLA_U32 }, [NFTA_LIMIT_BURST] = { .type = NLA_U32 },
[NFTA_LIMIT_TYPE] = { .type = NLA_U32 }, [NFTA_LIMIT_TYPE] = { .type = NLA_U32 },
[NFTA_LIMIT_FLAGS] = { .type = NLA_U32 },
}; };
static int nft_limit_pkts_init(const struct nft_ctx *ctx, static int nft_limit_pkts_init(const struct nft_ctx *ctx,