Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * netfilter module to enforce network quotas
0004  *
0005  * Sam Johnston <samj@samj.net>
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         /* we do not allow even small packets from now on */
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(&quota_mt_reg);
0084 }
0085 
0086 static void __exit quota_mt_exit(void)
0087 {
0088     xt_unregister_match(&quota_mt_reg);
0089 }
0090 
0091 module_init(quota_mt_init);
0092 module_exit(quota_mt_exit);