add condition, connbytes, string and quota netfilter modules
authorNicolas Thill <nico@openwrt.org>
Sun, 13 Nov 2005 23:26:39 +0000 (23:26 +0000)
committerNicolas Thill <nico@openwrt.org>
Sun, 13 Nov 2005 23:26:39 +0000 (23:26 +0000)
SVN-Revision: 2478

openwrt/target/linux/linux-2.4/config/ar7
openwrt/target/linux/linux-2.4/config/brcm
openwrt/target/linux/linux-2.4/config/x86
openwrt/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch [new file with mode: 0644]
openwrt/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch [new file with mode: 0644]
openwrt/target/linux/linux-2.4/patches/generic/611-netfilter_condition.patch [new file with mode: 0644]
openwrt/target/linux/linux-2.4/patches/generic/612-netfilter_quota.patch [new file with mode: 0644]
openwrt/target/linux/netfilter.mk

index 153ba9bf984ce1616cba2b45faeaee484dfb984a..833d9d3a24cf619a0fbc7e408bc23be448ff867e 100644 (file)
@@ -343,11 +343,14 @@ CONFIG_IP_NF_FTP=y
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
 CONFIG_IP_NF_SET=m
 CONFIG_IP_NF_SET_MAX=256
 CONFIG_IP_NF_SET_HASHSIZE=1024
@@ -364,6 +367,7 @@ CONFIG_IP_NF_MATCH_PKTTYPE=m
 CONFIG_IP_NF_MATCH_MARK=y
 CONFIG_IP_NF_MATCH_MULTIPORT=y
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_CONDITION=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_IPP2P=m
@@ -377,6 +381,7 @@ CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_LAYER7=m
 # CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
@@ -422,6 +427,7 @@ CONFIG_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
 CONFIG_IP6_NF_MATCH_MAC=m
 # CONFIG_IP6_NF_MATCH_RT is not set
 # CONFIG_IP6_NF_MATCH_OPTS is not set
index adff1f56cac4a3afe5d5a6df512c9399d188cd4c..5e7626523ec9eec4935844cbca467ed10b97bec5 100644 (file)
@@ -354,11 +354,14 @@ CONFIG_IP_NF_FTP=y
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
 CONFIG_IP_NF_SET=m
 CONFIG_IP_NF_SET_MAX=256
 CONFIG_IP_NF_SET_HASHSIZE=1024
@@ -375,6 +378,7 @@ CONFIG_IP_NF_MATCH_PKTTYPE=m
 CONFIG_IP_NF_MATCH_MARK=y
 CONFIG_IP_NF_MATCH_MULTIPORT=y
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_CONDITION=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_IPP2P=m
@@ -388,6 +392,7 @@ CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_LAYER7=m
 # CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
@@ -433,6 +438,7 @@ CONFIG_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
 CONFIG_IP6_NF_MATCH_MAC=m
 # CONFIG_IP6_NF_MATCH_RT is not set
 # CONFIG_IP6_NF_MATCH_OPTS is not set
index 2aef35b28b9b4a36b51bc093d3a42ce5e7311667..da27d3c45803c44b506077b6d4ba1d4b0afbdd0b 100644 (file)
@@ -282,16 +282,31 @@ CONFIG_IP_NF_FTP=y
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_IRC=y
+CONFIG_IP_NF_CT_ACCT=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_QUOTA=m
+CONFIG_IP_NF_SET=m
+CONFIG_IP_NF_SET_MAX=256
+CONFIG_IP_NF_SET_HASHSIZE=1024
+CONFIG_IP_NF_MATCH_SET=m
+CONFIG_IP_NF_TARGET_SET=m
+CONFIG_IP_NF_SET_IPMAP=m
+CONFIG_IP_NF_SET_PORTMAP=m
+CONFIG_IP_NF_SET_MACIPMAP=m
+CONFIG_IP_NF_SET_IPHASH=m
+CONFIG_IP_NF_SET_NETHASH=m
+CONFIG_IP_NF_SET_IPTREE=m
 CONFIG_IP_NF_MATCH_MAC=m
 CONFIG_IP_NF_MATCH_PKTTYPE=m
 CONFIG_IP_NF_MATCH_MARK=y
 CONFIG_IP_NF_MATCH_MULTIPORT=y
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_CONDITION=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_IPP2P=m
@@ -305,6 +320,7 @@ CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_STRING=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_LAYER7=m
 # CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
