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