linux/net/netfilter/xt_quota.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * netfilter module to enforce network quotas
   4 *
   5 * Sam Johnston <samj@samj.net>
   6 */
   7#include <linux/skbuff.h>
   8#include <linux/slab.h>
   9#include <linux/spinlock.h>
  10
  11#include <linux/netfilter/x_tables.h>
  12#include <linux/netfilter/xt_quota.h>
  13#include <linux/module.h>
  14
  15struct xt_quota_priv {
  16        spinlock_t      lock;
  17        uint64_t        quota;
  18};
  19
  20MODULE_LICENSE("GPL");
  21MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
  22MODULE_DESCRIPTION("Xtables: countdown quota match");
  23MODULE_ALIAS("ipt_quota");
  24MODULE_ALIAS("ip6t_quota");
  25
  26static bool
  27quota_mt(const struct sk_buff *skb, struct xt_action_param *par)
  28{
  29        struct xt_quota_info *q = (void *)par->matchinfo;
  30        struct xt_quota_priv *priv = q->master;
  31        bool ret = q->flags & XT_QUOTA_INVERT;
  32
  33        spin_lock_bh(&priv->lock);
  34        if (priv->quota >= skb->len) {
  35                priv->quota -= skb->len;
  36                ret = !ret;
  37        } else {
  38                /* we do not allow even small packets from now on */
  39                priv->quota = 0;
  40        }
  41        spin_unlock_bh(&priv->lock);
  42
  43        return ret;
  44}
  45
  46static int quota_mt_check(const struct xt_mtchk_param *par)
  47{
  48        struct xt_quota_info *q = par->matchinfo;
  49
  50        if (q->flags & ~XT_QUOTA_MASK)
  51                return -EINVAL;
  52
  53        q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
  54        if (q->master == NULL)
  55                return -ENOMEM;
  56
  57        spin_lock_init(&q->master->lock);
  58        q->master->quota = q->quota;
  59        return 0;
  60}
  61
  62static void quota_mt_destroy(const struct xt_mtdtor_param *par)
  63{
  64        const struct xt_quota_info *q = par->matchinfo;
  65
  66        kfree(q->master);
  67}
  68
  69static struct xt_match quota_mt_reg __read_mostly = {
  70        .name       = "quota",
  71        .revision   = 0,
  72        .family     = NFPROTO_UNSPEC,
  73        .match      = quota_mt,
  74        .checkentry = quota_mt_check,
  75        .destroy    = quota_mt_destroy,
  76        .matchsize  = sizeof(struct xt_quota_info),
  77        .usersize   = offsetof(struct xt_quota_info, master),
  78        .me         = THIS_MODULE,
  79};
  80
  81static int __init quota_mt_init(void)
  82{
  83        return xt_register_match(&quota_mt_reg);
  84}
  85
  86static void __exit quota_mt_exit(void)
  87{
  88        xt_unregister_match(&quota_mt_reg);
  89}
  90
  91module_init(quota_mt_init);
  92module_exit(quota_mt_exit);
  93