@@ -337,17 +353,6 @@ CONFIG_IP_NF_TARGET_TCPMSS=y
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_SET=m
-CONFIG_IP_NF_SET_MAX=256
-CONFIG_IP_NF_SET_HASHSIZE=1024
-CONFIG_IP_NF_MATCH_SET=m
-CONFIG_IP_NF_TARGET_SET=m
-CONFIG_IP_NF_SET_IPMAP=m
-CONFIG_IP_NF_SET_PORTMAP=m
-CONFIG_IP_NF_SET_MACIPMAP=m
-CONFIG_IP_NF_SET_IPHASH=m
-CONFIG_IP_NF_SET_NETHASH=m
-CONFIG_IP_NF_SET_IPTREE=m
 
 #
 #   IP: Virtual Server Configuration
@@ -361,6 +366,7 @@ CONFIG_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_CONDITION=m
 CONFIG_IP6_NF_MATCH_MAC=m
 # CONFIG_IP6_NF_MATCH_RT is not set
 # CONFIG_IP6_NF_MATCH_OPTS is not set
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch b/openwrt/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch
new file mode 100644 (file)
index 0000000..18f9f97
--- /dev/null
@@ -0,0 +1,265 @@
+--- linux/net/ipv4/netfilter/Config.in.org     2005-11-08 23:11:47.011929664 +0100
++++ linux/net/ipv4/netfilter/Config.in 2005-11-08 23:10:33.329131152 +0100
+@@ -50,6 +50,7 @@
+   fi
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+     dep_tristate '  Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
++    dep_tristate '  String match support (EXPERIMENTAL) ' CONFIG_IP_NF_MATCH_STRING $CONFIG_IP_NF_IPTABLES
+     dep_tristate '  Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
+     dep_tristate '  Layer 7 match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7 $CONFIG_IP_NF_CONNTRACK
+     dep_mbool '  Layer 7 debugging output (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7_DEBUG $CONFIG_IP_NF_MATCH_LAYER7
+--- linux/net/ipv4/netfilter/Makefile.org      2005-11-08 23:11:57.214378656 +0100
++++ linux/net/ipv4/netfilter/Makefile  2005-11-08 23:11:20.980886984 +0100
+@@ -97,6 +97,7 @@
+ 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_STRING) += ipt_string.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+ obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
+--- linux/net/ipv4/netfilter/ipt_string.c      1970-01-01 01:00:00.000000000 +0100
++++ linux/net/ipv4/netfilter/ipt_string.c      2005-11-08 23:08:51.531606728 +0100
+@@ -0,0 +1,218 @@
++/* Kernel module to match a string into a packet.
++ *
++ * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
++ * 
++ * ChangeLog
++ *    19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
++ *            Fixed SMP re-entrancy problem using per-cpu data areas
++ *            for the skip/shift tables.
++ *    02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
++ *            Fixed kernel panic, due to overrunning boyer moore string
++ *            tables. Also slightly tweaked heuristic for deciding what
++ *            search algo to use.
++ *    27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
++ *            Implemented Boyer Moore Sublinear search algorithm
++ *            alongside the existing linear search based on memcmp().
++ *            Also a quick check to decide which method to use on a per
++ *            packet basis.
++ */
++
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/file.h>
++#include <net/sock.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_string.h>
++
++MODULE_LICENSE("GPL");
++
++struct string_per_cpu {
++      int *skip;
++      int *shift;
++      int *len;
++};
++
++struct string_per_cpu *bm_string_data=NULL;
++
++/* Boyer Moore Sublinear string search - VERY FAST */
++char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
++{
++      int M1, right_end, sk, sh;  
++      int ended, j, i;
++
++      int *skip, *shift, *len;
++      
++      /* use data suitable for this CPU */
++      shift=bm_string_data[smp_processor_id()].shift;
++      skip=bm_string_data[smp_processor_id()].skip;
++      len=bm_string_data[smp_processor_id()].len;
++      
++      /* Setup skip/shift tables */
++      M1 = right_end = needle_len-1;
++      for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
++      for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
++
++      for (i = 1; i < needle_len; i++) {   
++              for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
++              len[i] = j;  
++      }  
++
++      shift[0] = 1;  
++      for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
++      for (i = M1; i > 0; i--) shift[len[i]] = i;  
++      ended = 0;  
++      
++      for (i = 0; i < needle_len; i++) {  
++              if (len[i] == M1 - i) ended = i;  
++              if (ended) shift[i] = ended;  
++      }  
++
++      /* Do the search*/  
++      while (right_end < haystack_len)
++      {
++              for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
++              if (i == needle_len) {
++                      return haystack+(right_end - M1);
++              }
++              
++              sk = skip[haystack[right_end - i]];  
++              sh = shift[i];
++              right_end = max(right_end - i + sk, right_end + sh);  
++      }
++
++      return NULL;
++}  
++
++/* Linear string search based on memcmp() */
++char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
++{
++      char *k = haystack + (haystack_len-needle_len);
++      char *t = haystack;
++      
++      while ( t <= k ) {
++              if (memcmp(t, needle, needle_len) == 0)
++                      return t;
++              t++;
++      }
++
++      return NULL;
++}
++
++
++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)
++{
++      const struct ipt_string_info *info = matchinfo;
++      struct iphdr *ip = skb->nh.iph;
++      int hlen, nlen;
++      char *needle, *haystack;
++      proc_ipt_search search=search_linear;
++
++      if ( !ip ) return 0;
++
++      /* get lenghts, and validate them */
++      nlen=info->len;
++      hlen=ntohs(ip->tot_len)-(ip->ihl*4);
++      if ( nlen > hlen ) return 0;
++
++      needle=(char *)&info->string;
++      haystack=(char *)ip+(ip->ihl*4);
++
++      /* The sublinear search comes in to its own
++       * on the larger packets */
++      if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
++              (nlen>IPT_STRING_NEEDLE_THRESH) ) {
++              if ( hlen < BM_MAX_HLEN ) {
++                      search=search_sublinear;
++              }else{
++                      if (net_ratelimit())
++                              printk(KERN_INFO "ipt_string: Packet too big "
++                                      "to attempt sublinear string search "
++                                      "(%d bytes)\n", hlen );
++              }
++      }
++      
++    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
++}
++
++static int
++checkentry(const char *tablename,
++           const struct ipt_ip *ip,
++           void *matchinfo,
++           unsigned int matchsize,
++           unsigned int hook_mask)
++{
++
++       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
++               return 0;
++
++       return 1;
++}
++
++void string_freeup_data(void)
++{
++      int c;
++      
++      if ( bm_string_data ) {
++              for(c=0; c<smp_num_cpus; c++) {
++                      if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
++                      if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
++                      if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
++              }
++              kfree(bm_string_data);
++      }
++}
++
++static struct ipt_match string_match
++= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++      int c;
++      size_t tlen;
++      size_t alen;
++
++      tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
++      alen=sizeof(int)*BM_MAX_HLEN;
++      
++      /* allocate array of structures */
++      if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
++              return 0;
++      }
++      
++      memset(bm_string_data, 0, tlen);
++      
++      /* allocate our skip/shift tables */
++      for(c=0; c<smp_num_cpus; c++) {
++              if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++              if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++              if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++      }
++      
++      return ipt_register_match(&string_match);
++
++alloc_fail:
++      string_freeup_data();
++      return 0;
++}
++
++static void __exit fini(void)
++{
++      ipt_unregister_match(&string_match);
++      string_freeup_data();
++}
++
++module_init(init);
++module_exit(fini);
+--- linux/include/linux/netfilter_ipv4/ipt_string.h    1970-01-01 01:00:00.000000000 +0100
++++ linux/include/linux/netfilter_ipv4/ipt_string.h    2005-11-08 23:09:45.219444936 +0100
+@@ -0,0 +1,21 @@
++#ifndef _IPT_STRING_H
++#define _IPT_STRING_H
++
++/* *** PERFORMANCE TWEAK ***
++ * Packet size and search string threshold,
++ * above which sublinear searches is used. */
++#define IPT_STRING_HAYSTACK_THRESH    100
++#define IPT_STRING_NEEDLE_THRESH      20
++
++#define BM_MAX_NLEN 256
++#define BM_MAX_HLEN 1024
++
++typedef char *(*proc_ipt_search) (char *, char *, int, int);
++
++struct ipt_string_info {
++    char string[BM_MAX_NLEN];
++    u_int16_t invert;
++    u_int16_t len;
++};
++
++#endif /* _IPT_STRING_H */
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch b/openwrt/target/linux/linux-2.4/patches/generic/610-netfilter_connbytes.patch
new file mode 100644 (file)
index 0000000..f6f84d3
--- /dev/null
@@ -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
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/611-netfilter_condition.patch b/openwrt/target/linux/linux-2.4/patches/generic/611-netfilter_condition.patch
new file mode 100644 (file)
index 0000000..6c16c29
--- /dev/null
@@ -0,0 +1,625 @@
+diff -ruN linux-2.4.30-old/Documentation/Configure.help linux-2.4.30-new/Documentation/Configure.help
+--- linux-2.4.30-old/Documentation/Configure.help      2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/Documentation/Configure.help      2005-11-13 22:20:15.000000000 +0100
+@@ -2979,6 +2979,14 @@
+   If you want to compile it as a module, say M here and read
+   <file:Documentation/modules.txt>.  If unsure, say `N'.
++Condition variable match support
++CONFIG_IP_NF_MATCH_CONDITION
++  This option allows you to match firewall rules against condition
++  variables stored in the /proc/net/ipt_condition directory.
++
++  If you want to compile it as a module, say M here and read
++  Documentation/modules.txt.  If unsure, say `N'.
++
+ conntrack match support
+ CONFIG_IP_NF_MATCH_CONNTRACK
+   This is a general conntrack match module, a superset of the state match.
+@@ -3354,6 +3362,14 @@
+   If you want to compile it as a module, say M here and read
+   <file:Documentation/modules.txt>.  If unsure, say `N'.
++Condition variable match support
++CONFIG_IP6_NF_MATCH_CONDITION
++  This option allows you to match firewall rules against condition
++  variables stored in the /proc/net/ipt_condition directory.
++
++  If you want to compile it as a module, say M here and read
++  Documentation/modules.txt.  If unsure, say `N'.
++
+ Multiple port match support
+ CONFIG_IP6_NF_MATCH_MULTIPORT
+   Multiport matching allows you to match TCP or UDP packets based on
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_condition.h linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_condition.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_condition.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_condition.h      2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,11 @@
++#ifndef __IPT_CONDITION_MATCH__
++#define __IPT_CONDITION_MATCH__
++
++#define CONDITION_NAME_LEN  32
++
++struct condition_info {
++      char name[CONDITION_NAME_LEN];
++      int  invert;
++};
++
++#endif
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.4.30-new/include/linux/netfilter_ipv6/ip6t_condition.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv6/ip6t_condition.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv6/ip6t_condition.h     2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,11 @@
++#ifndef __IP6T_CONDITION_MATCH__
++#define __IP6T_CONDITION_MATCH__
++
++#define CONDITION6_NAME_LEN  32
++
++struct condition6_info {
++      char name[CONDITION6_NAME_LEN];
++      int  invert;
++};
++
++#endif
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Config.in linux-2.4.30-new/net/ipv4/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv4/netfilter/Config.in      2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Config.in      2005-11-13 22:20:15.000000000 +0100
+@@ -43,6 +43,7 @@
+   dep_tristate '  netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
++  dep_tristate '  condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Makefile linux-2.4.30-new/net/ipv4/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv4/netfilter/Makefile       2005-11-13 21:52:27.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Makefile       2005-11-13 22:20:15.000000000 +0100
+@@ -94,6 +94,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
++obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
+ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/ipt_condition.c linux-2.4.30-new/net/ipv4/netfilter/ipt_condition.c
+--- linux-2.4.30-old/net/ipv4/netfilter/ipt_condition.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/ipt_condition.c        2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,256 @@
++/*-------------------------------------------*\
++|          Netfilter Condition Module         |
++|                                             |
++|  Description: This module allows firewall   |
++|    rules to match using condition variables |
++|    stored in /proc files.                   |
++|                                             |
++|  Author: Stephane Ouellette     2002-10-22  |
++|          <ouellettes@videotron.ca>          |
++|                                             |
++|  History:                                   |
++|    2003-02-10  Second version with improved |
++|                locking and simplified code. |
++|                                             |
++|  This software is distributed under the     |
++|  terms of the GNU GPL.                      |
++\*-------------------------------------------*/
++
++#include<linux/module.h>
++#include<linux/proc_fs.h>
++#include<linux/spinlock.h>
++#include<linux/string.h>
++#include<asm/atomic.h>
++#include<linux/netfilter_ipv4/ip_tables.h>
++#include<linux/netfilter_ipv4/ipt_condition.h>
++
++
++#ifndef CONFIG_PROC_FS
++#error  "Proc file system support is required for this module"
++#endif
++
++
++MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
++MODULE_DESCRIPTION("Allows rules to match against condition variables");
++MODULE_LICENSE("GPL");
++
++
++struct condition_variable {
++      struct condition_variable *next;
++      struct proc_dir_entry *status_proc;
++      atomic_t refcount;
++        int enabled;   /* TRUE == 1, FALSE == 0 */
++};
++
++
++static rwlock_t list_lock;
++static struct condition_variable *head = NULL;
++static struct proc_dir_entry *proc_net_condition = NULL;
++
++
++static int
++ipt_condition_read_info(char *buffer, char **start, off_t offset,
++                      int length, int *eof, void *data)
++{
++      struct condition_variable *var =
++          (struct condition_variable *) data;
++
++      if (offset == 0) {
++              *start = buffer;
++              buffer[0] = (var->enabled) ? '1' : '0';
++              buffer[1] = '\n';
++              return 2;
++      }
++
++      *eof = 1;
++      return 0;
++}
++
++
++static int
++ipt_condition_write_info(struct file *file, const char *buffer,
++                       unsigned long length, void *data)
++{
++      struct condition_variable *var =
++          (struct condition_variable *) data;
++
++      if (length) {
++              /* Match only on the first character */
++              switch (buffer[0]) {
++              case '0':
++                      var->enabled = 0;
++                      break;
++              case '1':
++                      var->enabled = 1;
++              }
++      }
++
++      return (int) length;
++}
++
++
++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)
++{
++      const struct condition_info *info =
++          (const struct condition_info *) matchinfo;
++      struct condition_variable *var;
++      int condition_status = 0;
++
++      read_lock(&list_lock);
++
++      for (var = head; var; var = var->next) {
++              if (strcmp(info->name, var->status_proc->name) == 0) {
++                      condition_status = var->enabled;
++                      break;
++              }
++      }
++
++      read_unlock(&list_lock);
++
++      return condition_status ^ info->invert;
++}
++
++
++
++static int
++checkentry(const char *tablename, const struct ipt_ip *ip,
++         void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++      struct condition_info *info = (struct condition_info *) matchinfo;
++      struct condition_variable *var, *newvar;
++
++      if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
++              return 0;
++
++      /* The first step is to check if the condition variable already exists. */
++      /* Here, a read lock is sufficient because we won't change the list */
++      read_lock(&list_lock);
++
++      for (var = head; var; var = var->next) {
++              if (strcmp(info->name, var->status_proc->name) == 0) {
++                      atomic_inc(&var->refcount);
++                      read_unlock(&list_lock);
++                      return 1;
++              }
++      }
++
++      read_unlock(&list_lock);
++
++      /* At this point, we need to allocate a new condition variable */
++      newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
++
++      if (!newvar)
++              return -ENOMEM;
++
++      /* Create the condition variable's proc file entry */
++      newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
++
++      if (!newvar->status_proc) {
++        /*
++         * There are two possibilities:
++         *  1- Another condition variable with the same name has been created, which is valid.
++         *  2- There was a memory allocation error.
++         */
++              kfree(newvar);
++              read_lock(&list_lock);
++
++              for (var = head; var; var = var->next) {
++                      if (strcmp(info->name, var->status_proc->name) == 0) {
++                              atomic_inc(&var->refcount);
++                              read_unlock(&list_lock);
++                              return 1;
++                      }
++              }
++
++              read_unlock(&list_lock);
++              return -ENOMEM;
++      }
++
++      atomic_set(&newvar->refcount, 1);
++      newvar->enabled = 0;
++      newvar->status_proc->owner = THIS_MODULE;
++      newvar->status_proc->data = newvar;
++      wmb();
++      newvar->status_proc->read_proc = ipt_condition_read_info;
++      newvar->status_proc->write_proc = ipt_condition_write_info;
++
++      write_lock(&list_lock);
++
++      newvar->next = head;
++      head = newvar;
++
++      write_unlock(&list_lock);
++
++      return 1;
++}
++
++
++static void
++destroy(void *matchinfo, unsigned int matchsize)
++{
++      struct condition_info *info = (struct condition_info *) matchinfo;
++      struct condition_variable *var, *prev = NULL;
++
++      if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
++              return;
++
++      write_lock(&list_lock);
++
++      for (var = head; var && strcmp(info->name, var->status_proc->name);
++           prev = var, var = var->next);
++
++      if (var && atomic_dec_and_test(&var->refcount)) {
++              if (prev)
++                      prev->next = var->next;
++              else
++                      head = var->next;
++
++              write_unlock(&list_lock);
++              remove_proc_entry(var->status_proc->name, proc_net_condition);
++              kfree(var);
++      } else
++              write_unlock(&list_lock);
++}
++
++
++static struct ipt_match condition_match = {
++      .name = "condition",
++      .match = &match,
++      .checkentry = &checkentry,
++      .destroy = &destroy,
++      .me = THIS_MODULE
++};
++
++
++static int __init
++init(void)
++{
++      int errorcode;
++
++      rwlock_init(&list_lock);
++      proc_net_condition = proc_mkdir("ipt_condition", proc_net);
++
++      if (proc_net_condition) {
++              errorcode = ipt_register_match(&condition_match);
++
++              if (errorcode)
++                      remove_proc_entry("ipt_condition", proc_net);
++      } else
++              errorcode = -EACCES;
++
++      return errorcode;
++}
++
++
++static void __exit
++fini(void)
++{
++      ipt_unregister_match(&condition_match);
++      remove_proc_entry("ipt_condition", proc_net);
++}
++
++module_init(init);
++module_exit(fini);
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/Config.in linux-2.4.30-new/net/ipv6/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv6/netfilter/Config.in      2003-06-13 16:51:39.000000000 +0200
++++ linux-2.4.30-new/net/ipv6/netfilter/Config.in      2005-11-13 22:20:15.000000000 +0100
+@@ -17,6 +17,7 @@
+ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
+ # The simple matches.
+   dep_tristate '  limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
++  dep_tristate '  condition match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES
+   dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+     dep_tristate '  Routing header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_RT $CONFIG_IP6_NF_IPTABLES
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/Makefile linux-2.4.30-new/net/ipv6/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv6/netfilter/Makefile       2003-06-13 16:51:39.000000000 +0200
++++ linux-2.4.30-new/net/ipv6/netfilter/Makefile       2005-11-13 22:20:15.000000000 +0100
+@@ -14,6 +14,7 @@
+ # Link order matters here.
+ obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
+ obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
++obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
+ obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
+ obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
+ obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
+diff -ruN linux-2.4.30-old/net/ipv6/netfilter/ip6t_condition.c linux-2.4.30-new/net/ipv6/netfilter/ip6t_condition.c
+--- linux-2.4.30-old/net/ipv6/netfilter/ip6t_condition.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv6/netfilter/ip6t_condition.c       2005-11-13 22:20:14.000000000 +0100
+@@ -0,0 +1,254 @@
++/*-------------------------------------------*\
++|    Netfilter Condition Module for IPv6      |
++|                                             |
++|  Description: This module allows firewall   |
++|    rules to match using condition variables |
++|    stored in /proc files.                   |
++|                                             |
++|  Author: Stephane Ouellette     2003-02-10  |
++|          <ouellettes@videotron.ca>          |
++|                                             |
++|  This software is distributed under the     |
++|  terms of the GNU GPL.                      |
++\*-------------------------------------------*/
++
++#include<linux/module.h>
++#include<linux/proc_fs.h>
++#include<linux/spinlock.h>
++#include<linux/string.h>
++#include<asm/atomic.h>
++#include<linux/netfilter_ipv6/ip6_tables.h>
++#include<linux/netfilter_ipv6/ip6t_condition.h>
++
++
++#ifndef CONFIG_PROC_FS
++#error  "Proc file system support is required for this module"
++#endif
++
++
++MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
++MODULE_DESCRIPTION("Allows rules to match against condition variables");
++MODULE_LICENSE("GPL");
++
++
++struct condition_variable {
++      struct condition_variable *next;
++      struct proc_dir_entry *status_proc;
++      atomic_t refcount;
++        int enabled; /* TRUE == 1, FALSE == 0 */
++};
++
++
++static rwlock_t list_lock;
++static struct condition_variable *head = NULL;
++static struct proc_dir_entry *proc_net_condition = NULL;
++
++
++static int
++ipt_condition_read_info(char *buffer, char **start, off_t offset,
++                      int length, int *eof, void *data)
++{
++      struct condition_variable *var =
++          (struct condition_variable *) data;
++
++      if (offset == 0) {
++              *start = buffer;
++              buffer[0] = (var->enabled) ? '1' : '0';
++              buffer[1] = '\n';
++              return 2;
++      }
++
++      *eof = 1;
++      return 0;
++}
++
++
++static int
++ipt_condition_write_info(struct file *file, const char *buffer,
++                       unsigned long length, void *data)
++{
++      struct condition_variable *var =
++          (struct condition_variable *) data;
++
++      if (length) {
++              /* Match only on the first character */
++              switch (buffer[0]) {
++              case '0':
++                      var->enabled = 0;
++                      break;
++              case '1':
++                      var->enabled = 1;
++              }
++      }
++
++      return (int) length;
++}
++
++
++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)
++{
++      const struct condition6_info *info =
++          (const struct condition6_info *) matchinfo;
++      struct condition_variable *var;
++      int condition_status = 0;
++
++      read_lock(&list_lock);
++
++      for (var = head; var; var = var->next) {
++              if (strcmp(info->name, var->status_proc->name) == 0) {
++                      condition_status = var->enabled;
++                      break;
++              }
++      }
++
++      read_unlock(&list_lock);
++
++      return condition_status ^ info->invert;
++}
++
++
++
++static int
++checkentry(const char *tablename, const struct ip6t_ip6 *ip,
++         void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++      struct condition6_info *info =
++          (struct condition6_info *) matchinfo;
++      struct condition_variable *var, *newvar;
++
++      if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
++              return 0;
++
++      /* The first step is to check if the condition variable already exists. */
++      /* Here, a read lock is sufficient because we won't change the list */
++      read_lock(&list_lock);
++
++      for (var = head; var; var = var->next) {
++              if (strcmp(info->name, var->status_proc->name) == 0) {
++                      atomic_inc(&var->refcount);
++                      read_unlock(&list_lock);
++                      return 1;
++              }
++      }
++
++      read_unlock(&list_lock);
++
++      /* At this point, we need to allocate a new condition variable */
++      newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
++
++      if (!newvar)
++              return -ENOMEM;
++
++      /* Create the condition variable's proc file entry */
++      newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
++
++      if (!newvar->status_proc) {
++        /*
++         * There are two possibilities:
++         *  1- Another condition variable with the same name has been created, which is valid.
++         *  2- There was a memory allocation error.
++         */
++              kfree(newvar);
++              read_lock(&list_lock);
++
++              for (var = head; var; var = var->next) {
++                      if (strcmp(info->name, var->status_proc->name) == 0) {
++                              atomic_inc(&var->refcount);
++                              read_unlock(&list_lock);
++                              return 1;
++                      }
++              }
++
++              read_unlock(&list_lock);
++              return -ENOMEM;
++      }
++
++      atomic_set(&newvar->refcount, 1);
++      newvar->enabled = 0;
++      newvar->status_proc->owner = THIS_MODULE;
++      newvar->status_proc->data = newvar;
++      wmb();
++      newvar->status_proc->read_proc = ipt_condition_read_info;
++      newvar->status_proc->write_proc = ipt_condition_write_info;
++
++      write_lock(&list_lock);
++
++      newvar->next = head;
++      head = newvar;
++
++      write_unlock(&list_lock);
++
++      return 1;
++}
++
++
++static void
++destroy(void *matchinfo, unsigned int matchsize)
++{
++      struct condition6_info *info =
++          (struct condition6_info *) matchinfo;
++      struct condition_variable *var, *prev = NULL;
++
++      if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
++              return;
++
++      write_lock(&list_lock);
++
++      for (var = head; var && strcmp(info->name, var->status_proc->name);
++           prev = var, var = var->next);
++
++      if (var && atomic_dec_and_test(&var->refcount)) {
++              if (prev)
++                      prev->next = var->next;
++              else
++                      head = var->next;
++
++              write_unlock(&list_lock);
++              remove_proc_entry(var->status_proc->name, proc_net_condition);
++              kfree(var);
++      } else
++              write_unlock(&list_lock);
++}
++
++
++static struct ip6t_match condition_match = {
++      .name = "condition",
++      .match = &match,
++      .checkentry = &checkentry,
++      .destroy = &destroy,
++      .me = THIS_MODULE
++};
++
++
++static int __init
++init(void)
++{
++      int errorcode;
++
++      rwlock_init(&list_lock);
++      proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
++
++      if (proc_net_condition) {
++              errorcode = ipt_register_match(&condition_match);
++
++              if (errorcode)
++                      remove_proc_entry("ip6t_condition", proc_net);
++      } else
++              errorcode = -EACCES;
++
++      return errorcode;
++}
++
++
++static void __exit
++fini(void)
++{
++      ipt_unregister_match(&condition_match);
++      remove_proc_entry("ip6t_condition", proc_net);
++}
++
++module_init(init);
++module_exit(fini);
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/612-netfilter_quota.patch b/openwrt/target/linux/linux-2.4/patches/generic/612-netfilter_quota.patch
new file mode 100644 (file)
index 0000000..a0a019c
--- /dev/null
@@ -0,0 +1,147 @@
+diff -ruN linux-2.4.30-old/Documentation/Configure.help linux-2.4.30-new/Documentation/Configure.help
+--- linux-2.4.30-old/Documentation/Configure.help      2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/Documentation/Configure.help      2005-11-13 22:31:17.000000000 +0100
+@@ -2888,6 +2888,13 @@
+   If you want to compile it as a module, say M here and read
+   <file:Documentation/modules.txt>.  If unsure, say `N'.
++quota match support
++CONFIG_IP_NF_MATCH_QUOTA
++  This match implements network quotas.
++
++  If you want to compile it as a module, say M here and read
++  Documentation/modules.txt.  If unsure, say `N'.
++
+ skb->pkt_type packet match support
+ CONFIG_IP_NF_MATCH_PKTTYPE
+   This patch allows you to match packet in accrodance
+diff -ruN linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_quota.h linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_quota.h
+--- linux-2.4.30-old/include/linux/netfilter_ipv4/ipt_quota.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/include/linux/netfilter_ipv4/ipt_quota.h  2005-11-13 22:31:17.000000000 +0100
+@@ -0,0 +1,12 @@
++#ifndef _IPT_QUOTA_H
++#define _IPT_QUOTA_H
++
++/* print debug info in both kernel/netfilter module & iptable library */
++//#define DEBUG_IPT_QUOTA
++
++struct ipt_quota_info {
++        u_int64_t quota;
++      struct ipt_quota_info *master;
++};
++
++#endif /*_IPT_QUOTA_H*/
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Config.in linux-2.4.30-new/net/ipv4/netfilter/Config.in
+--- linux-2.4.30-old/net/ipv4/netfilter/Config.in      2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Config.in      2005-11-13 22:31:17.000000000 +0100
+@@ -24,6 +24,7 @@
+ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
+ # The simple matches.
+   dep_tristate '  limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
++  dep_tristate '  quota match support' CONFIG_IP_NF_MATCH_QUOTA $CONFIG_IP_NF_IPTABLES
+   dep_tristate '  IP set support' CONFIG_IP_NF_SET $CONFIG_IP_NF_IPTABLES
+   if [ "$CONFIG_IP_NF_SET" != "n" ]; then
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/Makefile linux-2.4.30-new/net/ipv4/netfilter/Makefile
+--- linux-2.4.30-old/net/ipv4/netfilter/Makefile       2005-11-13 22:30:42.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/Makefile       2005-11-13 22:31:17.000000000 +0100
+@@ -74,6 +74,7 @@
+ # matches
+ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
++obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
+ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
+ obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
+diff -ruN linux-2.4.30-old/net/ipv4/netfilter/ipt_quota.c linux-2.4.30-new/net/ipv4/netfilter/ipt_quota.c
+--- linux-2.4.30-old/net/ipv4/netfilter/ipt_quota.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-new/net/ipv4/netfilter/ipt_quota.c    2005-11-13 22:31:17.000000000 +0100
+@@ -0,0 +1,88 @@
++/* 
++ * netfilter module to enforce network quotas
++ *
++ * Sam Johnston <samj@samj.net>
++ *
++ * 30/01/05: Fixed on SMP --Pablo Neira <pablo@eurodev.net>
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_quota.h>
++
++MODULE_LICENSE("GPL");
++
++static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
++
++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)
++{
++      struct ipt_quota_info *q =
++              ((struct ipt_quota_info *) matchinfo)->master;
++
++        spin_lock_bh(&quota_lock);
++
++        if (q->quota >= datalen) {
++                /* we can afford this one */
++                q->quota -= datalen;
++                spin_unlock_bh(&quota_lock);
++
++#ifdef DEBUG_IPT_QUOTA
++                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
++#endif
++                return 1;
++        }
++
++        /* so we do not allow even small packets from now on */
++        q->quota = 0;
++
++#ifdef DEBUG_IPT_QUOTA
++        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
++#endif
++
++        spin_unlock_bh(&quota_lock);
++        return 0;
++}
++
++static int
++checkentry(const char *tablename,
++           const struct ipt_ip *ip,
++           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
++{
++        /* TODO: spinlocks? sanity checks? */
++      struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
++
++        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
++                return 0;
++      
++      /* For SMP, we only want to use one set of counters. */
++      q->master = q;
++
++        return 1;
++}
++
++static struct ipt_match quota_match
++    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init
++init(void)
++{
++        return ipt_register_match(&quota_match);
++}
++
++static void __exit
++fini(void)
++{
++        ipt_unregister_match(&quota_match);
++}
++
++module_init(init);
++module_exit(fini);
++
index 3882a5ccb62a38960aed796103bbd5da0ffe8973..a625fb9336c8a795a980f7d8f07bea0b5b1026fd 100644 (file)
@@ -12,14 +12,18 @@ IPKG_KMOD_IPT_CONNTRACK-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK
 IPKG_KMOD_IPT_CONNTRACK-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state
 
 IPKG_KMOD_IPT_EXTRA-m :=
+IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition
+IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_MULTIPORT) += multiport
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype
+IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent
 IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT
+IPKG_KMOD_IPT_EXTRA-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string
 
 IPKG_KMOD_IPT_FILTER-m :=
 IPKG_KMOD_IPT_FILTER-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p
@@ -81,14 +85,18 @@ IPKG_IPTABLES_MOD_CONNTRACK-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper
 IPKG_IPTABLES_MOD_CONNTRACK-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state
 
 IPKG_IPTABLES_MOD_EXTRA-m :=
+IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition
+IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype
+IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent
 IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT
+IPKG_IPTABLES_MOD_EXTRA-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string
 
 IPKG_IPTABLES_MOD_FILTER-m :=
 IPKG_IPTABLES_MOD_FILTER-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p