Blame view
net/netfilter/xt_connbytes.c
4.47 KB
9d810fd2d
|
1 2 |
/* Kernel module to match connection tracking byte counter. * GPL (C) 2002 Martin Devera (devik@cdi.cz). |
9d810fd2d
|
3 |
*/ |
8bee4bad0
|
4 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9d810fd2d
|
5 |
#include <linux/module.h> |
1977f0327
|
6 |
#include <linux/bitops.h> |
9d810fd2d
|
7 |
#include <linux/skbuff.h> |
6f6d6a1a6
|
8 |
#include <linux/math64.h> |
2e4e6a17a
|
9 10 |
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_connbytes.h> |
587aa6416
|
11 |
#include <net/netfilter/nf_conntrack.h> |
584015727
|
12 |
#include <net/netfilter/nf_conntrack_acct.h> |
9d810fd2d
|
13 |
|
9d810fd2d
|
14 15 |
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
2ae15b64e
|
16 |
MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching"); |
2e4e6a17a
|
17 |
MODULE_ALIAS("ipt_connbytes"); |
73aaf9355
|
18 |
MODULE_ALIAS("ip6t_connbytes"); |
9d810fd2d
|
19 |
|
1d93a9cba
|
20 |
static bool |
62fc80510
|
21 |
connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par) |
9d810fd2d
|
22 |
{ |
f7108a20d
|
23 |
const struct xt_connbytes_info *sinfo = par->matchinfo; |
a47362a22
|
24 |
const struct nf_conn *ct; |
587aa6416
|
25 |
enum ip_conntrack_info ctinfo; |
9d810fd2d
|
26 |
u_int64_t what = 0; /* initialize to make gcc happy */ |
fb74a8416
|
27 28 |
u_int64_t bytes = 0; u_int64_t pkts = 0; |
f7b13e433
|
29 |
const struct nf_conn_acct *acct; |
584015727
|
30 |
const struct nf_conn_counter *counters; |
9d810fd2d
|
31 |
|
587aa6416
|
32 33 |
ct = nf_ct_get(skb, &ctinfo); if (!ct) |
1d93a9cba
|
34 |
return false; |
584015727
|
35 |
|
f7b13e433
|
36 37 |
acct = nf_conn_acct_find(ct); if (!acct) |
584015727
|
38 |
return false; |
9d810fd2d
|
39 |
|
f7b13e433
|
40 |
counters = acct->counter; |
9d810fd2d
|
41 |
switch (sinfo->what) { |
2e4e6a17a
|
42 |
case XT_CONNBYTES_PKTS: |
9d810fd2d
|
43 |
switch (sinfo->direction) { |
2e4e6a17a
|
44 |
case XT_CONNBYTES_DIR_ORIGINAL: |
b3e0bfa71
|
45 |
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); |
9d810fd2d
|
46 |
break; |
2e4e6a17a
|
47 |
case XT_CONNBYTES_DIR_REPLY: |
b3e0bfa71
|
48 |
what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
9d810fd2d
|
49 |
break; |
2e4e6a17a
|
50 |
case XT_CONNBYTES_DIR_BOTH: |
b3e0bfa71
|
51 52 |
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
9d810fd2d
|
53 54 55 |
break; } break; |
2e4e6a17a
|
56 |
case XT_CONNBYTES_BYTES: |
9d810fd2d
|
57 |
switch (sinfo->direction) { |
2e4e6a17a
|
58 |
case XT_CONNBYTES_DIR_ORIGINAL: |
b3e0bfa71
|
59 |
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); |
9d810fd2d
|
60 |
break; |
2e4e6a17a
|
61 |
case XT_CONNBYTES_DIR_REPLY: |
b3e0bfa71
|
62 |
what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
9d810fd2d
|
63 |
break; |
2e4e6a17a
|
64 |
case XT_CONNBYTES_DIR_BOTH: |
b3e0bfa71
|
65 66 |
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
9d810fd2d
|
67 68 69 |
break; } break; |
2e4e6a17a
|
70 |
case XT_CONNBYTES_AVGPKT: |
9d810fd2d
|
71 |
switch (sinfo->direction) { |
2e4e6a17a
|
72 |
case XT_CONNBYTES_DIR_ORIGINAL: |
b3e0bfa71
|
73 74 |
bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); |
9d810fd2d
|
75 |
break; |
2e4e6a17a
|
76 |
case XT_CONNBYTES_DIR_REPLY: |
b3e0bfa71
|
77 78 |
bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
9d810fd2d
|
79 |
break; |
2e4e6a17a
|
80 |
case XT_CONNBYTES_DIR_BOTH: |
b3e0bfa71
|
81 82 83 84 |
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
|
85 86 |
break; } |
fb74a8416
|
87 |
if (pkts != 0) |
6f6d6a1a6
|
88 |
what = div64_u64(bytes, pkts); |
9d810fd2d
|
89 90 |
break; } |
0354b48f6
|
91 |
if (sinfo->count.to >= sinfo->count.from) |
7c4e36bc1
|
92 |
return what <= sinfo->count.to && what >= sinfo->count.from; |
0354b48f6
|
93 94 |
else /* inverted */ return what < sinfo->count.to || what > sinfo->count.from; |
9d810fd2d
|
95 |
} |
b0f38452f
|
96 |
static int connbytes_mt_check(const struct xt_mtchk_param *par) |
9d810fd2d
|
97 |
{ |
9b4fce7a3
|
98 |
const struct xt_connbytes_info *sinfo = par->matchinfo; |
4a5a5c73b
|
99 |
int ret; |
9d810fd2d
|
100 |
|
2e4e6a17a
|
101 102 103 |
if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) |
bd414ee60
|
104 |
return -EINVAL; |
9d810fd2d
|
105 |
|
2e4e6a17a
|
106 107 108 |
if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) |
bd414ee60
|
109 |
return -EINVAL; |
9d810fd2d
|
110 |
|
ecb2421b5
|
111 |
ret = nf_ct_netns_get(par->net, par->family); |
f95c74e33
|
112 |
if (ret < 0) |
b26066447
|
113 114 115 |
pr_info_ratelimited("cannot load conntrack support for proto=%u ", par->family); |
a8756201b
|
116 117 118 119 120 121 |
/* * 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)) { |
b167a37c7
|
122 123 |
pr_warn("Forcing CT accounting to be enabled "); |
a8756201b
|
124 125 |
nf_ct_set_acct(par->net, true); } |
f95c74e33
|
126 |
return ret; |
9d810fd2d
|
127 |
} |
6be3d8598
|
128 |
static void connbytes_mt_destroy(const struct xt_mtdtor_param *par) |
11078c371
|
129 |
{ |
ecb2421b5
|
130 |
nf_ct_netns_put(par->net, par->family); |
11078c371
|
131 |
} |
92f3b2b1b
|
132 133 134 135 136 137 138 139 140 |
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
|
141 |
}; |
d3c5ee6d5
|
142 |
static int __init connbytes_mt_init(void) |
9d810fd2d
|
143 |
{ |
92f3b2b1b
|
144 |
return xt_register_match(&connbytes_mt_reg); |
9d810fd2d
|
145 |
} |
d3c5ee6d5
|
146 |
static void __exit connbytes_mt_exit(void) |
9d810fd2d
|
147 |
{ |
92f3b2b1b
|
148 |
xt_unregister_match(&connbytes_mt_reg); |
9d810fd2d
|
149 |
} |
d3c5ee6d5
|
150 151 |
module_init(connbytes_mt_init); module_exit(connbytes_mt_exit); |