1 /* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
4 * 2004-07-20 Harald Welte <laforge@netfilter.org>
5 * - reimplemented to use per-connection accounting counters
6 * - add functionality to match number of packets
7 * - add functionality to match average packet size
8 * - add support to match directions seperately
9 * 2005-10-16 Harald Welte <laforge@netfilter.org>
13 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 #include <net/netfilter/nf_conntrack_compat.h>
16 #include <linux/netfilter/x_tables.h>
17 #include <linux/netfilter/xt_connbytes.h>
19 #include <asm/div64.h>
20 #include <asm/bitops.h>
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
24 MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
25 MODULE_ALIAS("ipt_connbytes");
28 match(const struct sk_buff
*skb
,
29 const struct net_device
*in
,
30 const struct net_device
*out
,
31 const struct xt_match
*match
,
32 const void *matchinfo
,
37 const struct xt_connbytes_info
*sinfo
= matchinfo
;
38 u_int64_t what
= 0; /* initialize to make gcc happy */
41 const struct ip_conntrack_counter
*counters
;
43 if (!(counters
= nf_ct_get_counters(skb
)))
44 return 0; /* no match */
46 switch (sinfo
->what
) {
47 case XT_CONNBYTES_PKTS
:
48 switch (sinfo
->direction
) {
49 case XT_CONNBYTES_DIR_ORIGINAL
:
50 what
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
52 case XT_CONNBYTES_DIR_REPLY
:
53 what
= counters
[IP_CT_DIR_REPLY
].packets
;
55 case XT_CONNBYTES_DIR_BOTH
:
56 what
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
57 what
+= counters
[IP_CT_DIR_REPLY
].packets
;
61 case XT_CONNBYTES_BYTES
:
62 switch (sinfo
->direction
) {
63 case XT_CONNBYTES_DIR_ORIGINAL
:
64 what
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
66 case XT_CONNBYTES_DIR_REPLY
:
67 what
= counters
[IP_CT_DIR_REPLY
].bytes
;
69 case XT_CONNBYTES_DIR_BOTH
:
70 what
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
71 what
+= counters
[IP_CT_DIR_REPLY
].bytes
;
75 case XT_CONNBYTES_AVGPKT
:
76 switch (sinfo
->direction
) {
77 case XT_CONNBYTES_DIR_ORIGINAL
:
78 bytes
= counters
[IP_CT_DIR_ORIGINAL
].bytes
;
79 pkts
= counters
[IP_CT_DIR_ORIGINAL
].packets
;
81 case XT_CONNBYTES_DIR_REPLY
:
82 bytes
= counters
[IP_CT_DIR_REPLY
].bytes
;
83 pkts
= counters
[IP_CT_DIR_REPLY
].packets
;
85 case XT_CONNBYTES_DIR_BOTH
:
86 bytes
= counters
[IP_CT_DIR_ORIGINAL
].bytes
+
87 counters
[IP_CT_DIR_REPLY
].bytes
;
88 pkts
= counters
[IP_CT_DIR_ORIGINAL
].packets
+
89 counters
[IP_CT_DIR_REPLY
].packets
;
93 what
= div64_64(bytes
, pkts
);
98 return (what
<= sinfo
->count
.to
&& what
>= sinfo
->count
.from
);
100 return (what
>= sinfo
->count
.from
);
103 static int check(const char *tablename
,
105 const struct xt_match
*match
,
107 unsigned int hook_mask
)
109 const struct xt_connbytes_info
*sinfo
= matchinfo
;
111 if (sinfo
->what
!= XT_CONNBYTES_PKTS
&&
112 sinfo
->what
!= XT_CONNBYTES_BYTES
&&
113 sinfo
->what
!= XT_CONNBYTES_AVGPKT
)
116 if (sinfo
->direction
!= XT_CONNBYTES_DIR_ORIGINAL
&&
117 sinfo
->direction
!= XT_CONNBYTES_DIR_REPLY
&&
118 sinfo
->direction
!= XT_CONNBYTES_DIR_BOTH
)
121 if (nf_ct_l3proto_try_module_get(match
->family
) < 0) {
122 printk(KERN_WARNING
"can't load conntrack support for "
123 "proto=%d\n", match
->family
);
131 destroy(const struct xt_match
*match
, void *matchinfo
)
133 nf_ct_l3proto_module_put(match
->family
);
136 static struct xt_match xt_connbytes_match
[] = {
143 .matchsize
= sizeof(struct xt_connbytes_info
),
152 .matchsize
= sizeof(struct xt_connbytes_info
),
157 static int __init
xt_connbytes_init(void)
159 return xt_register_matches(xt_connbytes_match
,
160 ARRAY_SIZE(xt_connbytes_match
));
163 static void __exit
xt_connbytes_fini(void)
165 xt_unregister_matches(xt_connbytes_match
,
166 ARRAY_SIZE(xt_connbytes_match
));
169 module_init(xt_connbytes_init
);
170 module_exit(xt_connbytes_fini
);