diff options
author | Patrick McHardy <kaber@trash.net> | 2006-05-30 01:20:32 (GMT) |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 04:28:49 (GMT) |
commit | 62b7743483b402f8fb73545d5d487ca714e82766 (patch) | |
tree | f90e434e85c1f4391ad46310ee128ce25c1dca57 /net/netfilter/xt_quota.c | |
parent | 957dc80ac30f3c4d53259fa936df807663ba54fa (diff) | |
download | linux-fsl-qoriq-62b7743483b402f8fb73545d5d487ca714e82766.tar.xz |
[NETFILTER]: x_tables: add quota match
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter/xt_quota.c')
-rw-r--r-- | net/netfilter/xt_quota.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c new file mode 100644 index 0000000..4cdba74 --- /dev/null +++ b/net/netfilter/xt_quota.c @@ -0,0 +1,96 @@ +/* + * netfilter module to enforce network quotas + * + * Sam Johnston <samj@samj.net> + */ +#include <linux/skbuff.h> +#include <linux/spinlock.h> + +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_quota.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sam Johnston <samj@samj.net>"); + +static DEFINE_SPINLOCK(quota_lock); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, + int offset, unsigned int protoff, int *hotdrop) +{ + struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master; + int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0; + + spin_lock_bh("a_lock); + if (q->quota >= skb->len) { + q->quota -= skb->len; + ret ^= 1; + } else { + /* we do not allow even small packets from now on */ + q->quota = 0; + } + spin_unlock_bh("a_lock); + + return ret; +} + +static int +checkentry(const char *tablename, const void *entry, + const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) +{ + struct xt_quota_info *q = (struct xt_quota_info *)matchinfo; + + if (q->flags & ~XT_QUOTA_MASK) + return 0; + /* For SMP, we only want to use one set of counters. */ + q->master = q; + return 1; +} + +static struct xt_match quota_match = { + .name = "quota", + .family = AF_INET, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static struct xt_match quota_match6 = { + .name = "quota", + .family = AF_INET6, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static int __init xt_quota_init(void) +{ + int ret; + + ret = xt_register_match("a_match); + if (ret) + goto err1; + ret = xt_register_match("a_match6); + if (ret) + goto err2; + return ret; + +err2: + xt_unregister_match("a_match); +err1: + return ret; +} + +static void __exit xt_quota_fini(void) +{ + xt_unregister_match("a_match6); + xt_unregister_match("a_match); +} + +module_init(xt_quota_init); +module_exit(xt_quota_fini); |