1 /* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
4 #include <linux/module.h>
5 #include <linux/bitops.h>
6 #include <linux/skbuff.h>
7 #include <linux/math64.h>
8 #include <linux/netfilter/x_tables.h>
9 #include <linux/netfilter/xt_connbytes.h>
10 #include <net/netfilter/nf_conntrack.h>
12 MODULE_LICENSE("GPL");
13 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
14 MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
15 MODULE_ALIAS("ipt_connbytes");
16 MODULE_ALIAS("ip6t_connbytes");
19 connbytes_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
,
24 const struct xt_connbytes_info
*sinfo
= matchinfo
;
25 const struct nf_conn
*ct
;
26 enum ip_conntrack_info ctinfo
;
27 u_int64_t what
= 0; /* initialize to make gcc happy */
30 const struct ip_conntrack_counter
*counters
;
32 ct
= nf_ct_get(skb
, &ctinfo
);
35 counters
= ct
->counters
;
37 switch (sinfo
->what
) {
38 case XT_CONNBYTES_PKTS
:
39 switch (sinfo
->direction
) {
40 case XT_CONNBYTES_DIR_ORIGINAL
:
41 what
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
43 case XT_CONNBYTES_DIR_REPLY
:
44 what
= counters
[IP_CT_DIR_REPLY
].packets
;
46 case XT_CONNBYTES_DIR_BOTH
:
47 what
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
48 what
+= counters
[IP_CT_DIR_REPLY
].packets
;
52 case XT_CONNBYTES_BYTES
:
53 switch (sinfo
->direction
) {
54 case XT_CONNBYTES_DIR_ORIGINAL
:
55 what
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
57 case XT_CONNBYTES_DIR_REPLY
:
58 what
= counters
[IP_CT_DIR_REPLY
].bytes
;
60 case XT_CONNBYTES_DIR_BOTH
:
61 what
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
62 what
+= counters
[IP_CT_DIR_REPLY
].bytes
;
66 case XT_CONNBYTES_AVGPKT
:
67 switch (sinfo
->direction
) {
68 case XT_CONNBYTES_DIR_ORIGINAL
:
69 bytes
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
70 pkts
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
72 case XT_CONNBYTES_DIR_REPLY
:
73 bytes
= counters
[IP_CT_DIR_REPLY
].bytes
;
74 pkts
= counters
[IP_CT_DIR_REPLY
].packets
;
76 case XT_CONNBYTES_DIR_BOTH
:
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
;
84 what
= div64_u64(bytes
, pkts
);
89 return what
<= sinfo
->count
.to
&& what
>= sinfo
->count
.from
;
91 return what
>= sinfo
->count
.from
;
95 connbytes_mt_check(const char *tablename
, const void *ip
,
96 const struct xt_match
*match
, void *matchinfo
,
97 unsigned int hook_mask
)
99 const struct xt_connbytes_info
*sinfo
= matchinfo
;
101 if (sinfo
->what
!= XT_CONNBYTES_PKTS
&&
102 sinfo
->what
!= XT_CONNBYTES_BYTES
&&
103 sinfo
->what
!= XT_CONNBYTES_AVGPKT
)
106 if (sinfo
->direction
!= XT_CONNBYTES_DIR_ORIGINAL
&&
107 sinfo
->direction
!= XT_CONNBYTES_DIR_REPLY
&&
108 sinfo
->direction
!= XT_CONNBYTES_DIR_BOTH
)
111 if (nf_ct_l3proto_try_module_get(match
->family
) < 0) {
112 printk(KERN_WARNING
"can't load conntrack support for "
113 "proto=%u\n", match
->family
);
121 connbytes_mt_destroy(const struct xt_match
*match
, void *matchinfo
)
123 nf_ct_l3proto_module_put(match
->family
);
126 static struct xt_match connbytes_mt_reg
[] __read_mostly
= {
130 .checkentry
= connbytes_mt_check
,
131 .match
= connbytes_mt
,
132 .destroy
= connbytes_mt_destroy
,
133 .matchsize
= sizeof(struct xt_connbytes_info
),
139 .checkentry
= connbytes_mt_check
,
140 .match
= connbytes_mt
,
141 .destroy
= connbytes_mt_destroy
,
142 .matchsize
= sizeof(struct xt_connbytes_info
),
147 static int __init
connbytes_mt_init(void)
149 return xt_register_matches(connbytes_mt_reg
,
150 ARRAY_SIZE(connbytes_mt_reg
));
153 static void __exit
connbytes_mt_exit(void)
155 xt_unregister_matches(connbytes_mt_reg
, ARRAY_SIZE(connbytes_mt_reg
));
158 module_init(connbytes_mt_init
);
159 module_exit(connbytes_mt_exit
);