blob: 5bf4aa08b0fd081486b79a4746c8210a5f6e4c46 [file] [log] [blame]
Harald Welte9d810fd2005-08-13 13:56:26 -07001/* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
Harald Welte9d810fd2005-08-13 13:56:26 -07003 */
4#include <linux/module.h>
Jiri Slaby1977f032007-10-18 23:40:25 -07005#include <linux/bitops.h>
Harald Welte9d810fd2005-08-13 13:56:26 -07006#include <linux/skbuff.h>
Roman Zippel6f6d6a12008-05-01 04:34:28 -07007#include <linux/math64.h>
Harald Welte2e4e6a12006-01-12 13:30:04 -08008#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter/xt_connbytes.h>
Patrick McHardy587aa642007-03-14 16:37:25 -070010#include <net/netfilter/nf_conntrack.h>
Krzysztof Piotr Oledzki58401572008-07-21 10:01:34 -070011#include <net/netfilter/nf_conntrack_acct.h>
Harald Welte9d810fd2005-08-13 13:56:26 -070012
Harald Welte9d810fd2005-08-13 13:56:26 -070013MODULE_LICENSE("GPL");
14MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
Jan Engelhardt2ae15b62008-01-14 23:42:28 -080015MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
Harald Welte2e4e6a12006-01-12 13:30:04 -080016MODULE_ALIAS("ipt_connbytes");
Jan Engelhardt73aaf932007-10-11 14:36:40 -070017MODULE_ALIAS("ip6t_connbytes");
Harald Welte9d810fd2005-08-13 13:56:26 -070018
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070019static bool
Jan Engelhardtf7108a22008-10-08 11:35:18 +020020connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par)
Harald Welte9d810fd2005-08-13 13:56:26 -070021{
Jan Engelhardtf7108a22008-10-08 11:35:18 +020022 const struct xt_connbytes_info *sinfo = par->matchinfo;
Jan Engelhardta47362a2007-07-07 22:16:55 -070023 const struct nf_conn *ct;
Patrick McHardy587aa642007-03-14 16:37:25 -070024 enum ip_conntrack_info ctinfo;
Harald Welte9d810fd2005-08-13 13:56:26 -070025 u_int64_t what = 0; /* initialize to make gcc happy */
Patrick McHardyfb74a8412007-01-30 14:24:29 -080026 u_int64_t bytes = 0;
27 u_int64_t pkts = 0;
Krzysztof Piotr Oledzki58401572008-07-21 10:01:34 -070028 const struct nf_conn_counter *counters;
Harald Welte9d810fd2005-08-13 13:56:26 -070029
Patrick McHardy587aa642007-03-14 16:37:25 -070030 ct = nf_ct_get(skb, &ctinfo);
31 if (!ct)
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070032 return false;
Krzysztof Piotr Oledzki58401572008-07-21 10:01:34 -070033
34 counters = nf_conn_acct_find(ct);
35 if (!counters)
36 return false;
Harald Welte9d810fd2005-08-13 13:56:26 -070037
38 switch (sinfo->what) {
Harald Welte2e4e6a12006-01-12 13:30:04 -080039 case XT_CONNBYTES_PKTS:
Harald Welte9d810fd2005-08-13 13:56:26 -070040 switch (sinfo->direction) {
Harald Welte2e4e6a12006-01-12 13:30:04 -080041 case XT_CONNBYTES_DIR_ORIGINAL:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080042 what = counters[IP_CT_DIR_ORIGINAL].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070043 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080044 case XT_CONNBYTES_DIR_REPLY:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080045 what = counters[IP_CT_DIR_REPLY].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070046 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080047 case XT_CONNBYTES_DIR_BOTH:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080048 what = counters[IP_CT_DIR_ORIGINAL].packets;
49 what += counters[IP_CT_DIR_REPLY].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070050 break;
51 }
52 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080053 case XT_CONNBYTES_BYTES:
Harald Welte9d810fd2005-08-13 13:56:26 -070054 switch (sinfo->direction) {
Harald Welte2e4e6a12006-01-12 13:30:04 -080055 case XT_CONNBYTES_DIR_ORIGINAL:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080056 what = counters[IP_CT_DIR_ORIGINAL].bytes;
Harald Welte9d810fd2005-08-13 13:56:26 -070057 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080058 case XT_CONNBYTES_DIR_REPLY:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080059 what = counters[IP_CT_DIR_REPLY].bytes;
Harald Welte9d810fd2005-08-13 13:56:26 -070060 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080061 case XT_CONNBYTES_DIR_BOTH:
Yasuyuki Kozakai9fb9cbb2005-11-09 16:38:16 -080062 what = counters[IP_CT_DIR_ORIGINAL].bytes;
63 what += counters[IP_CT_DIR_REPLY].bytes;
Harald Welte9d810fd2005-08-13 13:56:26 -070064 break;
65 }
66 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080067 case XT_CONNBYTES_AVGPKT:
Harald Welte9d810fd2005-08-13 13:56:26 -070068 switch (sinfo->direction) {
Harald Welte2e4e6a12006-01-12 13:30:04 -080069 case XT_CONNBYTES_DIR_ORIGINAL:
Patrick McHardyfb74a8412007-01-30 14:24:29 -080070 bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
71 pkts = counters[IP_CT_DIR_ORIGINAL].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070072 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080073 case XT_CONNBYTES_DIR_REPLY:
Patrick McHardyfb74a8412007-01-30 14:24:29 -080074 bytes = counters[IP_CT_DIR_REPLY].bytes;
75 pkts = counters[IP_CT_DIR_REPLY].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070076 break;
Harald Welte2e4e6a12006-01-12 13:30:04 -080077 case XT_CONNBYTES_DIR_BOTH:
Patrick McHardyfb74a8412007-01-30 14:24:29 -080078 bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
79 counters[IP_CT_DIR_REPLY].bytes;
80 pkts = counters[IP_CT_DIR_ORIGINAL].packets +
81 counters[IP_CT_DIR_REPLY].packets;
Harald Welte9d810fd2005-08-13 13:56:26 -070082 break;
83 }
Patrick McHardyfb74a8412007-01-30 14:24:29 -080084 if (pkts != 0)
Roman Zippel6f6d6a12008-05-01 04:34:28 -070085 what = div64_u64(bytes, pkts);
Harald Welte9d810fd2005-08-13 13:56:26 -070086 break;
87 }
88
89 if (sinfo->count.to)
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -070090 return what <= sinfo->count.to && what >= sinfo->count.from;
Harald Welte9d810fd2005-08-13 13:56:26 -070091 else
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -070092 return what >= sinfo->count.from;
Harald Welte9d810fd2005-08-13 13:56:26 -070093}
94
Jan Engelhardt9b4fce72008-10-08 11:35:18 +020095static bool connbytes_mt_check(const struct xt_mtchk_param *par)
Harald Welte9d810fd2005-08-13 13:56:26 -070096{
Jan Engelhardt9b4fce72008-10-08 11:35:18 +020097 const struct xt_connbytes_info *sinfo = par->matchinfo;
Harald Welte9d810fd2005-08-13 13:56:26 -070098
Harald Welte2e4e6a12006-01-12 13:30:04 -080099 if (sinfo->what != XT_CONNBYTES_PKTS &&
100 sinfo->what != XT_CONNBYTES_BYTES &&
101 sinfo->what != XT_CONNBYTES_AVGPKT)
Jan Engelhardtccb79bd2007-07-07 22:16:00 -0700102 return false;
Harald Welte9d810fd2005-08-13 13:56:26 -0700103
Harald Welte2e4e6a12006-01-12 13:30:04 -0800104 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
105 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
106 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
Jan Engelhardtccb79bd2007-07-07 22:16:00 -0700107 return false;
Harald Welte9d810fd2005-08-13 13:56:26 -0700108
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200109 if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
Yasuyuki Kozakai11078c32006-12-12 00:29:02 -0800110 printk(KERN_WARNING "can't load conntrack support for "
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200111 "proto=%u\n", par->match->family);
Jan Engelhardtccb79bd2007-07-07 22:16:00 -0700112 return false;
Yasuyuki Kozakai11078c32006-12-12 00:29:02 -0800113 }
114
Jan Engelhardtccb79bd2007-07-07 22:16:00 -0700115 return true;
Harald Welte9d810fd2005-08-13 13:56:26 -0700116}
117
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200118static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
Yasuyuki Kozakai11078c32006-12-12 00:29:02 -0800119{
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200120 nf_ct_l3proto_module_put(par->match->family);
Yasuyuki Kozakai11078c32006-12-12 00:29:02 -0800121}
122
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800123static struct xt_match connbytes_mt_reg[] __read_mostly = {
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700124 {
125 .name = "connbytes",
Jan Engelhardtee999d82008-10-08 11:35:01 +0200126 .family = NFPROTO_IPV4,
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800127 .checkentry = connbytes_mt_check,
128 .match = connbytes_mt,
129 .destroy = connbytes_mt_destroy,
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700130 .matchsize = sizeof(struct xt_connbytes_info),
131 .me = THIS_MODULE
132 },
133 {
134 .name = "connbytes",
Jan Engelhardtee999d82008-10-08 11:35:01 +0200135 .family = NFPROTO_IPV6,
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800136 .checkentry = connbytes_mt_check,
137 .match = connbytes_mt,
138 .destroy = connbytes_mt_destroy,
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700139 .matchsize = sizeof(struct xt_connbytes_info),
140 .me = THIS_MODULE
141 },
Harald Welte9d810fd2005-08-13 13:56:26 -0700142};
143
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800144static int __init connbytes_mt_init(void)
Harald Welte9d810fd2005-08-13 13:56:26 -0700145{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800146 return xt_register_matches(connbytes_mt_reg,
147 ARRAY_SIZE(connbytes_mt_reg));
Harald Welte9d810fd2005-08-13 13:56:26 -0700148}
149
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800150static void __exit connbytes_mt_exit(void)
Harald Welte9d810fd2005-08-13 13:56:26 -0700151{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800152 xt_unregister_matches(connbytes_mt_reg, ARRAY_SIZE(connbytes_mt_reg));
Harald Welte9d810fd2005-08-13 13:56:26 -0700153}
154
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800155module_init(connbytes_mt_init);
156module_exit(connbytes_mt_exit);