Blame view

net/netfilter/xt_connbytes.c 4.4 KB
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
1
2
  /* Kernel module to match connection tracking byte counter.
   * GPL (C) 2002 Martin Devera (devik@cdi.cz).
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
3
   */
8bee4bad0   Jan Engelhardt   netfilter: xt ext...
4
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
5
  #include <linux/module.h>
1977f0327   Jiri Slaby   remove asm/bitops...
6
  #include <linux/bitops.h>
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
7
  #include <linux/skbuff.h>
6f6d6a1a6   Roman Zippel   rename div64_64 t...
8
  #include <linux/math64.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
9
10
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_connbytes.h>
587aa6416   Patrick McHardy   [NETFILTER]: Remo...
11
  #include <net/netfilter/nf_conntrack.h>
584015727   Krzysztof Piotr Oledzki   netfilter: accoun...
12
  #include <net/netfilter/nf_conntrack_acct.h>
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
13

9d810fd2d   Harald Welte   [NETFILTER]: Add ...
14
15
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2ae15b64e   Jan Engelhardt   [NETFILTER]: Upda...
16
  MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
17
  MODULE_ALIAS("ipt_connbytes");
73aaf9355   Jan Engelhardt   [NETFILTER]: x_ta...
18
  MODULE_ALIAS("ip6t_connbytes");
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
19

1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
20
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
21
  connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
22
  {
f7108a20d   Jan Engelhardt   netfilter: xtable...
23
  	const struct xt_connbytes_info *sinfo = par->matchinfo;
a47362a22   Jan Engelhardt   [NETFILTER]: add ...
24
  	const struct nf_conn *ct;
587aa6416   Patrick McHardy   [NETFILTER]: Remo...
25
  	enum ip_conntrack_info ctinfo;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
26
  	u_int64_t what = 0;	/* initialize to make gcc happy */
fb74a8416   Patrick McHardy   [NETFILTER]: xt_c...
27
28
  	u_int64_t bytes = 0;
  	u_int64_t pkts = 0;
584015727   Krzysztof Piotr Oledzki   netfilter: accoun...
29
  	const struct nf_conn_counter *counters;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
30

587aa6416   Patrick McHardy   [NETFILTER]: Remo...
31
32
  	ct = nf_ct_get(skb, &ctinfo);
  	if (!ct)
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
33
  		return false;
584015727   Krzysztof Piotr Oledzki   netfilter: accoun...
34
35
36
37
  
  	counters = nf_conn_acct_find(ct);
  	if (!counters)
  		return false;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
38
39
  
  	switch (sinfo->what) {
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
40
  	case XT_CONNBYTES_PKTS:
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
41
  		switch (sinfo->direction) {
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
42
  		case XT_CONNBYTES_DIR_ORIGINAL:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
43
  			what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
44
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
45
  		case XT_CONNBYTES_DIR_REPLY:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
46
  			what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
47
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
48
  		case XT_CONNBYTES_DIR_BOTH:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
49
50
  			what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
  			what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
51
52
53
  			break;
  		}
  		break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
54
  	case XT_CONNBYTES_BYTES:
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
55
  		switch (sinfo->direction) {
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
56
  		case XT_CONNBYTES_DIR_ORIGINAL:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
57
  			what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
58
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
59
  		case XT_CONNBYTES_DIR_REPLY:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
60
  			what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
61
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
62
  		case XT_CONNBYTES_DIR_BOTH:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
63
64
  			what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
  			what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
65
66
67
  			break;
  		}
  		break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
68
  	case XT_CONNBYTES_AVGPKT:
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
69
  		switch (sinfo->direction) {
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
70
  		case XT_CONNBYTES_DIR_ORIGINAL:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
71
72
  			bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
  			pkts  = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
73
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
74
  		case XT_CONNBYTES_DIR_REPLY:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
75
76
  			bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
  			pkts  = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
77
  			break;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
78
  		case XT_CONNBYTES_DIR_BOTH:
b3e0bfa71   Eric Dumazet   netfilter: nf_con...
79
80
81
82
  			bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +
  				atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
  			pkts  = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +
  				atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
83
84
  			break;
  		}
fb74a8416   Patrick McHardy   [NETFILTER]: xt_c...
85
  		if (pkts != 0)
6f6d6a1a6   Roman Zippel   rename div64_64 t...
86
  			what = div64_u64(bytes, pkts);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
87
88
  		break;
  	}
0354b48f6   Florian Westphal   netfilter: xt_con...
89
  	if (sinfo->count.to >= sinfo->count.from)
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
90
  		return what <= sinfo->count.to && what >= sinfo->count.from;
0354b48f6   Florian Westphal   netfilter: xt_con...
91
92
  	else /* inverted */
  		return what < sinfo->count.to || what > sinfo->count.from;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
93
  }
