root/net/netfilter/xt_statistic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. statistic_mt
  2. statistic_mt_check
  3. statistic_mt_destroy
  4. statistic_mt_init
  5. statistic_mt_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
   4  *
   5  * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>.
   6  */
   7 
   8 #include <linux/init.h>
   9 #include <linux/spinlock.h>
  10 #include <linux/skbuff.h>
  11 #include <linux/net.h>
  12 #include <linux/slab.h>
  13 
  14 #include <linux/netfilter/xt_statistic.h>
  15 #include <linux/netfilter/x_tables.h>
  16 #include <linux/module.h>
  17 
  18 struct xt_statistic_priv {
  19         atomic_t count;
  20 } ____cacheline_aligned_in_smp;
  21 
  22 MODULE_LICENSE("GPL");
  23 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  24 MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)");
  25 MODULE_ALIAS("ipt_statistic");
  26 MODULE_ALIAS("ip6t_statistic");
  27 
  28 static bool
  29 statistic_mt(const struct sk_buff *skb, struct xt_action_param *par)
  30 {
  31         const struct xt_statistic_info *info = par->matchinfo;
  32         bool ret = info->flags & XT_STATISTIC_INVERT;
  33         int nval, oval;
  34 
  35         switch (info->mode) {
  36         case XT_STATISTIC_MODE_RANDOM:
  37                 if ((prandom_u32() & 0x7FFFFFFF) < info->u.random.probability)
  38                         ret = !ret;
  39                 break;
  40         case XT_STATISTIC_MODE_NTH:
  41                 do {
  42                         oval = atomic_read(&info->master->count);
  43                         nval = (oval == info->u.nth.every) ? 0 : oval + 1;
  44                 } while (atomic_cmpxchg(&info->master->count, oval, nval) != oval);
  45                 if (nval == 0)
  46                         ret = !ret;
  47                 break;
  48         }
  49 
  50         return ret;
  51 }
  52 
  53 static int statistic_mt_check(const struct xt_mtchk_param *par)
  54 {
  55         struct xt_statistic_info *info = par->matchinfo;
  56 
  57         if (info->mode > XT_STATISTIC_MODE_MAX ||
  58             info->flags & ~XT_STATISTIC_MASK)
  59                 return -EINVAL;
  60 
  61         info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
  62         if (info->master == NULL)
  63                 return -ENOMEM;
  64         atomic_set(&info->master->count, info->u.nth.count);
  65 
  66         return 0;
  67 }
  68 
  69 static void statistic_mt_destroy(const struct xt_mtdtor_param *par)
  70 {
  71         const struct xt_statistic_info *info = par->matchinfo;
  72 
  73         kfree(info->master);
  74 }
  75 
  76 static struct xt_match xt_statistic_mt_reg __read_mostly = {
  77         .name       = "statistic",
  78         .revision   = 0,
  79         .family     = NFPROTO_UNSPEC,
  80         .match      = statistic_mt,
  81         .checkentry = statistic_mt_check,
  82         .destroy    = statistic_mt_destroy,
  83         .matchsize  = sizeof(struct xt_statistic_info),
  84         .usersize   = offsetof(struct xt_statistic_info, master),
  85         .me         = THIS_MODULE,
  86 };
  87 
  88 static int __init statistic_mt_init(void)
  89 {
  90         return xt_register_match(&xt_statistic_mt_reg);
  91 }
  92 
  93 static void __exit statistic_mt_exit(void)
  94 {
  95         xt_unregister_match(&xt_statistic_mt_reg);
  96 }
  97 
  98 module_init(statistic_mt_init);
  99 module_exit(statistic_mt_exit);

/* [<][>][^][v][top][bottom][index][help] */