1 /* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5 #include <linux/module.h>
6 #include <linux/bitops.h>
7 #include <linux/skbuff.h>
8 #include <linux/math64.h>
9 #include <linux/netfilter/x_tables.h>
10 #include <linux/netfilter/xt_connbytes.h>
11 #include <net/netfilter/nf_conntrack.h>
12 #include <net/netfilter/nf_conntrack_acct.h>
14 MODULE_LICENSE("GPL");
15 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
16 MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
17 MODULE_ALIAS("ipt_connbytes");
18 MODULE_ALIAS("ip6t_connbytes");
21 connbytes_mt(const struct sk_buff
*skb
, struct xt_action_param
*par
)
23 const struct xt_connbytes_info
*sinfo
= par
->matchinfo
;
24 const struct nf_conn
*ct
;
25 enum ip_conntrack_info ctinfo
;
26 u_int64_t what
= 0; /* initialize to make gcc happy */
29 const struct nf_conn_acct
*acct
;
30 const struct nf_conn_counter
*counters
;
32 ct
= nf_ct_get(skb
, &ctinfo
);
36 acct
= nf_conn_acct_find(ct
);
40 counters
= acct
->counter
;
41 switch (sinfo
->what
) {
42 case XT_CONNBYTES_PKTS
:
43 switch (sinfo
->direction
) {
44 case XT_CONNBYTES_DIR_ORIGINAL
:
45 what
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].packets
);
47 case XT_CONNBYTES_DIR_REPLY
:
48 what
= atomic64_read(&counters
[IP_CT_DIR_REPLY
].packets
);
50 case XT_CONNBYTES_DIR_BOTH
:
51 what
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].packets
);
52 what
+= atomic64_read(&counters
[IP_CT_DIR_REPLY
].packets
);
56 case XT_CONNBYTES_BYTES
:
57 switch (sinfo
->direction
) {
58 case XT_CONNBYTES_DIR_ORIGINAL
:
59 what
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].bytes
);
61 case XT_CONNBYTES_DIR_REPLY
:
62 what
= atomic64_read(&counters
[IP_CT_DIR_REPLY
].bytes
);
64 case XT_CONNBYTES_DIR_BOTH
:
65 what
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].bytes
);
66 what
+= atomic64_read(&counters
[IP_CT_DIR_REPLY
].bytes
);
70 case XT_CONNBYTES_AVGPKT
:
71 switch (sinfo
->direction
) {
72 case XT_CONNBYTES_DIR_ORIGINAL
:
73 bytes
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].bytes
);
74 pkts
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].packets
);
76 case XT_CONNBYTES_DIR_REPLY
:
77 bytes
= atomic64_read(&counters
[IP_CT_DIR_REPLY
].bytes
);
78 pkts
= atomic64_read(&counters
[IP_CT_DIR_REPLY
].packets
);
80 case XT_CONNBYTES_DIR_BOTH
:
81 bytes
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].bytes
) +
82 atomic64_read(&counters
[IP_CT_DIR_REPLY
].bytes
);
83 pkts
= atomic64_read(&counters
[IP_CT_DIR_ORIGINAL
].packets
) +
84 atomic64_read(&counters
[IP_CT_DIR_REPLY
].packets
);
88 what
= div64_u64(bytes
, pkts
);
92 if (sinfo
->count
.to
>= sinfo
->count
.from
)
93 return what
<= sinfo
->count
.to
&& what
>= sinfo
->count
.from
;
95 return what
< sinfo
->count
.to
|| what
> sinfo
->count
.from
;
98 static int connbytes_mt_check(const struct xt_mtchk_param
*par
)
100 const struct xt_connbytes_info
*sinfo
= par
->matchinfo
;
103 if (sinfo
->what
!= XT_CONNBYTES_PKTS
&&
104 sinfo
->what
!= XT_CONNBYTES_BYTES
&&
105 sinfo
->what
!= XT_CONNBYTES_AVGPKT
)
108 if (sinfo
->direction
!= XT_CONNBYTES_DIR_ORIGINAL
&&
109 sinfo
->direction
!= XT_CONNBYTES_DIR_REPLY
&&
110 sinfo
->direction
!= XT_CONNBYTES_DIR_BOTH
)
113 ret
= nf_ct_netns_get(par
->net
, par
->family
);
115 pr_info("cannot load conntrack support for proto=%u\n",
119 * This filter cannot function correctly unless connection tracking
120 * accounting is enabled, so complain in the hope that someone notices.
122 if (!nf_ct_acct_enabled(par
->net
)) {
123 pr_warn("Forcing CT accounting to be enabled\n");
124 nf_ct_set_acct(par
->net
, true);
130 static void connbytes_mt_destroy(const struct xt_mtdtor_param
*par
)
132 nf_ct_netns_put(par
->net
, par
->family
);
135 static struct xt_match connbytes_mt_reg __read_mostly
= {
138 .family
= NFPROTO_UNSPEC
,
139 .checkentry
= connbytes_mt_check
,
140 .match
= connbytes_mt
,
141 .destroy
= connbytes_mt_destroy
,
142 .matchsize
= sizeof(struct xt_connbytes_info
),
146 static int __init
connbytes_mt_init(void)
148 return xt_register_match(&connbytes_mt_reg
);
151 static void __exit
connbytes_mt_exit(void)
153 xt_unregister_match(&connbytes_mt_reg
);
156 module_init(connbytes_mt_init
);
157 module_exit(connbytes_mt_exit
);