1/* 2 * Copyright (c) 2006 Patrick McHardy <kaber@trash.net> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>. 9 */ 10 11#include <linux/init.h> 12#include <linux/spinlock.h> 13#include <linux/skbuff.h> 14#include <linux/net.h> 15 16#include <linux/netfilter/xt_statistic.h> 17#include <linux/netfilter/x_tables.h> 18 19MODULE_LICENSE("GPL"); 20MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 21MODULE_DESCRIPTION("xtables statistical match module"); 22MODULE_ALIAS("ipt_statistic"); 23MODULE_ALIAS("ip6t_statistic"); 24 25static DEFINE_SPINLOCK(nth_lock); 26 27static int 28match(const struct sk_buff *skb, 29 const struct net_device *in, const struct net_device *out, 30 const struct xt_match *match, const void *matchinfo, 31 int offset, unsigned int protoff, int *hotdrop) 32{ 33 struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; 34 int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0; 35 36 switch (info->mode) { 37 case XT_STATISTIC_MODE_RANDOM: 38 if ((net_random() & 0x7FFFFFFF) < info->u.random.probability) 39 ret ^= 1; 40 break; 41 case XT_STATISTIC_MODE_NTH: 42 info = info->master; 43 spin_lock_bh(&nth_lock); 44 if (info->u.nth.count++ == info->u.nth.every) { 45 info->u.nth.count = 0; 46 ret ^= 1; 47 } 48 spin_unlock_bh(&nth_lock); 49 break; 50 } 51 52 return ret; 53} 54 55static int 56checkentry(const char *tablename, const void *entry, 57 const struct xt_match *match, void *matchinfo, 58 unsigned int hook_mask) 59{ 60 struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; 61 62 if (info->mode > XT_STATISTIC_MODE_MAX || 63 info->flags & ~XT_STATISTIC_MASK) 64 return 0; 65 info->master = info; 66 return 1; 67} 68 69static struct xt_match xt_statistic_match[] = { 70 { 71 .name = "statistic", 72 .family = AF_INET, 73 .checkentry = checkentry, 74 .match = match, 75 .matchsize = sizeof(struct xt_statistic_info), 76 .me = THIS_MODULE, 77 }, 78 { 79 .name = "statistic", 80 .family = AF_INET6, 81 .checkentry = checkentry, 82 .match = match, 83 .matchsize = sizeof(struct xt_statistic_info), 84 .me = THIS_MODULE, 85 }, 86}; 87 88static int __init xt_statistic_init(void) 89{ 90 return xt_register_matches(xt_statistic_match, 91 ARRAY_SIZE(xt_statistic_match)); 92} 93 94static void __exit xt_statistic_fini(void) 95{ 96 xt_unregister_matches(xt_statistic_match, 97 ARRAY_SIZE(xt_statistic_match)); 98} 99 100module_init(xt_statistic_init); 101module_exit(xt_statistic_fini); 102