Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25-rc1 205 lines 5.0 kB view raw
1/* 2 * (C) 2007 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#include <linux/module.h> 9#include <linux/skbuff.h> 10#include <linux/gen_stats.h> 11#include <linux/jhash.h> 12#include <linux/rtnetlink.h> 13#include <linux/random.h> 14#include <net/gen_stats.h> 15#include <net/netlink.h> 16 17#include <linux/netfilter/x_tables.h> 18#include <linux/netfilter/xt_RATEEST.h> 19#include <net/netfilter/xt_rateest.h> 20 21static DEFINE_MUTEX(xt_rateest_mutex); 22 23#define RATEEST_HSIZE 16 24static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; 25static unsigned int jhash_rnd __read_mostly; 26 27static unsigned int xt_rateest_hash(const char *name) 28{ 29 return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & 30 (RATEEST_HSIZE - 1); 31} 32 33static void xt_rateest_hash_insert(struct xt_rateest *est) 34{ 35 unsigned int h; 36 37 h = xt_rateest_hash(est->name); 38 hlist_add_head(&est->list, &rateest_hash[h]); 39} 40 41struct xt_rateest *xt_rateest_lookup(const char *name) 42{ 43 struct xt_rateest *est; 44 struct hlist_node *n; 45 unsigned int h; 46 47 h = xt_rateest_hash(name); 48 mutex_lock(&xt_rateest_mutex); 49 hlist_for_each_entry(est, n, &rateest_hash[h], list) { 50 if (strcmp(est->name, name) == 0) { 51 est->refcnt++; 52 mutex_unlock(&xt_rateest_mutex); 53 return est; 54 } 55 } 56 mutex_unlock(&xt_rateest_mutex); 57 return NULL; 58} 59EXPORT_SYMBOL_GPL(xt_rateest_lookup); 60 61void xt_rateest_put(struct xt_rateest *est) 62{ 63 mutex_lock(&xt_rateest_mutex); 64 if (--est->refcnt == 0) { 65 hlist_del(&est->list); 66 gen_kill_estimator(&est->bstats, &est->rstats); 67 kfree(est); 68 } 69 mutex_unlock(&xt_rateest_mutex); 70} 71EXPORT_SYMBOL_GPL(xt_rateest_put); 72 73static unsigned int 74xt_rateest_tg(struct sk_buff *skb, 75 const struct net_device *in, 76 const struct net_device *out, 77 unsigned int hooknum, 78 const struct xt_target *target, 79 const void *targinfo) 80{ 81 const struct xt_rateest_target_info *info = targinfo; 82 struct gnet_stats_basic *stats = &info->est->bstats; 83 84 spin_lock_bh(&info->est->lock); 85 stats->bytes += skb->len; 86 stats->packets++; 87 spin_unlock_bh(&info->est->lock); 88 89 return XT_CONTINUE; 90} 91 92static bool 93xt_rateest_tg_checkentry(const char *tablename, 94 const void *entry, 95 const struct xt_target *target, 96 void *targinfo, 97 unsigned int hook_mask) 98{ 99 struct xt_rateest_target_info *info = (void *)targinfo; 100 struct xt_rateest *est; 101 struct { 102 struct nlattr opt; 103 struct gnet_estimator est; 104 } cfg; 105 106 est = xt_rateest_lookup(info->name); 107 if (est) { 108 /* 109 * If estimator parameters are specified, they must match the 110 * existing estimator. 111 */ 112 if ((!info->interval && !info->ewma_log) || 113 (info->interval != est->params.interval || 114 info->ewma_log != est->params.ewma_log)) { 115 xt_rateest_put(est); 116 return false; 117 } 118 info->est = est; 119 return true; 120 } 121 122 est = kzalloc(sizeof(*est), GFP_KERNEL); 123 if (!est) 124 goto err1; 125 126 strlcpy(est->name, info->name, sizeof(est->name)); 127 spin_lock_init(&est->lock); 128 est->refcnt = 1; 129 est->params.interval = info->interval; 130 est->params.ewma_log = info->ewma_log; 131 132 cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); 133 cfg.opt.nla_type = TCA_STATS_RATE_EST; 134 cfg.est.interval = info->interval; 135 cfg.est.ewma_log = info->ewma_log; 136 137 if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, 138 &cfg.opt) < 0) 139 goto err2; 140 141 info->est = est; 142 xt_rateest_hash_insert(est); 143 144 return true; 145 146err2: 147 kfree(est); 148err1: 149 return false; 150} 151 152static void xt_rateest_tg_destroy(const struct xt_target *target, 153 void *targinfo) 154{ 155 struct xt_rateest_target_info *info = targinfo; 156 157 xt_rateest_put(info->est); 158} 159 160static struct xt_target xt_rateest_target[] __read_mostly = { 161 { 162 .family = AF_INET, 163 .name = "RATEEST", 164 .target = xt_rateest_tg, 165 .checkentry = xt_rateest_tg_checkentry, 166 .destroy = xt_rateest_tg_destroy, 167 .targetsize = sizeof(struct xt_rateest_target_info), 168 .me = THIS_MODULE, 169 }, 170 { 171 .family = AF_INET6, 172 .name = "RATEEST", 173 .target = xt_rateest_tg, 174 .checkentry = xt_rateest_tg_checkentry, 175 .destroy = xt_rateest_tg_destroy, 176 .targetsize = sizeof(struct xt_rateest_target_info), 177 .me = THIS_MODULE, 178 }, 179}; 180 181static int __init xt_rateest_tg_init(void) 182{ 183 unsigned int i; 184 185 for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) 186 INIT_HLIST_HEAD(&rateest_hash[i]); 187 188 get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); 189 return xt_register_targets(xt_rateest_target, 190 ARRAY_SIZE(xt_rateest_target)); 191} 192 193static void __exit xt_rateest_tg_fini(void) 194{ 195 xt_unregister_targets(xt_rateest_target, ARRAY_SIZE(xt_rateest_target)); 196} 197 198 199MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 200MODULE_LICENSE("GPL"); 201MODULE_DESCRIPTION("Xtables: packet rate estimator"); 202MODULE_ALIAS("ipt_RATEEST"); 203MODULE_ALIAS("ip6t_RATEEST"); 204module_init(xt_rateest_tg_init); 205module_exit(xt_rateest_tg_fini);