File Index
Files and directories
Sign in
FILE

ebt_limit.c

File preview with syntax highlighting.

linux-6.19.14/net/bridge/netfilter/ebt_limit.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 *  ebt_limit
  4 *
  5 *	Authors:
  6 *	Tom Marshall <tommy@home.tig-grr.com>
  7 *
  8 *	Mostly copied from netfilter's ipt_limit.c, see that file for
  9 *	more explanation
 10 *
 11 *  September, 2003
 12 *
 13 */
 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 15#include <linux/module.h>
 16#include <linux/netdevice.h>
 17#include <linux/spinlock.h>
 18#include <linux/netfilter/x_tables.h>
 19#include <linux/netfilter_bridge/ebtables.h>
 20#include <linux/netfilter_bridge/ebt_limit.h>
 21
 22static DEFINE_SPINLOCK(limit_lock);
 23
 24#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
 25
 26#define _POW2_BELOW2(x) ((x)|((x)>>1))
 27#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
 28#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
 29#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
 30#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
 31#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
 32
 33#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
 34
 35static bool
 36ebt_limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 37{
 38	struct ebt_limit_info *info = (void *)par->matchinfo;
 39	unsigned long now = jiffies;
 40
 41	spin_lock_bh(&limit_lock);
 42	info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY;
 43	if (info->credit > info->credit_cap)
 44		info->credit = info->credit_cap;
 45
 46	if (info->credit >= info->cost) {
 47		/* We're not limited. */
 48		info->credit -= info->cost;
 49		spin_unlock_bh(&limit_lock);
 50		return true;
 51	}
 52
 53	spin_unlock_bh(&limit_lock);
 54	return false;
 55}
 56
 57/* Precision saver. */
 58static u_int32_t
 59user2credits(u_int32_t user)
 60{
 61	/* If multiplying would overflow... */
 62	if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
 63		/* Divide first. */
 64		return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
 65
 66	return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
 67}
 68
 69static int ebt_limit_mt_check(const struct xt_mtchk_param *par)
 70{
 71	struct ebt_limit_info *info = par->matchinfo;
 72
 73	/* Check for overflow. */
 74	if (info->burst == 0 ||
 75	    user2credits(info->avg * info->burst) < user2credits(info->avg)) {
 76		pr_info_ratelimited("overflow, try lower: %u/%u\n",
 77				    info->avg, info->burst);
 78		return -EINVAL;
 79	}
 80
 81	/* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
 82	info->prev = jiffies;
 83	info->credit = user2credits(info->avg * info->burst);
 84	info->credit_cap = user2credits(info->avg * info->burst);
 85	info->cost = user2credits(info->avg);
 86	return 0;
 87}
 88
 89
 90#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
 91/*
 92 * no conversion function needed --
 93 * only avg/burst have meaningful values in userspace.
 94 */
 95struct ebt_compat_limit_info {
 96	compat_uint_t avg, burst;
 97	compat_ulong_t prev;
 98	compat_uint_t credit, credit_cap, cost;
 99};
100#endif
101
102static struct xt_match ebt_limit_mt_reg __read_mostly = {
103	.name		= "limit",
104	.revision	= 0,
105	.family		= NFPROTO_BRIDGE,
106	.match		= ebt_limit_mt,
107	.checkentry	= ebt_limit_mt_check,
108	.matchsize	= sizeof(struct ebt_limit_info),
109	.usersize	= offsetof(struct ebt_limit_info, prev),
110#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
111	.compatsize	= sizeof(struct ebt_compat_limit_info),
112#endif
113	.me		= THIS_MODULE,
114};
115
116static int __init ebt_limit_init(void)
117{
118	return xt_register_match(&ebt_limit_mt_reg);
119}
120
121static void __exit ebt_limit_fini(void)
122{
123	xt_unregister_match(&ebt_limit_mt_reg);
124}
125
126module_init(ebt_limit_init);
127module_exit(ebt_limit_fini);
128MODULE_DESCRIPTION("Ebtables: Rate-limit match");
129MODULE_LICENSE("GPL");
~/ Read-only file preview.