b0f38452f   Jan Engelhardt   netfilter: xtable...
94
  static int connbytes_mt_check(const struct xt_mtchk_param *par)
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
95
  {
9b4fce7a3   Jan Engelhardt   netfilter: xtable...
96
  	const struct xt_connbytes_info *sinfo = par->matchinfo;
4a5a5c73b   Jan Engelhardt   netfilter: xtable...
97
  	int ret;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
98

2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
99
100
101
  	if (sinfo->what != XT_CONNBYTES_PKTS &&
  	    sinfo->what != XT_CONNBYTES_BYTES &&
  	    sinfo->what != XT_CONNBYTES_AVGPKT)
bd414ee60   Jan Engelhardt   netfilter: xtable...
102
  		return -EINVAL;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
103

2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
104
105
106
  	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
  	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
  	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
bd414ee60   Jan Engelhardt   netfilter: xtable...
107
  		return -EINVAL;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
108

4a5a5c73b   Jan Engelhardt   netfilter: xtable...
109
  	ret = nf_ct_l3proto_try_module_get(par->family);
f95c74e33   Jan Engelhardt   netfilter: xtable...
110
  	if (ret < 0)
8bee4bad0   Jan Engelhardt   netfilter: xt ext...
111
112
113
  		pr_info("cannot load conntrack support for proto=%u
  ",
  			par->family);
a8756201b   Tim Gardner   netfilter: xt_con...
114
115
116
117
118
119
120
121
122
123
  
  	/*
  	 * This filter cannot function correctly unless connection tracking
  	 * accounting is enabled, so complain in the hope that someone notices.
  	 */
  	if (!nf_ct_acct_enabled(par->net)) {
  		pr_warning("Forcing CT accounting to be enabled
  ");
  		nf_ct_set_acct(par->net, true);
  	}
f95c74e33   Jan Engelhardt   netfilter: xtable...
124
  	return ret;
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
125
  }
6be3d8598   Jan Engelhardt   netfilter: xtable...
126
  static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
11078c371   Yasuyuki Kozakai   [NETFILTER]: x_ta...
127
  {
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
128
  	nf_ct_l3proto_module_put(par->family);
11078c371   Yasuyuki Kozakai   [NETFILTER]: x_ta...
129
  }
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
130
131
132
133
134
135
136
137
138
  static struct xt_match connbytes_mt_reg __read_mostly = {
  	.name       = "connbytes",
  	.revision   = 0,
  	.family     = NFPROTO_UNSPEC,
  	.checkentry = connbytes_mt_check,
  	.match      = connbytes_mt,
  	.destroy    = connbytes_mt_destroy,
  	.matchsize  = sizeof(struct xt_connbytes_info),
  	.me         = THIS_MODULE,
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
139
  };
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
140
  static int __init connbytes_mt_init(void)
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
141
  {
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
142
  	return xt_register_match(&connbytes_mt_reg);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
143
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
144
  static void __exit connbytes_mt_exit(void)
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
145
  {
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
146
  	xt_unregister_match(&connbytes_mt_reg);
9d810fd2d   Harald Welte   [NETFILTER]: Add ...
147
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
148
149
  module_init(connbytes_mt_init);
  module_exit(connbytes_mt_exit);