Blame view

net/netfilter/xt_rateest.c 3.7 KB
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * (C) 2007 Patrick McHardy <kaber@trash.net>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/gen_stats.h>
  
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_rateest.h>
  #include <net/netfilter/xt_rateest.h>
f7108a20d   Jan Engelhardt   netfilter: xtable...
15
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
16
  xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par)
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
17
  {
f7108a20d   Jan Engelhardt   netfilter: xtable...
18
  	const struct xt_rateest_match_info *info = par->matchinfo;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  	struct gnet_stats_rate_est *r;
  	u_int32_t bps1, bps2, pps1, pps2;
  	bool ret = true;
  
  	spin_lock_bh(&info->est1->lock);
  	r = &info->est1->rstats;
  	if (info->flags & XT_RATEEST_MATCH_DELTA) {
  		bps1 = info->bps1 >= r->bps ? info->bps1 - r->bps : 0;
  		pps1 = info->pps1 >= r->pps ? info->pps1 - r->pps : 0;
  	} else {
  		bps1 = r->bps;
  		pps1 = r->pps;
  	}
  	spin_unlock_bh(&info->est1->lock);
  
  	if (info->flags & XT_RATEEST_MATCH_ABS) {
  		bps2 = info->bps2;
  		pps2 = info->pps2;
  	} else {
  		spin_lock_bh(&info->est2->lock);
  		r = &info->est2->rstats;
  		if (info->flags & XT_RATEEST_MATCH_DELTA) {
  			bps2 = info->bps2 >= r->bps ? info->bps2 - r->bps : 0;
  			pps2 = info->pps2 >= r->pps ? info->pps2 - r->pps : 0;
  		} else {
  			bps2 = r->bps;
  			pps2 = r->pps;
  		}
  		spin_unlock_bh(&info->est2->lock);
  	}
  
  	switch (info->mode) {
  	case XT_RATEEST_MATCH_LT:
  		if (info->flags & XT_RATEEST_MATCH_BPS)
  			ret &= bps1 < bps2;
  		if (info->flags & XT_RATEEST_MATCH_PPS)
  			ret &= pps1 < pps2;
  		break;
  	case XT_RATEEST_MATCH_GT:
  		if (info->flags & XT_RATEEST_MATCH_BPS)
  			ret &= bps1 > bps2;
  		if (info->flags & XT_RATEEST_MATCH_PPS)
  			ret &= pps1 > pps2;
  		break;
  	case XT_RATEEST_MATCH_EQ:
  		if (info->flags & XT_RATEEST_MATCH_BPS)
  			ret &= bps1 == bps2;
  		if (info->flags & XT_RATEEST_MATCH_PPS)
4d900f9df   Patrick McHardy   netfilter: xt_rat...
67
  			ret &= pps1 == pps2;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
68
69
70
71
72
73
  		break;
  	}
  
  	ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false;
  	return ret;
  }
b0f38452f   Jan Engelhardt   netfilter: xtable...
74
  static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
75
  {
9b4fce7a3   Jan Engelhardt   netfilter: xtable...
76
  	struct xt_rateest_match_info *info = par->matchinfo;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
77
  	struct xt_rateest *est1, *est2;
00fe1ae91   Eric Dumazet   netfilter: xt_rat...
78
  	int ret = -EINVAL;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  
  	if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
  				     XT_RATEEST_MATCH_REL)) != 1)
  		goto err1;
  
  	if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS)))
  		goto err1;
  
  	switch (info->mode) {
  	case XT_RATEEST_MATCH_EQ:
  	case XT_RATEEST_MATCH_LT:
  	case XT_RATEEST_MATCH_GT:
  		break;
  	default:
  		goto err1;
  	}
4a5a5c73b   Jan Engelhardt   netfilter: xtable...
95
  	ret  = -ENOENT;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
96
97
98
  	est1 = xt_rateest_lookup(info->name1);
  	if (!est1)
  		goto err1;
00fe1ae91   Eric Dumazet   netfilter: xt_rat...
99
  	est2 = NULL;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
100
101
102
103
  	if (info->flags & XT_RATEEST_MATCH_REL) {
  		est2 = xt_rateest_lookup(info->name2);
  		if (!est2)
  			goto err2;
00fe1ae91   Eric Dumazet   netfilter: xt_rat...
104
  	}
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
105
106
107
  
  	info->est1 = est1;
  	info->est2 = est2;
bd414ee60   Jan Engelhardt   netfilter: xtable...
108
  	return 0;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
109
110
111
112
  
  err2:
  	xt_rateest_put(est1);
  err1:
00fe1ae91   Eric Dumazet   netfilter: xt_rat...
113
  	return ret;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
114
  }
6be3d8598   Jan Engelhardt   netfilter: xtable...
115
  static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par)
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
116
  {
6be3d8598   Jan Engelhardt   netfilter: xtable...
117
  	struct xt_rateest_match_info *info = par->matchinfo;
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
118
119
120
121
122
  
  	xt_rateest_put(info->est1);
  	if (info->est2)
  		xt_rateest_put(info->est2);
  }
55b69e910   Jan Engelhardt   netfilter: implem...
123
124
125
126
127
128
129
130
131
  static struct xt_match xt_rateest_mt_reg __read_mostly = {
  	.name       = "rateest",
  	.revision   = 0,
  	.family     = NFPROTO_UNSPEC,
  	.match      = xt_rateest_mt,
  	.checkentry = xt_rateest_mt_checkentry,
  	.destroy    = xt_rateest_mt_destroy,
  	.matchsize  = sizeof(struct xt_rateest_match_info),
  	.me         = THIS_MODULE,
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
132
133
134
135
  };
  
  static int __init xt_rateest_mt_init(void)
  {
55b69e910   Jan Engelhardt   netfilter: implem...
136
  	return xt_register_match(&xt_rateest_mt_reg);
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
137
138
139
140
  }
  
  static void __exit xt_rateest_mt_fini(void)
  {
55b69e910   Jan Engelhardt   netfilter: implem...
141
  	xt_unregister_match(&xt_rateest_mt_reg);
50c164a81   Patrick McHardy   [NETFILTER]: x_ta...
142
143
144
145
146
147
148
149
150
  }
  
  MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("xtables rate estimator match");
  MODULE_ALIAS("ipt_rateest");
  MODULE_ALIAS("ip6t_rateest");
  module_init(xt_rateest_mt_init);
  module_exit(xt_rateest_mt_fini);