diff options
| -rw-r--r-- | include/uapi/linux/netfilter/nf_tables.h | 6 | ||||
| -rw-r--r-- | net/netfilter/nft_limit.c | 16 | 
2 files changed, 19 insertions, 3 deletions
| diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index b48a3ab761f8..22043ce95ae6 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -780,6 +780,10 @@ 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   * @@ -787,6 +791,7 @@ enum nft_limit_type {   * @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, @@ -794,6 +799,7 @@ enum nft_limit_attributes {  	NFTA_LIMIT_UNIT,  	NFTA_LIMIT_BURST,  	NFTA_LIMIT_TYPE, +	NFTA_LIMIT_FLAGS,  	__NFTA_LIMIT_MAX  };  #define NFTA_LIMIT_MAX		(__NFTA_LIMIT_MAX - 1) 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 {  	u64		rate;  	u64		nsecs;  	u32		burst; +	bool		invert;  };  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) {  		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, @@ -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; @@ -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; @@ -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, | 
