[NETFILTER]: Remove incorrect inline markers
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / netfilter / xt_connbytes.c
CommitLineData
9d810fd2
HW
1/* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
9d810fd2
HW
3 */
4#include <linux/module.h>
5#include <linux/skbuff.h>
2e4e6a17
HW
6#include <linux/netfilter/x_tables.h>
7#include <linux/netfilter/xt_connbytes.h>
587aa641 8#include <net/netfilter/nf_conntrack.h>
9d810fd2
HW
9
10#include <asm/div64.h>
11#include <asm/bitops.h>
12
13MODULE_LICENSE("GPL");
14MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
15MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
2e4e6a17 16MODULE_ALIAS("ipt_connbytes");
9d810fd2 17
1d93a9cb 18static bool
9d810fd2
HW
19match(const struct sk_buff *skb,
20 const struct net_device *in,
21 const struct net_device *out,
c4986734 22 const struct xt_match *match,
9d810fd2
HW
23 const void *matchinfo,
24 int offset,
2e4e6a17 25 unsigned int protoff,
cff533ac 26 bool *hotdrop)
9d810fd2 27{
2e4e6a17 28 const struct xt_connbytes_info *sinfo = matchinfo;
a47362a2 29 const struct nf_conn *ct;
587aa641 30 enum ip_conntrack_info ctinfo;
9d810fd2 31 u_int64_t what = 0; /* initialize to make gcc happy */
fb74a841
PM
32 u_int64_t bytes = 0;
33 u_int64_t pkts = 0;
9fb9cbb1 34 const struct ip_conntrack_counter *counters;
9d810fd2 35
587aa641
PM
36 ct = nf_ct_get(skb, &ctinfo);
37 if (!ct)
1d93a9cb 38 return false;
587aa641 39 counters = ct->counters;
9d810fd2
HW
40
41 switch (sinfo->what) {
2e4e6a17 42 case XT_CONNBYTES_PKTS:
9d810fd2 43 switch (sinfo->direction) {
2e4e6a17 44 case XT_CONNBYTES_DIR_ORIGINAL:
9fb9cbb1 45 what = counters[IP_CT_DIR_ORIGINAL].packets;
9d810fd2 46 break;
2e4e6a17 47 case XT_CONNBYTES_DIR_REPLY:
9fb9cbb1 48 what = counters[IP_CT_DIR_REPLY].packets;
9d810fd2 49 break;
2e4e6a17 50 case XT_CONNBYTES_DIR_BOTH:
9fb9cbb1
YK
51 what = counters[IP_CT_DIR_ORIGINAL].packets;
52 what += counters[IP_CT_DIR_REPLY].packets;
9d810fd2
HW
53 break;
54 }
55 break;
2e4e6a17 56 case XT_CONNBYTES_BYTES:
9d810fd2 57 switch (sinfo->direction) {
2e4e6a17 58 case XT_CONNBYTES_DIR_ORIGINAL:
9fb9cbb1 59 what = counters[IP_CT_DIR_ORIGINAL].bytes;
9d810fd2 60 break;
2e4e6a17 61 case XT_CONNBYTES_DIR_REPLY:
9fb9cbb1 62 what = counters[IP_CT_DIR_REPLY].bytes;
9d810fd2 63 break;
2e4e6a17 64 case XT_CONNBYTES_DIR_BOTH:
9fb9cbb1
YK
65 what = counters[IP_CT_DIR_ORIGINAL].bytes;
66 what += counters[IP_CT_DIR_REPLY].bytes;
9d810fd2
HW
67 break;
68 }
69 break;
2e4e6a17 70 case XT_CONNBYTES_AVGPKT:
9d810fd2 71 switch (sinfo->direction) {
2e4e6a17 72 case XT_CONNBYTES_DIR_ORIGINAL:
fb74a841
PM
73 bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
74 pkts = counters[IP_CT_DIR_ORIGINAL].packets;
9d810fd2 75 break;
2e4e6a17 76 case XT_CONNBYTES_DIR_REPLY:
fb74a841
PM
77 bytes = counters[IP_CT_DIR_REPLY].bytes;
78 pkts = counters[IP_CT_DIR_REPLY].packets;
9d810fd2 79 break;
2e4e6a17 80 case XT_CONNBYTES_DIR_BOTH:
fb74a841
PM
81 bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
82 counters[IP_CT_DIR_REPLY].bytes;
83 pkts = counters[IP_CT_DIR_ORIGINAL].packets +
84 counters[IP_CT_DIR_REPLY].packets;
9d810fd2
HW
85 break;
86 }
fb74a841
PM
87 if (pkts != 0)
88 what = div64_64(bytes, pkts);
9d810fd2
HW
89 break;
90 }
91
92 if (sinfo->count.to)
93 return (what <= sinfo->count.to && what >= sinfo->count.from);
94 else
95 return (what >= sinfo->count.from);
96}
97
ccb79bdc
JE
98static bool check(const char *tablename,
99 const void *ip,
100 const struct xt_match *match,
101 void *matchinfo,
102 unsigned int hook_mask)
9d810fd2 103{
2e4e6a17 104 const struct xt_connbytes_info *sinfo = matchinfo;
9d810fd2 105
2e4e6a17
HW
106 if (sinfo->what != XT_CONNBYTES_PKTS &&
107 sinfo->what != XT_CONNBYTES_BYTES &&
108 sinfo->what != XT_CONNBYTES_AVGPKT)
ccb79bdc 109 return false;
9d810fd2 110
2e4e6a17
HW
111 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
112 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
113 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
ccb79bdc 114 return false;
9d810fd2 115
11078c37
YK
116 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
117 printk(KERN_WARNING "can't load conntrack support for "
118 "proto=%d\n", match->family);
ccb79bdc 119 return false;
11078c37
YK
120 }
121
ccb79bdc 122 return true;
9d810fd2
HW
123}
124
11078c37
YK
125static void
126destroy(const struct xt_match *match, void *matchinfo)
127{
128 nf_ct_l3proto_module_put(match->family);
129}
130
fe1cb108 131static struct xt_match xt_connbytes_match[] = {
4470bbc7
PM
132 {
133 .name = "connbytes",
134 .family = AF_INET,
135 .checkentry = check,
136 .match = match,
11078c37 137 .destroy = destroy,
4470bbc7
PM
138 .matchsize = sizeof(struct xt_connbytes_info),
139 .me = THIS_MODULE
140 },
141 {
142 .name = "connbytes",
143 .family = AF_INET6,
144 .checkentry = check,
145 .match = match,
11078c37 146 .destroy = destroy,
4470bbc7
PM
147 .matchsize = sizeof(struct xt_connbytes_info),
148 .me = THIS_MODULE
149 },
9d810fd2
HW
150};
151
65b4b4e8 152static int __init xt_connbytes_init(void)
9d810fd2 153{
4470bbc7
PM
154 return xt_register_matches(xt_connbytes_match,
155 ARRAY_SIZE(xt_connbytes_match));
9d810fd2
HW
156}
157
65b4b4e8 158static void __exit xt_connbytes_fini(void)
9d810fd2 159{
4470bbc7
PM
160 xt_unregister_matches(xt_connbytes_match,
161 ARRAY_SIZE(xt_connbytes_match));
9d810fd2
HW
162}
163
65b4b4e8
AM
164module_init(xt_connbytes_init);
165module_exit(xt_connbytes_fini);