diff -Nru a/conntrack-acct/linux-2.4/net/ipv4/netfilter/Config.in.ladd b/conntrack-acct/linux-2.4/net/ipv4/netfilter/Config.in.ladd --- a/conntrack-acct/linux-2.4/net/ipv4/netfilter/Config.in.ladd 1970-01-01 01:00:00.000000000 +0100 +++ b/conntrack-acct/linux-2.4/net/ipv4/netfilter/Config.in.ladd 2004-11-15 22:43:12.000000000 +0100 @@ -0,0 +1,3 @@ + dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK + dep_tristate ' Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK + diff -Nru a/conntrack-acct/linux-2.4.patch b/conntrack-acct/linux-2.4.patch --- a/conntrack-acct/linux-2.4.patch 1970-01-01 01:00:00.000000000 +0100 +++ b/conntrack-acct/linux-2.4.patch 2004-11-15 23:09:20.000000000 +0100 @@ -0,0 +1,210 @@ +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h +--- a/include/linux/netfilter_ipv4/ip_conntrack.h 2004-08-08 01:26:06.000000000 +0200 ++++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-14 20:55:47.000000000 +0100 +@@ -156,6 +156,12 @@ + union ip_conntrack_expect_help help; + }; + ++struct ip_conntrack_counter ++{ ++ u_int64_t packets; ++ u_int64_t bytes; ++}; ++ + struct ip_conntrack_helper; + + struct ip_conntrack +@@ -173,6 +179,12 @@ + /* Timer function; drops refcnt when it goes off. */ + struct timer_list timeout; + ++#if defined(CONFIG_IP_NF_CT_ACCT) || \ ++ defined(CONFIG_IP_NF_CT_ACCT_MODULE) ++ /* Accounting Information (same cache line as other written members) */ ++ struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; ++#endif ++ + /* If we're expecting another related connection, this will be + in expected linked list */ + struct list_head sibling_list; +@@ -242,8 +254,10 @@ + const struct ip_conntrack_tuple *orig); + + /* Refresh conntrack for this many jiffies */ +-extern void ip_ct_refresh(struct ip_conntrack *ct, +- unsigned long extra_jiffies); ++extern void ip_ct_refresh_acct(struct ip_conntrack *ct, ++ enum ip_conntrack_info ctinfo, ++ const struct iphdr *iph, ++ unsigned long extra_jiffies); + + /* These are for NAT. Icky. */ + /* Call me when a conntrack is destroyed. */ +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c +--- a/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-02-18 14:36:32.000000000 +0100 ++++ b/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-11-14 20:29:39.000000000 +0100 +@@ -75,7 +75,7 @@ + + /* increase the UDP timeout of the master connection as replies from + * Amanda clients to the server can be quite delayed */ +- ip_ct_refresh(ct, master_timeout * HZ); ++ ip_ct_refresh_acct(ct,ctinfo,NULL, master_timeout * HZ); + + /* Search for "CONNECT " string */ + do { +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c +--- a/net/ipv4/netfilter/ip_conntrack_core.c 2004-08-08 01:26:06.000000000 +0200 ++++ b/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-14 20:29:52.000000000 +0100 +@@ -1164,21 +1164,40 @@ + MOD_DEC_USE_COUNT; + } + ++static inline void ct_add_counters(struct ip_conntrack *ct, ++ enum ip_conntrack_info ctinfo, ++ const struct iphdr *iph) ++{ ++#if defined(CONFIG_IP_NF_CT_ACCT) || \ ++ defined(CONFIG_IP_NF_CT_ACCT_MODULE) ++ if (iph) { ++ ct->counters[CTINFO2DIR(ctinfo)].packets++; ++ ct->counters[CTINFO2DIR(ctinfo)].bytes += ++ ntohs(iph->tot_len); ++ } ++#endif ++} ++ + /* Refresh conntrack for this many jiffies. */ +-void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies) ++void ip_ct_refresh_acct(struct ip_conntrack *ct, ++ enum ip_conntrack_info ctinfo, ++ const struct iphdr *iph, ++ unsigned long extra_jiffies) + { + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + WRITE_LOCK(&ip_conntrack_lock); + /* If not in hash table, timer will not be active yet */ +- if (!is_confirmed(ct)) ++ if (!is_confirmed(ct)) { + ct->timeout.expires = extra_jiffies; +- else { ++ ct_add_counters(ct, ctinfo,iph); ++ } else { + /* Need del_timer for race avoidance (may already be dying). */ + if (del_timer(&ct->timeout)) { + ct->timeout.expires = jiffies + extra_jiffies; + add_timer(&ct->timeout); + } ++ ct_add_counters(ct, ctinfo, iph); + } + WRITE_UNLOCK(&ip_conntrack_lock); + } +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c +--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2003-11-28 19:26:21.000000000 +0100 ++++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-11-14 20:30:15.000000000 +0100 +@@ -41,9 +41,9 @@ + /* Returns verdict for packet, or -1 for invalid. */ + static int established(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len, +- enum ip_conntrack_info conntrackinfo) ++ enum ip_conntrack_info ctinfo) + { +- ip_ct_refresh(conntrack, ip_ct_generic_timeout); ++ ip_ct_refresh_acct(conntrack, ctinfo,iph,ip_ct_generic_timeout); + return NF_ACCEPT; + } + +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2003-11-28 19:26:21.000000000 +0100 ++++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-11-14 20:30:18.000000000 +0100 +@@ -82,7 +82,7 @@ + ct->timeout.function((unsigned long)ct); + } else { + atomic_inc(&ct->proto.icmp.count); +- ip_ct_refresh(ct, ip_ct_icmp_timeout); ++ ip_ct_refresh_acct(ct,ctinfo,iph, ip_ct_icmp_timeout); + } + + return NF_ACCEPT; +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-11-28 19:26:21.000000000 +0100 ++++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-11-14 20:30:26.000000000 +0100 +@@ -211,7 +211,7 @@ + set_bit(IPS_ASSURED_BIT, &conntrack->status); + + WRITE_UNLOCK(&tcp_lock); +- ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]); ++ ip_ct_refresh_acct(conntrack,ctinfo,iph, *tcp_timeouts[newconntrack]); + } + + return NF_ACCEPT; +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c +--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-11-28 19:26:21.000000000 +0100 ++++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-11-14 20:30:23.000000000 +0100 +@@ -47,16 +47,16 @@ + /* Returns verdict for packet, and may modify conntracktype */ + static int udp_packet(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len, +- enum ip_conntrack_info conntrackinfo) ++ enum ip_conntrack_info ctinfo) + { + /* If we've seen traffic both ways, this is some kind of UDP + stream. Extend timeout. */ + if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { +- ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream); ++ ip_ct_refresh_acct(conntrack,ctinfo,iph,ip_ct_udp_timeout_stream); + /* Also, more likely to be important, and not a probe */ + set_bit(IPS_ASSURED_BIT, &conntrack->status); + } else +- ip_ct_refresh(conntrack, ip_ct_udp_timeout); ++ ip_ct_refresh_acct(conntrack,ctinfo,iph, ip_ct_udp_timeout); + + return NF_ACCEPT; + } +diff -Nru -x '*.orig' -x '*.rej' -x '*.in' a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c +--- a/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-08-08 01:26:06.000000000 +0200 ++++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-14 20:30:30.000000000 +0100 +@@ -79,6 +79,18 @@ + return len; + } + ++#if defined(CONFIG_IP_NF_CT_ACCT) || \ ++ defined(CONFIG_IP_NF_CT_ACCT_MODULE) ++static unsigned int ++print_counters(char *buffer, struct ip_conntrack_counter *counter) ++{ ++ return sprintf(buffer, "packets=%llu bytes=%llu ", ++ counter->packets, counter->bytes); ++} ++#else ++#define print_counters(x, y) 0 ++#endif ++ + static unsigned int + print_conntrack(char *buffer, struct ip_conntrack *conntrack) + { +@@ -98,11 +110,15 @@ + len += print_tuple(buffer + len, + &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, + proto); ++ len += print_counters(buffer + len, ++ &conntrack->counters[IP_CT_DIR_ORIGINAL]); + if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status))) + len += sprintf(buffer + len, "[UNREPLIED] "); + len += print_tuple(buffer + len, + &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple, + proto); ++ len += print_counters(buffer + len, ++ &conntrack->counters[IP_CT_DIR_REPLY]); + if (test_bit(IPS_ASSURED_BIT, &conntrack->status)) + len += sprintf(buffer + len, "[ASSURED] "); + len += sprintf(buffer + len, "use=%u ", +@@ -467,7 +483,7 @@ + EXPORT_SYMBOL(ip_conntrack_helper_register); + EXPORT_SYMBOL(ip_conntrack_helper_unregister); + EXPORT_SYMBOL(ip_ct_selective_cleanup); +-EXPORT_SYMBOL(ip_ct_refresh); ++EXPORT_SYMBOL(ip_ct_refresh_acct); + EXPORT_SYMBOL(ip_ct_find_proto); + EXPORT_SYMBOL(__ip_ct_find_proto); + EXPORT_SYMBOL(ip_ct_find_helper);