0001
0002
0003
0004
0005
0006
0007 #include <linux/skbuff.h>
0008 #include <linux/slab.h>
0009 #include <linux/spinlock.h>
0010
0011 #include <linux/netfilter/x_tables.h>
0012 #include <linux/netfilter/xt_quota.h>
0013 #include <linux/module.h>
0014
0015 struct xt_quota_priv {
0016 spinlock_t lock;
0017 uint64_t quota;
0018 };
0019
0020 MODULE_LICENSE("GPL");
0021 MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
0022 MODULE_DESCRIPTION("Xtables: countdown quota match");
0023 MODULE_ALIAS("ipt_quota");
0024 MODULE_ALIAS("ip6t_quota");
0025
0026 static bool
0027 quota_mt(const struct sk_buff *skb, struct xt_action_param *par)
0028 {
0029 struct xt_quota_info *q = (void *)par->matchinfo;
0030 struct xt_quota_priv *priv = q->master;
0031 bool ret = q->flags & XT_QUOTA_INVERT;
0032
0033 spin_lock_bh(&priv->lock);
0034 if (priv->quota >= skb->len) {
0035 priv->quota -= skb->len;
0036 ret = !ret;
0037 } else {
0038
0039 priv->quota = 0;
0040 }
0041 spin_unlock_bh(&priv->lock);
0042
0043 return ret;
0044 }
0045
0046 static int quota_mt_check(const struct xt_mtchk_param *par)
0047 {
0048 struct xt_quota_info *q = par->matchinfo;
0049
0050 if (q->flags & ~XT_QUOTA_MASK)
0051 return -EINVAL;
0052
0053 q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
0054 if (q->master == NULL)
0055 return -ENOMEM;
0056
0057 spin_lock_init(&q->master->lock);
0058 q->master->quota = q->quota;
0059 return 0;
0060 }
0061
0062 static void quota_mt_destroy(const struct xt_mtdtor_param *par)
0063 {
0064 const struct xt_quota_info *q = par->matchinfo;
0065
0066 kfree(q->master);
0067 }
0068
0069 static struct xt_match quota_mt_reg __read_mostly = {
0070 .name = "quota",
0071 .revision = 0,
0072 .family = NFPROTO_UNSPEC,
0073 .match = quota_mt,
0074 .checkentry = quota_mt_check,
0075 .destroy = quota_mt_destroy,
0076 .matchsize = sizeof(struct xt_quota_info),
0077 .usersize = offsetof(struct xt_quota_info, master),
0078 .me = THIS_MODULE,
0079 };
0080
0081 static int __init quota_mt_init(void)
0082 {
0083 return xt_register_match("a_mt_reg);
0084 }
0085
0086 static void __exit quota_mt_exit(void)
0087 {
0088 xt_unregister_match("a_mt_reg);
0089 }
0090
0091 module_init(quota_mt_init);
0092 module_exit(quota_mt_exit);