diff options
Diffstat (limited to 'target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch')
-rw-r--r-- | target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch b/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch new file mode 100644 index 000000000..f6f84d320 --- /dev/null +++ b/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch @@ -0,0 +1,417 @@ +--- 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_WHAT_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_WHAT_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_WHAT_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_WHAT_PKTS && ++ sinfo->what != IPT_CONNBYTES_WHAT_BYTES && ++ sinfo->what != IPT_CONNBYTES_WHAT_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_WHAT_PKTS, ++ IPT_CONNBYTES_WHAT_BYTES, ++ IPT_CONNBYTES_WHAT_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 |