Skip to content

Commit

Permalink
netfilter: nft_limit: allow to invert matching criteria
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pablo Neira Ayuso committed Jan 3, 2016
1 parent 5913bea commit c7862a5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
6 changes: 6 additions & 0 deletions include/uapi/linux/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,20 +780,26 @@ enum nft_limit_type {
NFT_LIMIT_PKT_BYTES
};

enum nft_limit_flags {
NFT_LIMIT_F_INV = (1 << 0),
};

/**
* enum nft_limit_attributes - nf_tables limit expression netlink attributes
*
* @NFTA_LIMIT_RATE: refill rate (NLA_U64)
* @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
* @NFTA_LIMIT_BURST: burst (NLA_U32)
* @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 {
NFTA_LIMIT_UNSPEC,
NFTA_LIMIT_RATE,
NFTA_LIMIT_UNIT,
NFTA_LIMIT_BURST,
NFTA_LIMIT_TYPE,
NFTA_LIMIT_FLAGS,
__NFTA_LIMIT_MAX
};
#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)
Expand Down
16 changes: 13 additions & 3 deletions net/netfilter/nft_limit.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct nft_limit {
u64 rate;
u64 nsecs;
u32 burst;
bool invert;
};

static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
Expand All @@ -44,11 +45,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
if (delta >= 0) {
limit->tokens = delta;
spin_unlock_bh(&limit_lock);
return false;
return limit->invert;
}
limit->tokens = tokens;
spin_unlock_bh(&limit_lock);
return true;
return !limit->invert;
}

static int nft_limit_init(struct nft_limit *limit,
Expand Down Expand Up @@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit,

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();

return 0;
Expand All @@ -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,
enum nft_limit_type type)
{
u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
u64 rate = limit->rate - limit->burst;

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_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;
return 0;

Expand Down Expand Up @@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
[NFTA_LIMIT_UNIT] = { .type = NLA_U64 },
[NFTA_LIMIT_BURST] = { .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,
Expand Down

0 comments on commit c7862a5

Please sign in to comment.