1 Index: linux-2.4.35.4/net/ipv4/netfilter/Config.in
2 ===================================================================
3 --- linux-2.4.35.4.orig/net/ipv4/netfilter/Config.in
4 +++ linux-2.4.35.4/net/ipv4/netfilter/Config.in
5 @@ -11,6 +11,8 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ];
6 dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
7 dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
8 dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
9 + dep_tristate ' Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK
10 + dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
11 dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
12 dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
14 Index: linux-2.4.35.4/net/ipv4/netfilter/Makefile
15 ===================================================================
16 --- linux-2.4.35.4.orig/net/ipv4/netfilter/Makefile
17 +++ linux-2.4.35.4/net/ipv4/netfilter/Makefile
18 @@ -106,6 +106,7 @@ obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_
19 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
20 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
21 obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
22 +obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
23 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
24 obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
25 obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
26 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_amanda.c
27 ===================================================================
28 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_amanda.c
29 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_amanda.c
30 @@ -75,7 +75,7 @@ static int help(const struct iphdr *iph,
32 /* increase the UDP timeout of the master connection as replies from
33 * Amanda clients to the server can be quite delayed */
34 - ip_ct_refresh(ct, master_timeout * HZ);
35 + ip_ct_refresh_acct(ct,ctinfo,NULL, master_timeout * HZ);
37 /* Search for "CONNECT " string */
39 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
40 ===================================================================
41 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
42 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
43 @@ -211,7 +211,7 @@ static int tcp_packet(struct ip_conntrac
44 set_bit(IPS_ASSURED_BIT, &conntrack->status);
46 WRITE_UNLOCK(&tcp_lock);
47 - ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
48 + ip_ct_refresh_acct(conntrack,ctinfo,iph, *tcp_timeouts[newconntrack]);
52 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_udp.c
53 ===================================================================
54 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c
55 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_udp.c
56 @@ -47,16 +47,16 @@ static unsigned int udp_print_conntrack(
57 /* Returns verdict for packet, and may modify conntracktype */
58 static int udp_packet(struct ip_conntrack *conntrack,
59 struct iphdr *iph, size_t len,
60 - enum ip_conntrack_info conntrackinfo)
61 + enum ip_conntrack_info ctinfo)
63 /* If we've seen traffic both ways, this is some kind of UDP
64 stream. Extend timeout. */
65 if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
66 - ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
67 + ip_ct_refresh_acct(conntrack,ctinfo,iph,ip_ct_udp_timeout_stream);
68 /* Also, more likely to be important, and not a probe */
69 set_bit(IPS_ASSURED_BIT, &conntrack->status);
71 - ip_ct_refresh(conntrack, ip_ct_udp_timeout);
72 + ip_ct_refresh_acct(conntrack,ctinfo,iph, ip_ct_udp_timeout);
76 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_standalone.c
77 ===================================================================
78 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_standalone.c
79 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_standalone.c
80 @@ -79,6 +79,18 @@ print_expect(char *buffer, const struct
84 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
85 + defined(CONFIG_IP_NF_CT_ACCT_MODULE)
87 +print_counters(char *buffer, struct ip_conntrack_counter *counter)
89 + return sprintf(buffer, "packets=%llu bytes=%llu ",
90 + counter->packets, counter->bytes);
93 +#define print_counters(x, y) 0
97 print_conntrack(char *buffer, struct ip_conntrack *conntrack)
99 @@ -98,11 +110,15 @@ print_conntrack(char *buffer, struct ip_
100 len += print_tuple(buffer + len,
101 &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
103 + len += print_counters(buffer + len,
104 + &conntrack->counters[IP_CT_DIR_ORIGINAL]);
105 if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
106 len += sprintf(buffer + len, "[UNREPLIED] ");
107 len += print_tuple(buffer + len,
108 &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
110 + len += print_counters(buffer + len,
111 + &conntrack->counters[IP_CT_DIR_REPLY]);
112 if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
113 len += sprintf(buffer + len, "[ASSURED] ");
114 len += sprintf(buffer + len, "use=%u ",
115 @@ -478,7 +494,7 @@ EXPORT_SYMBOL(ip_conntrack_get);
116 EXPORT_SYMBOL(ip_conntrack_helper_register);
117 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
118 EXPORT_SYMBOL(ip_ct_iterate_cleanup);
119 -EXPORT_SYMBOL(ip_ct_refresh);
120 +EXPORT_SYMBOL(ip_ct_refresh_acct);
121 EXPORT_SYMBOL(ip_ct_find_proto);
122 EXPORT_SYMBOL(__ip_ct_find_proto);
123 EXPORT_SYMBOL(ip_ct_find_helper);
124 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_generic.c
125 ===================================================================
126 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_proto_generic.c
127 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_generic.c
128 @@ -41,9 +41,9 @@ static unsigned int generic_print_conntr
129 /* Returns verdict for packet, or -1 for invalid. */
130 static int established(struct ip_conntrack *conntrack,
131 struct iphdr *iph, size_t len,
132 - enum ip_conntrack_info conntrackinfo)
133 + enum ip_conntrack_info ctinfo)
135 - ip_ct_refresh(conntrack, ip_ct_generic_timeout);
136 + ip_ct_refresh_acct(conntrack, ctinfo,iph,ip_ct_generic_timeout);
140 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
141 ===================================================================
142 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
143 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
144 @@ -82,7 +82,7 @@ static int icmp_packet(struct ip_conntra
145 ct->timeout.function((unsigned long)ct);
147 atomic_inc(&ct->proto.icmp.count);
148 - ip_ct_refresh(ct, ip_ct_icmp_timeout);
149 + ip_ct_refresh_acct(ct,ctinfo,iph, ip_ct_icmp_timeout);
153 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_core.c
154 ===================================================================
155 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_core.c
156 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_core.c
157 @@ -1196,22 +1196,40 @@ void ip_conntrack_helper_unregister(stru
161 +static inline void ct_add_counters(struct ip_conntrack *ct,
162 + enum ip_conntrack_info ctinfo,
163 + const struct iphdr *iph)
165 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
166 + defined(CONFIG_IP_NF_CT_ACCT_MODULE)
168 + ct->counters[CTINFO2DIR(ctinfo)].packets++;
169 + ct->counters[CTINFO2DIR(ctinfo)].bytes +=
170 + ntohs(iph->tot_len);
175 /* Refresh conntrack for this many jiffies. */
176 -void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
177 +void ip_ct_refresh_acct(struct ip_conntrack *ct,
178 + enum ip_conntrack_info ctinfo,
179 + const struct iphdr *iph,
180 + unsigned long extra_jiffies)
182 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
184 WRITE_LOCK(&ip_conntrack_lock);
185 /* If not in hash table, timer will not be active yet */
186 - if (!is_confirmed(ct))
187 + if (!is_confirmed(ct)) {
188 ct->timeout.expires = extra_jiffies;
190 + ct_add_counters(ct, ctinfo,iph);
192 /* Need del_timer for race avoidance (may already be dying). */
193 if (del_timer(&ct->timeout)) {
194 ct->timeout.expires = jiffies + extra_jiffies;
195 add_timer(&ct->timeout);
197 + ct_add_counters(ct, ctinfo, iph);
199 WRITE_UNLOCK(&ip_conntrack_lock);
201 Index: linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack.h
202 ===================================================================
203 --- linux-2.4.35.4.orig/include/linux/netfilter_ipv4/ip_conntrack.h
204 +++ linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack.h
205 @@ -164,6 +164,12 @@ struct ip_conntrack_expect
206 union ip_conntrack_expect_help help;
209 +struct ip_conntrack_counter
215 struct ip_conntrack_helper;
218 @@ -181,6 +187,12 @@ struct ip_conntrack
219 /* Timer function; drops refcnt when it goes off. */
220 struct timer_list timeout;
222 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
223 + defined(CONFIG_IP_NF_CT_ACCT_MODULE)
224 + /* Accounting Information (same cache line as other written members) */
225 + struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
228 /* If we're expecting another related connection, this will be
229 in expected linked list */
230 struct list_head sibling_list;
231 @@ -264,8 +276,10 @@ extern int invert_tuplepr(struct ip_conn
232 const struct ip_conntrack_tuple *orig);
234 /* Refresh conntrack for this many jiffies */
235 -extern void ip_ct_refresh(struct ip_conntrack *ct,
236 - unsigned long extra_jiffies);
237 +extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
238 + enum ip_conntrack_info ctinfo,
239 + const struct iphdr *iph,
240 + unsigned long extra_jiffies);
242 /* These are for NAT. Icky. */
243 /* Call me when a conntrack is destroyed. */
244 Index: linux-2.4.35.4/net/ipv4/netfilter/ipt_connbytes.c
245 ===================================================================
247 +++ linux-2.4.35.4/net/ipv4/netfilter/ipt_connbytes.c
249 +/* Kernel module to match connection tracking byte counter.
250 + * GPL (C) 2002 Martin Devera (devik@cdi.cz).
252 + * 2004-07-20 Harald Welte <laforge at netfilter.org>
253 + * - reimplemented to use per-connection accounting counters
254 + * - add functionality to match number of packets
255 + * - add functionality to match average packet size
256 + * - add support to match directions seperately
258 + * 2004-10-24 Piotr Chytla <pch at fouk.org>
259 + * - Connbytes with per-connection accouting backported to 2.4
263 +#include <linux/module.h>
264 +#include <linux/skbuff.h>
265 +#include <linux/types.h>
266 +#include <linux/netfilter_ipv4/ip_conntrack.h>
267 +#include <linux/netfilter_ipv4/ip_tables.h>
268 +#include <linux/netfilter_ipv4/ipt_connbytes.h>
270 +#include <asm/div64.h>
272 +static u_int64_t mydiv(u_int64_t arg1,u_int32_t arg2)
279 +match(const struct sk_buff *skb,
280 + const struct net_device *in,
281 + const struct net_device *out,
282 + const void *matchinfo,
288 + static u_int64_t what;
289 + const struct ipt_connbytes_info *sinfo = matchinfo;
290 + enum ip_conntrack_info ctinfo;
291 + struct ip_conntrack *ct;
293 + if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)))
294 + return 0; /* no match */
295 + switch (sinfo->what) {
296 + case IPT_CONNBYTES_PKTS:
297 + switch (sinfo->direction) {
298 + case IPT_CONNBYTES_DIR_ORIGINAL:
299 + what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
301 + case IPT_CONNBYTES_DIR_REPLY:
302 + what = ct->counters[IP_CT_DIR_REPLY].packets;
304 + case IPT_CONNBYTES_DIR_BOTH:
305 + what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
306 + what += ct->counters[IP_CT_DIR_REPLY].packets;
310 + case IPT_CONNBYTES_BYTES:
311 + switch (sinfo->direction) {
312 + case IPT_CONNBYTES_DIR_ORIGINAL:
313 + what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
315 + case IPT_CONNBYTES_DIR_REPLY:
316 + what = ct->counters[IP_CT_DIR_REPLY].bytes;
318 + case IPT_CONNBYTES_DIR_BOTH:
319 + what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
320 + what += ct->counters[IP_CT_DIR_REPLY].bytes;
324 + case IPT_CONNBYTES_AVGPKT:
325 + switch (sinfo->direction) {
326 + case IPT_CONNBYTES_DIR_ORIGINAL:
330 + if (ct->counters[IP_CT_DIR_ORIGINAL].packets > 0xfffffffff)
331 + pkts32 = 0xffffffff;
333 + pkts32 = ct->counters[IP_CT_DIR_ORIGINAL].packets;
334 + what = mydiv(ct->counters[IP_CT_DIR_ORIGINAL].bytes,pkts32);
337 + case IPT_CONNBYTES_DIR_REPLY:
341 + if (ct->counters[IP_CT_DIR_REPLY].packets > 0xffffffff)
342 + pkts32 = 0xffffffff;
344 + pkts32 = ct->counters[IP_CT_DIR_REPLY].packets;
345 + what = mydiv(ct->counters[IP_CT_DIR_REPLY].bytes,pkts32);
348 + case IPT_CONNBYTES_DIR_BOTH:
353 + bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
354 + ct->counters[IP_CT_DIR_REPLY].bytes;
355 + pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets +
356 + ct->counters[IP_CT_DIR_REPLY].packets;
357 + if (pkts > 0xffffffff)
358 + pkts32 = 0xffffffff;
361 + what = mydiv(bytes,pkts);
367 + if (sinfo->count.to)
368 + return (what <= sinfo->count.to && what >= sinfo->count.from);
370 + return (what >= sinfo->count.from);
373 +static int check(const char *tablename,
374 + const struct ipt_ip *ip,
376 + unsigned int matchsize,
377 + unsigned int hook_mask)
379 + const struct ipt_connbytes_info *sinfo = matchinfo;
381 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
383 + if (sinfo->what != IPT_CONNBYTES_PKTS &&
384 + sinfo->what != IPT_CONNBYTES_BYTES &&
385 + sinfo->what != IPT_CONNBYTES_AVGPKT)
388 + if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
389 + sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
390 + sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
396 +static struct ipt_match state_match
397 += { { NULL, NULL }, "connbytes", &match, &check, NULL, THIS_MODULE };
399 +static int __init init(void)
401 + return ipt_register_match(&state_match);
404 +static void __exit fini(void)
406 + ipt_unregister_match(&state_match);
411 +MODULE_LICENSE("GPL");
412 Index: linux-2.4.35.4/include/linux/netfilter_ipv4/ipt_connbytes.h
413 ===================================================================
415 +++ linux-2.4.35.4/include/linux/netfilter_ipv4/ipt_connbytes.h
417 +#ifndef _IPT_CONNBYTES_H
418 +#define _IPT_CONNBYTES_H
419 +enum ipt_connbytes_what {
420 + IPT_CONNBYTES_PKTS,
421 + IPT_CONNBYTES_BYTES,
422 + IPT_CONNBYTES_AVGPKT,
425 +enum ipt_connbytes_direction {
426 + IPT_CONNBYTES_DIR_ORIGINAL,
427 + IPT_CONNBYTES_DIR_REPLY,
428 + IPT_CONNBYTES_DIR_BOTH,
431 +struct ipt_connbytes_info
434 + u_int64_t from; /* count to be matched */
435 + u_int64_t to; /* count to be matched */
437 + u_int8_t what; /* ipt_connbytes_what */
438 + u_int8_t direction; /* ipt_connbytes_direction */
442 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_gre.c
443 ===================================================================
444 --- linux-2.4.35.4.orig/net/ipv4/netfilter/ip_conntrack_proto_gre.c
445 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_proto_gre.c
446 @@ -237,16 +237,16 @@ static unsigned int gre_print_conntrack(
447 /* Returns verdict for packet, and may modify conntrack */
448 static int gre_packet(struct ip_conntrack *ct,
449 struct iphdr *iph, size_t len,
450 - enum ip_conntrack_info conntrackinfo)
451 + enum ip_conntrack_info ctinfo)
453 /* If we've seen traffic both ways, this is a GRE connection.
455 if (ct->status & IPS_SEEN_REPLY) {
456 - ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout);
457 + ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.stream_timeout);
458 /* Also, more likely to be important, and not a probe. */
459 set_bit(IPS_ASSURED_BIT, &ct->status);
461 - ip_ct_refresh_acct(ct, ct->proto.gre.timeout);
462 + ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.timeout);