aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic-2.4/patches/610-netfilter_connbytes.patch')
-rw-r--r--target/linux/generic-2.4/patches/610-netfilter_connbytes.patch439
1 files changed, 439 insertions, 0 deletions
diff --git a/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch
new file mode 100644
index 0000000000..95bc10f2bc
--- /dev/null
+++ b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch
@@ -0,0 +1,439 @@
+--- linux/net/ipv4/netfilter/Config.in.org 2005-11-13 15:53:59.457222512 +0100
++++ linux/net/ipv4/netfilter/Config.in 2005-11-13 15:56:25.241060000 +0100
+@@ -11,6 +11,8 @@
+ dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
+ 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
++ dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ fi
+--- linux/net/ipv4/netfilter/Makefile.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/Makefile 2005-11-13 15:56:38.663019552 +0100
+@@ -94,6 +94,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
++obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+--- linux/net/ipv4/netfilter/ip_conntrack_amanda.c.org 2004-02-18 14:36:32.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_amanda.c 2005-11-13 15:40:00.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 {
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-11-13 15:45:41.045992536 +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;
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2005-11-13 15:47:38.348159896 +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;
+ }
+--- linux/net/ipv4/netfilter/ip_conntrack_standalone.c.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-11-13 15:51:07.608347512 +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 ",
+@@ -478,7 +494,7 @@
+ EXPORT_SYMBOL(ip_conntrack_helper_register);
+ EXPORT_SYMBOL(ip_conntrack_helper_unregister);
+ EXPORT_SYMBOL(ip_ct_iterate_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);
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2005-11-13 15:44:20.734201784 +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;
+ }
+
+--- linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c.org 2003-11-28 19:26:21.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2005-11-13 15:44:50.733641176 +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;
+--- linux/net/ipv4/netfilter/ip_conntrack_core.c.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/net/ipv4/netfilter/ip_conntrack_core.c 2005-11-13 15:43:23.882844504 +0100
+@@ -1196,22 +1196,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);
+ }
+--- linux/include/linux/netfilter_ipv4/ip_conntrack.h.org 2005-11-12 16:48:38.000000000 +0100
++++ linux/include/linux/netfilter_ipv4/ip_conntrack.h 2005-11-13 15:39:04.000000000 +0100
+@@ -164,6 +164,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
+@@ -181,6 +187,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;
+@@ -264,8 +276,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. */
+--- linux/net/ipv4/netfilter/ipt_connbytes.c.org 1970-01-01 01:00:00.000000000 +0100
++++ linux/net/ipv4/netfilter/ipt_connbytes.c 2005-11-13 16:22:02.021433872 +0100
+@@ -0,0 +1,163 @@
++/* Kernel module to match connection tracking byte counter.
++ * GPL (C) 2002 Martin Devera (devik@cdi.cz).
++ *
++ * 2004-07-20 Harald Welte <laforge at netfilter.org>
++ * - reimplemented to use per-connection accounting counters
++ * - add functionality to match number of packets
++ * - add functionality to match average packet size
++ * - add support to match directions seperately
++ *
++ * 2004-10-24 Piotr Chytla <pch at fouk.org>
++ * - Connbytes with per-connection accouting backported to 2.4
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/types.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_connbytes.h>
++
++#include <asm/div64.h>
++
++static u_int64_t mydiv(u_int64_t arg1,u_int32_t arg2)
++{
++ do_div(arg1,arg2);
++ return arg1;
++}
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ static u_int64_t what;
++ const struct ipt_connbytes_info *sinfo = matchinfo;
++ enum ip_conntrack_info ctinfo;
++ struct ip_conntrack *ct;
++
++ if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)))
++ return 0; /* no match */
++ switch (sinfo->what) {
++ case IPT_CONNBYTES_PKTS:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ what = ct->counters[IP_CT_DIR_REPLY].packets;
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ what += ct->counters[IP_CT_DIR_REPLY].packets;
++ break;
++ }
++ break;
++ case IPT_CONNBYTES_BYTES:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ what = ct->counters[IP_CT_DIR_REPLY].bytes;
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
++ what += ct->counters[IP_CT_DIR_REPLY].bytes;
++ break;
++ }
++ break;
++ case IPT_CONNBYTES_AVGPKT:
++ switch (sinfo->direction) {
++ case IPT_CONNBYTES_DIR_ORIGINAL:
++ {
++ u_int32_t pkts32;
++
++ if (ct->counters[IP_CT_DIR_ORIGINAL].packets > 0xfffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = ct->counters[IP_CT_DIR_ORIGINAL].packets;
++ what = mydiv(ct->counters[IP_CT_DIR_ORIGINAL].bytes,pkts32);
++ }
++ break;
++ case IPT_CONNBYTES_DIR_REPLY:
++ {
++ u_int32_t pkts32;
++
++ if (ct->counters[IP_CT_DIR_REPLY].packets > 0xffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = ct->counters[IP_CT_DIR_REPLY].packets;
++ what = mydiv(ct->counters[IP_CT_DIR_REPLY].bytes,pkts32);
++ }
++ break;
++ case IPT_CONNBYTES_DIR_BOTH:
++ {
++ u_int64_t bytes;
++ u_int64_t pkts;
++ u_int32_t pkts32;
++ bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
++ ct->counters[IP_CT_DIR_REPLY].bytes;
++ pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets +
++ ct->counters[IP_CT_DIR_REPLY].packets;
++ if (pkts > 0xffffffff)
++ pkts32 = 0xffffffff;
++ else
++ pkts32 = pkts;
++ what = mydiv(bytes,pkts);
++ }
++ break;
++ }
++ break;
++ }
++ if (sinfo->count.to)
++ return (what <= sinfo->count.to && what >= sinfo->count.from);
++ else
++ return (what >= sinfo->count.from);
++}
++
++static int check(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ const struct ipt_connbytes_info *sinfo = matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
++ return 0;
++ if (sinfo->what != IPT_CONNBYTES_PKTS &&
++ sinfo->what != IPT_CONNBYTES_BYTES &&
++ sinfo->what != IPT_CONNBYTES_AVGPKT)
++ return 0;
++
++ if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
++ sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
++ sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
++ return 0;
++
++ return 1;
++}
++
++static struct ipt_match state_match
++= { { NULL, NULL }, "connbytes", &match, &check, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++ return ipt_register_match(&state_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&state_match);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+--- linux/include/linux/netfilter_ipv4/ipt_connbytes.h.org 1970-01-01 01:00:00.000000000 +0100
++++ linux/include/linux/netfilter_ipv4/ipt_connbytes.h 2005-11-13 16:11:24.567341624 +0100
+@@ -0,0 +1,25 @@
++#ifndef _IPT_CONNBYTES_H
++#define _IPT_CONNBYTES_H
++enum ipt_connbytes_what {
++ IPT_CONNBYTES_PKTS,
++ IPT_CONNBYTES_BYTES,
++ IPT_CONNBYTES_AVGPKT,
++};
++
++enum ipt_connbytes_direction {
++ IPT_CONNBYTES_DIR_ORIGINAL,
++ IPT_CONNBYTES_DIR_REPLY,
++ IPT_CONNBYTES_DIR_BOTH,
++};
++
++struct ipt_connbytes_info
++{
++ struct {
++ u_int64_t from; /* count to be matched */
++ u_int64_t to; /* count to be matched */
++ } count;
++ u_int8_t what; /* ipt_connbytes_what */
++ u_int8_t direction; /* ipt_connbytes_direction */
++};
++
++#endif
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2006-02-04 19:16:25.000000000 +0100
++++ /home/florian//openwrt/trunk/openwrt/build_mipsel/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2006-02-04 18:19:08.000000000 +0100
+@@ -237,16 +237,16 @@
+ /* Returns verdict for packet, and may modify conntrack */
+ static int gre_packet(struct ip_conntrack *ct,
+ 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 a GRE connection.
+ * Extend timeout. */
+ if (ct->status & IPS_SEEN_REPLY) {
+- ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout);
++ ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.stream_timeout);
+ /* Also, more likely to be important, and not a probe. */
+ set_bit(IPS_ASSURED_BIT, &ct->status);
+ } else
+- ip_ct_refresh_acct(ct, ct->proto.gre.timeout);
++ ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.timeout);
+
+ return NF_ACCEPT;
+ }